天天看點

震驚!純 CSS 的導航欄切換方案

本文是非常有意思的一篇文章,介紹了 CSS 中,非常強大的一個知識點:

如何通過點選某個元素,控制其他元素~

不用

Javascript

,使用純

CSS

方案,實作類似下圖的導航欄切換:

震驚!純 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" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >清單1</a></li>
    <li><a href="#content2" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >清單2</a></li>
</ul>
<div id="content1">清單1内容:123456</div>
<div id="content2">清單2内容:abcdefgkijkl</div>
           

這樣,上面

<a href="#content1" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >

中的錨點

#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" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow"

時,頁面的 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" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >清單1</a></li>
    <li><a href="#content2" target="_blank" rel="external nofollow"  target="_blank" rel="external nofollow" >清單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僞類實作)[1]

法二:

<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 {
  // 進行樣式操作
}
           
同樣用到了兄弟選擇符 ~

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

但是,這裡有個問題 我們的 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 結構及核心 CSS 樣式:

<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>
           
input {
 display: none;
}

.nav1:checked ~ .content > div {
 display: none;

 &:first-child {
  display: block;
 }
}
.nav2:checked ~ .content > div {
 display: none;

 &:last-child {
  display: block;
 }
}
           

使用兩個單選框,分别對應兩個導航選項,運用上面介紹的 label 綁定表單,

:checked

接收點選事件,可以得到第二解法。

看看最後的結果:

震驚!純 CSS 的導航欄切換方案

Demo戳我:純CSS導航切換(label 綁定 input:radio && ~) [2]

最後

我們在網上能夠看到的所有的關乎于純 CSS 導航,純 CSS Tab 切換,純 CSS 按鈕點選控制其他元素的一些顯示、隐藏,動效的觸發,其原理基本都是運用到了上述兩種方案。

好了,本文到此結束,希望對你有幫助 :)

參考資料

[1]

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

[2]

Demo戳我:純CSS導航切換(label 綁定 input:radio && ~) : https://codepen.io/Chokcoco/pen/VKXXEq

[3]

Github -- iCSS: https://github.com/chokcoco/iCSS

繼續閱讀