純CSS的導航欄Tab切換例項

lotus_ruan發表於2021-09-09

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

圖片描述

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

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

  1. 如何接收點選事件

  2. 如何操作相關DOM

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

 

法一::target 偽類選擇器

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

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

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


        
  • 列表1
  •     
  • 列表2
列表1內容:123456
列表2內容:abcdefgkijkl

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


        
  •     
列表1內容:123456
列表2內容:abcdefgkijkl

這樣,上面  中的錨點 #content1 就對應了列表1 

 。錨點2與之相同對應列表2。

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

#content1,
#content2{
    display:none;
}
 
#content1:target,
#content2:target{
    display:block;
}

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

  1. 由  變成 #content1

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

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

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

列表1內容:123456
列表2內容:abcdefgkijkl
        
  •     

仔細對比一下與上面結構的異同,這裡我只是將 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偽類實現)

 

法二: && 

上面的方法透過新增  標籤新增頁面錨點的方式接收點選事件。

這裡還有一種方式能夠接收到點選事件,就是擁有 checked 屬性的表單元素,  或者 。

假設有這樣的結構:


 
        
  • 列表1

對於上面的結構,當我們點選  單選框表單元素的時候,使用 :checked是可以捕獲到點選事件的。

.nav1:checked ~ .nav li {
  // 進行樣式操作
}

同樣用到了兄弟選擇符 ~

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

可以試著點選下面 codepen 中的單選框。

但是,這裡有個問題 我們的 Tab 切換,要點選的是

  • 元素,而不是表單元素,所以這裡很重要的一點是,使用  繫結表單元素。看看如下結構:

    
     
    
          

    上面的 

  •  中,有一層  ,裡面的 for="li1" 意思是繫結 id 為li1 的表單元素。

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

    這樣改造之後,當我們點選 

  •  元素的時候,相當於點選了 這個單選框表單元素,而這個表單元素被點選選中的時候,又可以被 :checked 偽類捕獲到。

    這個時候,我們就可以將頁面上的表單元素隱藏,做到點選 

  •  相當於點選表單:

    input{
        display:none;
    }

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

                  
              
    •         
    •     
        
            
    列表1內容:123456
            
    列表2內容:abcdefgkijkl
        

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

    看看最後的結果:

    Demo戳我:純CSS導航切換(label 繫結 input:radio && ~)

    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/1762/viewspace-2808746/,如需轉載,請註明出處,否則將追究法律責任。

    相關文章