有趣的 CSS 題目(8):純CSS的導航欄Tab切換方案

純CSS的導航欄Tab切換方案


不用 Javascript,使用純 CSS 方案,實現類似下圖的導航欄切換:




CSS 的強大之處有的時候超乎我們的想象,Tab 切換,常規而言確實需要用到一定的腳本才能實現。下面看看如何使用 CSS 完成同樣的事情。


實現 Tab 切換的難點在於如何使用 CSS 接收到用戶的點擊事情並對相關的節點進行操作。即是:


  1. 如何接收點擊事件

  2. 如何操作相關DOM


下面看看如何使用兩種不同的方法實現需求:


法一::target 僞類選擇器


首先,我們要解決的問題是如何接收點擊事件,這裏第一種方法我們採用 :target 僞類接收。


:target 是 CSS3 新增的一個僞類,可用於選取當前活動的目標元素。當然 URL 末尾帶有錨名稱 #,就可以指向文檔內某個具體的元素。這個被鏈接的元素就是目標元素(target element)。它需要一個 id 去匹配文檔中的 target 。


解釋很難理解,看看實際的使用情況,假設我們的 HTML 代碼如下:


<ul class="nav">

    <li>列表1</li>

    <li>列表2</li>

</ul>

<div>列表1內容:123456</div>

<div>列表2內容:abcdefgkijkl</div>


由於要使用 :target,需要 HTML 錨點,以及錨點對應的 HTML 片段。所以上面的結構要變成:


<ul class="nav">

    <li><a href="#content1">列表1</a></li>

    <li><a href="#content2">列表2</a></li>

</ul>

<div id="content1">列表1內容:123456</div>

<div id="content2">列表2內容:abcdefgkijkl</div>


這樣,上面 <a href="#content1"> 中的錨點 #content1 就對應了列表1 <div id="content1"> 。錨點2與之相同對應列表2。


接下來,我們就可以使用 :target 接受到點擊事件,並操作對應的 DOM 了:


#content1,

#content2{

    display:none;

}

 

#content1:target,

#content2:target{

    display:block;

}


上面的 CSS 代碼,一開始頁面中的 #content1 與 #content2 都是隱藏的,當點擊列表1觸發href="#content1" 時,頁面的 URL 會發生變化:


  1. 由 www.example.com 變成 www.example.com#content1

  2. 接下來會觸發 #content1:target{ } 這條 CSS 規則,#content1 元素由 display:none 變成display:block ,點擊列表2亦是如此。


如此即達到了 Tab 切換。當然除了 content1 content2 的切換,我們的 li 元素樣式也要不斷變化,這個時候,就需要我們在 DOM 結構佈局的時候多留心,在 #content1:target 觸發的時候可以同時去修改 li 的樣式。


在上面 HTML 的基礎上,再修改一下,變成如下結構:


<div id="content1">列表1內容:123456</div>

<div id="content2">列表2內容:abcdefgkijkl</div>

<ul class="nav">

    <li><a href="#content1">列表1</a></li>

    <li><a href="#content2">列表2</a></li>

</ul>


仔細對比一下與上面結構的異同,這裏我只是將 ul 從兩個 content 上面挪到了下面,爲什麼要這樣做呢?


因爲這裏需要使用兄弟選擇符 ~ 。


E~F{ cssRules } ,CSS3 兄弟選擇符(E~F) ,選擇 E 元素後面的所有兄弟元素 F。


注意這裏,最重要的一句話是 E~F 只能選擇 E 元素 之後 的 F 元素,所以順序就顯得很重要了。


在這樣調換位置之後,通過兄弟選擇符 ~ 可以操作整個 .nav 的樣式。


#content1:target ~ .nav li{

    // 改變li元素的背景色和字體顏色

    &:first-child{

        background:#ff7300;

        color:#fff;

    }

}

#content2:target ~ .nav li{

    // 改變li元素的背景色和字體顏色

    &:last-child{

        background:#ff7300;

        color:#fff;

    }

}


上面的 CSS 規則中,我們使用 ~ 選擇符,在 #content1:target 和 #content2:target 觸發的時候分別去控制兩個導航 li 元素的樣式。


至此兩個問題,1. 如何接收點擊事件 與 2. 如何操作相關DOM 都已經解決,剩下的是一些小樣式的修補工作。


Demo戳我:純CSS導航切換(:target僞類實現)(http://codepen.io/Chokcoco/pen/mAxQBv)


法二:<input type="radio"> && <label for="">


上面的方法通過添加 <a> 標籤添加頁面錨點的方式接收點擊事件。


這裏還有一種方式能夠接收到點擊事件,就是擁有 checked 屬性的表單元素, <input type="radio"> 或者<input type="checkbox"> 。


假設有這樣的結構:


<input class="nav1" type="radio">

 

<ul class='nav'>

    <li>列表1</li>

</ul>


對於上面的結構,當我們點擊 <input class="nav1" type="radio"> 單選框表單元素的時候,使用 :checked是可以捕獲到點擊事件的。


.nav1:checked ~ .nav li {

  // 進行樣式操作

}


同樣用到了兄弟選擇符 ~


這樣,當接收到表單元素的點擊事件時,可以通過兄弟選擇符 ~ 操作它的兄弟元素的樣式。


可以試着點擊下面 codepen(http://codepen.io/Chokcoco/pen/yaEvYK/) 中的單選框。


但是,這裏有個問題 我們的 Tab 切換,要點擊的是<li>元素,而不是表單元素,所以這裏很重要的一點是,使用 <label for=""> 綁定表單元素。看看如下結構:


<input class="nav1" id="li1" type="radio">

 

<ul class='nav'>

    <li><label for="li1">列表1</label></li>

</ul>


通過使用 <label> 包裹一個 <li> 元素,而 <label> 有一個屬性 for 可以綁定一個表單元素。


上面的 <li> 中,有一層 <label for="li"> ,裏面的 for="li1" 意思是綁定 id 爲li1 的表單元素。


label 標籤中的 for 定義:for 屬性規定 label 與哪個表單元素綁定。


這樣改造之後,當我們點擊 <li> 元素的時候,相當於點擊了 <input class="nav1" id="li1" type="radio">這個單選框表單元素,而這個表單元素被點擊選中的時候,又可以被 :checked 僞類捕獲到。


這個時候,我們就可以將頁面上的表單元素隱藏,做到點擊 <li> 相當於點擊表單:


input{

    display:none;

}


這樣,應用到本題目,我們應該建立如下 DOM 結構:


<div class="container">

    <input class="nav1" id="li1" type="radio" name="nav">

    <input class="nav2" id="li2" type="radio" name="nav">

    <ul class='nav'>

        <li class='active'><label for="li1">列表1</label></li>

        <li><label for="li2">列表2</label></li>

    </ul>

    <div class="content">

        <div class="content1">列表1內容:123456</div>

        <div class="content1">列表2內容:abcdefgkijkl</div>

    </div>

</div>


使用兩個單選框,分別對應兩個導航選項,運用上面介紹的 label 綁定表單,:checked 接收點擊事件,可以得到第二解法。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章