Skip to main content

Command Palette

Search for a command to run...

#67 CSS :target 應用:純 CSS 光箱、純 CSS Tab 頁籤

Updated
3 min read
#67 CSS :target 應用:純 CSS 光箱、純 CSS Tab 頁籤
Y

Chief Designer @HealthyPlate

⚠️ 本篇文章已搬遷至 css.im1010ioio.dev,請至新站閱讀完整版


上一篇我們提到 CSS 的 :target 的偽類,可以針對 HTML 元素是否為目標狀態而去調整樣式。所以,如果延伸想一想,有許多 UI 都是會有狀態的,其實是可以做許多應用的。

上一篇著重在滾動時的目標狀態,這一篇我們來試試把這種目標狀態應用在別的地方吧!


一、純 CSS 光箱

光箱(Lightbox)效果是網頁中非常常見的 UI,通常用於點擊圖片或按鈕後,跳出一個覆蓋整個畫面的視窗來顯示更多內容。以前這大多需要 JavaScript 來控制顯示與隱藏,但現在透過 :target,我們只要純 CSS 就能做到!

怎麼做出來的?

核心概念是:

  1. 一個觸發按鈕:這是一個 <a> 連結,它的 href 指向光箱元素的 ID,例如 href="#lightbox1"

  2. 一個光箱容器:這是一個 <div>,它有一個對應的 ID,例如 id="lightbox1"

  3. 一個關閉按鈕:這也是一個 <a> 連結,它的 href 指向 "#" 或一個不存在的 ID,目的是清除網址列中的 hash,讓光箱變回非 :target 狀態。

當我們點擊「觸發按鈕」,網址列會加上 #lightbox1,此時 ID 為 lightbox1<div> 元素就符合了 :target 的條件,我們就可以透過 CSS 選擇器 .lightbox:target 來改變它的樣式,讓它從原本隱藏的狀態(opacity: 0)變成顯示狀態(opacity: 1)。

HTML 的結構很單純:

<a class="btn btn1" href="#lightbox1">Open Lightbox #1</a>

<div class="lightbox" id="lightbox1">
    <figure>
        <a href="#" class="close"></a>
        <figcaption>
            <h2>Hello! I'm Lightbox #1.</h2>
            <hr>
            Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec felis enim,
      placerat id eleifend eu, semper vel sem.
        </figcaption>
    </figure>
</div>

接著是 CSS 的魔法:

/* 預設狀態:光箱是透明的,而且無法被點擊 */
.lightbox {
    opacity: 0;
    pointer-events: none; /* 讓元素無法成為滑鼠事件的目標 */
    transition: .3s; /* 加個過渡效果更滑順 */
}

/* 目標狀態:當光箱成為 target 時,讓它完全不透明,且可以被點擊 */
.lightbox:target {
    opacity: 1;
    pointer-events: auto;
}

/* 關閉按鈕的容器,只是為了定位 */
.lightbox .close {
    position: relative;
    display: block;
}

/* 關閉按鈕本體,用 ::after 偽元素畫一個叉叉 */
.lightbox .close::after {
    position: absolute;
    top: -.5rem;    right: -.5rem;
    z-index: 1;
    width: 1.5rem;  height: 1.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #555;
    border-radius: 50%;
    color: white;
    content: "×";
    cursor: pointer;
}

/* 光箱背景:我們用 ::before 偽元素做出一個覆蓋全螢幕的半透明黑底 */
.lightbox .close::before {
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    position: fixed; /* 用 fixed 定位才能蓋住整個畫面 */
    background-color: rgba(0, 0, 0, 0.5);
    content: "";
    cursor: default;
}

我們利用了 ::before 偽元素做出了背景遮罩,再用 ::after 做出了關閉按鈕,整個過程完全沒有動到任何一行 JavaScript!

更詳細的細節,請看 DEMO:

DEMO 連結:Pure CSS Lightbox by :target


二、純 CSS Tab 頁籤

Tab 頁籤也是一個很常見的 UI 元件,使用者可以點擊不同的頁籤來切換內容。這個效果跟光箱非常類似,都是利用 :target 來控制不同內容區塊的顯示與隱藏。

怎麼做出來的?

這次的 HTML 結構需要一點小巧思。為了讓 CSS 選擇器可以順利運作,我們需要將**「內容區塊」放在「頁籤按鈕」的前面**。

為什麼呢?因為我們要用這個波浪選擇器 ~ 符號。這個選擇器的作用是「選取某個元素後面的弟弟」。

我們的邏輯是:當某個內容區塊(例如 #tab1)變成 :target 時,我們要去改變它後面對應的頁籤按鈕(.btn-tab)的樣式,讓它看起來是「被選中」的狀態。

HTML 結構如下:

<div class="content">
    <!-- 內容區塊要先放 -->
    <div id="tab1" class="tab-content"> ... </div>
    <div id="tab2" class="tab-content"> ... </div>
    <div id="tab3" class="tab-content"> ... </div>

    <!-- 頁籤按鈕後放 -->
    <div class="tabs-row">
        <a class="btn-tab" href="#tab1">一月</a>
        <a class="btn-tab" href="#tab2">二月</a>
        <a class="btn-tab" href="#tab3">三月</a>
    </div>
</div>

CSS 的部分:

/* 預設狀態:所有內容區塊都隱藏 */
.tab-content{
    display: none;
    padding: 1rem 2rem;
}

/* 目標狀態:當內容區塊成為 target 時,顯示它 */
.tab-content:target{
    display: block;
}

/* 頁籤按鈕的基本樣式 */
.tabs-row{
    display: flex;
}

.btn-tab{
    text-decoration: none;
    color: #79a6d0;
    background: #d3d886;
    padding: 1rem 1rem .5rem 1rem;
    border-top-left-radius: 1rem;
    border-top-right-radius: 1rem;
    transition: .3s;
}

/* 當 #tabN 是 target 時,選取它後面的第 N 個 .btn-tab */
#tab1:target ~ .tabs-row .btn-tab:nth-child(1),
#tab2:target ~ .tabs-row .btn-tab:nth-child(2),
#tab3:target ~ .tabs-row .btn-tab:nth-child(3){
    background: #f2f5bc; /* 變成 active 的顏色 */
}

/* 預設顯示第一個頁籤 */
/* :not(:has(...)) 的意思是「當 .content 裡面沒有任何 .tab-content 是 target 狀態時」 */
.content:not(:has(.tab-content:target)){
    /* 讓第一個內容區塊顯示 */
    .tab-content:nth-child(1) {
        display: block;
    }
    /* 讓第一個頁籤按鈕也顯示 active 樣式 */
    .tabs-row .btn-tab:nth-child(1){
        background: #f2f5bc;
    }
}

透過安排 HTML 順序,並搭配 ~ 選擇器,我們就成功實現了純 CSS 的頁籤切換效果,甚至還做出了預設狀態!

雖然說稍微有一點不夠彈性,要一個個頁籤設定;不過頁籤通常不會太多,所以在維護上還可以。如果更進一步,會使用 SASS/SCSS 的話,可以使用 for 迴圈寫出來,就會乾淨許多。

更詳細的細節,請看 DEMO:

DEMO 連結:Pure CSS tabs by the CSS :target


今天我們看到了 :target 的兩個實際應用,它讓我們可以根據網址的 hash 來改變頁面樣式,進而實作出以往需要 JS 才能完成的互動效果。雖然它有其限制(例如會改變 URL、無法處理複雜的狀態管理),但在許多簡單的場景下,:target 無疑是一個輕量、有趣的解決方法。

延伸閱讀:


↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

感謝看到最後的你,若你覺得獲益良多,請不要吝嗇給我按個喜歡。❤️

如果你喜歡我的創作,還想看看其他有趣的分享與日常,
可以追蹤我的 IG @im1010ioio,或者是🧋送杯珍奶鼓勵我,謝謝你🥰。

Eva Chen 送杯珍奶鼓勵我

超級簡單寫 CSS(Super Easy CSS)

Part 1 of 50

本系列文章目標是學習 CSS 基本知識,並且研究 The State of CSS 中值得令人期待新屬性,讓想要學習 CSS 的人也能一起學到新知識,不用再零零散散地去爬文搜尋。此外,還會提及一些前端基本知識、版本控制、開發經驗等必要概念,讓新手對於前端開發有全面的認識。

More from this blog

#93 SASS/SCSS (12) 防呆與偵錯 @debug / @warn / @error

⚠️ 本篇文章已搬遷至 css.im1010ioio.dev,請至新站閱讀完整版。 我們已經了解了 SASS/SCSS 的所有主要功能了,不過「我要如何確保別人(或未來的自己)不會用錯我寫的工具?」這是當 Mixin 和 Function 變得越來越複雜時,需要好好考慮的問題。 在 SCSS 中,可以為自己的 Code 建立「防呆」和「除錯」機制,SCSS 提供了三個指令,也就是:@debug、@warn 和 @error。其實我們在介紹 Lists 和 Maps 時就已經稍微帶過其中的 @...

Oct 13, 20251 min read44
#93 SASS/SCSS (12) 防呆與偵錯 @debug / @warn / @error

#92 SASS/SCSS (11) 資料結構 Map

⚠️ 本篇文章已搬遷至 css.im1010ioio.dev,請至新站閱讀完整版。 昨天學到的 List 是個簡單的列表,今天我們要來看看 SCSS 中的 Map,它有點像 json 資料。 假設專案裡有 5 個主要顏色、4 個斷點、6 種字體大小。如果用傳統的變數,你會有 15 個散亂的變數 $variable。但是用了 Map,就可以把它們全部收納在一個變數裡,讓結構一目了然。 一、Map 語法 1. 基本語法 Map 是由「鍵值對 (key-value pairs)」組成,比方說像下...

Oct 13, 20251 min read20
#92 SASS/SCSS (11) 資料結構 Map

#91 SASS/SCSS (10) 資料結構 List (列表)

⚠️ 本篇文章已搬遷至 css.im1010ioio.dev,請至新站閱讀完整版。 在 SASS/SCSS 中,我們已經使用變數、Mixin 和 Function 等語法來幫我們管理 CSS Code 了,但是它還是可能會亂,例如散亂的單一變數,除了寫註解外,還有什麼辦法能夠讓 Code 更有結構呢? 答案是 SCSS 的資料結構——Lists 和 Maps,其實昨天在寫 Function 時有稍微帶過,今天,我們就更近一步先來仔細研究 Lists 吧! 一、List 語法 List (列...

Oct 12, 20251 min read15
#91 SASS/SCSS (10) 資料結構 List (列表)

#90 SASS/SCSS (9) 函式 (Function) - 打造你自己的工具箱

⚠️ 本篇文章已搬遷至 css.im1010ioio.dev,請至新站閱讀完整版。 我們已經一路學習了 SCSS 的變數、顏色、邏輯判斷與迴圈等等,你可能已經覺得 SCSS 非常強大了。但今天,我們要來認識 SCSS 中一個更厲害的用法:Function 函式。 Function 能讓你為你的樣式打造屬於你自己的工具。 假設,你經常需要做一些重複性的計算,或要根據不同的輸入產生特定的樣式。每次都要重寫一遍,那這樣就會很難維護。這時候,Function 就可以派上用場了! 一、Functio...

Oct 10, 20251 min read14
#90 SASS/SCSS (9) 函式 (Function) - 打造你自己的工具箱

#89 SASS/SCSS (8) 邏輯 @if, @each, @for 與 @while

⚠️ 本篇文章已搬遷至 css.im1010ioio.dev,請至新站閱讀完整版。 今天,我們來介紹 SCSS 中最像「程式語言」的部分——SCSS 的控制指令 (Control Directives),它們能讓你的樣式擁有真正的「邏輯」,根據條件、迴圈來自動生成樣式,也就是所謂的: @if:如果 A 否則 B @each:處理「每一個」重複 @for:由數字跑迴圈 @while:條件成立就不斷循環 一、@if:如果 A 否則 B @if 就如同其他程式語言中的 if/else...

Oct 9, 20251 min read16
#89 SASS/SCSS (8) 邏輯 @if, @each, @for 與 @while
E

Eva Chen | 網頁設計師下班後

97 posts

ᴅᴇsɪɢɴᴇʀ / ғʀᴏɴᴛᴇɴᴅ ᴅᴇᴠᴇʟᴏᴘᴇʀ / 網頁設計 x 創作日常 x 工作日常 x 遊戲日常