先看看Demo:

講到頁籤(Tabs)功能時,大多會想到用JavaScript去做,像知名的前端框架:Bootstrap所提供的Tab元件,就是用jQuery實作的(其實網路上有很多用jQuery開發的Tab UI);但其實不用jQuery或JavaScript技術,就能實作高效能且易維護的Tabs元件,讓我們來看看是怎麼辦到的:

規劃HTML結構

  1. 通常我們會用List element來製作頁籤的介面,每個<li>代表用來包含一組頁籤與其對應的內容區塊。
  2. 接下來加入頁籤,頁籤必須使用<label>元素才能實作我們要的功能,原因待會會講,是這篇實作的核心技巧之一。
  3. 內容區塊則是<div>元素。
  4. 再來我們為每個<label>前面加上表單元件Radio button,結果如下:
  <ul class="tabs">
  <li>
    <input type="radio" name="tabs">
    <label class="tab">頁籤A</label>
    <div class="section">這是內文A</div>
  </li>
  <li>
    <input type="radio" name="tabs">
    <label class="tab">頁籤B</label>
    <div class="section">這是內文B</div>
  </li>
  <li>
    <input type="radio" name="tabs">
    <label class="tab">頁籤C</label>
    <div class="section">這是內文C</div>
  </li>
</ul>

為什麼使用Label與Radio button?

這支實作的主要技巧也就是要靠這兩種元素的特性,因為我們要「借用」Radio button的單選特性,決定哪個Tab是Active,同時確保其他Tab是未選取的狀態。

為了保持Radio button是用來決定選取與否的單純角色,不建議直接把它設計成Tab,所以我們使用<label>來擔任Tab view的角色,也比較容易style,再藉由Label的For屬性去觸發對應id的Radio button。

所以我們為Radio button加上id,然後將Label的for屬性指向對應的id:

  <ul class="tabs">
  <li>
    <input type="radio" name="tabs" id="tabA">
    <label class="tab" for="tabA">頁籤A</label>
    <div class="section">這是內文A</div>
  </li>
  <li>
    <input type="radio" name="tabs" id="tabB">
    <label class="tab" for="tabB">頁籤B</label>
    <div class="section">這是內文B</div>
  </li>
  <li>
    <input type="radio" name="tabs" id="tabC">
    <label class="tab" for="tabC">頁籤C</label>
    <div class="section">這是內文C</div>
  </li>
</ul>

這樣就完成我們的HTML結構了,再來要寫點CSS,讓功能得以運作起來。

寫點CSS

  1. 我們先讓<li>並排(display:inline-block)。
  2. 再來為<label>和內容區塊<div class="section">設計外觀。
  3. 特別注意內容區塊用絕對定位讓每次顯示的區塊都在同樣的位置,之後我們再控制圖層上下位置(z-index)和透明度(opacity)來達成顯示/隱藏。
  li { display: inline-block; }

input[type="radio"] {
  position: absolute;
  outline: none;
    ...
}

.tab {
    ...
}

.section {
  position: absolute;
  top: 50px; // 取決於你的Label高度
  left: 0;
    ...
}

咦?還是不能動?因為我們還需要運用CSS的兩個重要技巧:偽類別(Pseudo-class)和同層選擇器(Sibling Combinator),才能讓頁籤與內容區塊做切換。

加入CSS偽類別與同層選擇器

我們為Radio button加上偽類別:checked,表示當這個Radio button被點選時(亦等於對應的頁籤被點選)才會呈現的Style。

  input[type="radio"]:checked {
    ...
}

然後要做切換動作的是頁籤和內容區塊,由於它們與Radio button屬同一層父元素,所以我們這裡要用到同層選擇器~來做,同層選擇器有兩種:

  1. 同層相鄰選擇器(Adjacent Sibling Combinator)是用來選取同層裡相鄰的元素。
  2. 同層全體選擇器(General Sibling Combinator)則是用來選取同層裡所有匹配的元素。

我們使用同層全體選擇器即可:

  input[type="radio"]:checked ~ .tab {        // 這裡也可以使用同層相鄰選擇器來做
    ...
}

input[type="radio"]:checked ~ .section {
    ...
  z-index: 2;
}

注意內容區塊(.section)要加上z-index屬性才能覆蓋其它頁籤的內容區塊,最後我們再將Radio button設為透明或使用定位的技巧讓它消失在UI上,前面沒有先提這點的原因,是因為可以讓你在點選頁籤時,觀察Radio button的選取狀態變化,同時也方便測試,確認頁籤對應的Radio button有正確被觸發。

這樣就大功告成啦!

整理

大略整理一下重點與需要注意的地方:

  1. Radio button的單選特性是基於同樣的name屬性,所以name一定要設,而且要一樣;反之,你可以設置多組name去實現多組的頁籤元件,而且各自是獨立運作,不會互相影響。
  2. Radio button的id和Label的for是必要的屬性。
  3. 內容區塊的定位要避免覆蓋到頁籤。
  4. 注意HTML的結構是否正確,CSS選擇器的使用是否正確(頁籤和內容區塊有沒有在同一層)。
  5. 注意z-index的設置是否正確。

Radio-based Tab元件的實作給予頁籤UI另一種開發的選擇,Radio button的特性還有很多應用可以做(如Switcher),只要善用HTML表單元件與CSS的一些技巧,也能玩出很多有趣的功能,甚至替代JavaScript的部份工作。

寫得不好敬請多多包含與指教嘍!XD

其它連結


8,306 0 3