:focus-within 是一個非常實用的 CSS 偽類別選擇器,當一個元素本身或其任何子元素取得焦點(focus)時,就會觸發該元素的樣式。這讓我們可以不用 JavaScript 就能實現許多互動效果。
基本原理
傳統的 :focus 只會在元素本身被 focus 時觸發。:focus-within 則不同,只要子元素有任何一個被 focus,父元素就會 match,這個特性類似 DOM 事件的冒泡(bubble)機制。
1
2
3
4
|
<div class="form-group">
<label>姓名</label>
<input type="text" placeholder="請輸入姓名">
</div>
|
1
2
3
4
5
|
/* 當 input 被 focus 時,父層 .form-group 也會被選中 */
.form-group:focus-within {
border: 2px solid #007bff;
background-color: #f0f8ff;
}
|
應用場景
1. 表單群組高亮
當使用者點擊某個輸入框時,整組 label + input 都一起高亮,提升使用者體驗:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
.form-group {
padding: 12px;
border: 1px solid #ccc;
border-radius: 4px;
transition: border-color 0.2s;
}
.form-group:focus-within {
border-color: #007bff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
.form-group:focus-within label {
color: #007bff;
font-weight: bold;
}
|
2. 下拉選單顯示
純 CSS 實現下拉選單,點擊觸發展開:
1
2
3
4
5
6
7
|
<nav class="dropdown">
<button>選單</button>
<ul class="menu">
<li><a href="#">項目一</a></li>
<li><a href="#">項目二</a></li>
</ul>
</nav>
|
1
2
3
4
5
6
7
|
.menu {
display: none;
}
.dropdown:focus-within .menu {
display: block;
}
|
3. 懸浮標籤(Floating Label)
結合 :focus-within 和 :placeholder-shown 實現無 JavaScript 的懸浮標籤效果:
1
2
3
4
|
<div class="input-wrap">
<input type="text" id="username" placeholder=" " />
<label for="username">使用者名稱</label>
</div>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
.input-wrap {
position: relative;
}
.input-wrap label {
position: absolute;
top: 50%;
transform: translateY(-50%);
transition: all 0.2s;
}
.input-wrap:focus-within label,
.input-wrap input:not(:placeholder-shown) + label {
top: 0;
font-size: 0.75em;
color: #007bff;
}
|
:focus-within vs :focus-visible
這兩個選擇器容易混淆,差異如下:
| 選擇器 |
觸發條件 |
:focus |
元素本身被 focus |
:focus-within |
元素本身或其子元素被 focus |
:focus-visible |
元素被 focus,且瀏覽器判斷應該顯示焦點樣式(通常是鍵盤操作時) |
:focus-visible 的設計是為了解決「滑鼠點擊按鈕時也顯示藍色外框」的問題,讓焦點樣式只在鍵盤操作時顯示,兼顧無障礙設計:
1
2
3
4
|
/* 只有鍵盤 focus 才顯示外框,滑鼠點擊不顯示 */
button:focus-visible {
outline: 2px solid #007bff;
}
|
瀏覽器支援度
:focus-within 已獲得所有現代瀏覽器支援(Chrome 60+、Firefox 52+、Safari 10.1+、Edge 79+),IE 不支援。
:focus-visible 支援度稍晚(Chrome 86+、Firefox 85+、Safari 15.4+),IE 同樣不支援。
參考資料