利用 :checked 偽類 + 相鄰/通用兄弟選擇器(+ ~),配合 <label> 擴大點擊區域,可實現零 JavaScript 的狀態切換交互。適用於簡單開關、抽屜面板、標籤頁等場景,減少 JS 依賴,提升首屏性能。
<style>
[type=checkbox] + * { display: none; }
[type=checkbox]:checked + * { display: inline-block; }
</style>
<input type="checkbox" /><input />
勾選時,緊鄰的文本框顯示;取消勾選即隱藏。缺點:Checkbox 暴露在視圖中,語義不清。
<style>
[type=checkbox] { display: none; }
[type=checkbox] ~ input { display: none; }
[type=checkbox]:checked ~ input { display: inline-block; }
[type=checkbox] ~ span { cursor: pointer; margin-right: 10px; }
[type=checkbox] ~ span::before { content: '點我顯示文本框'; }
[type=checkbox] ~ span:hover { color: #c30; }
[type=checkbox]:checked ~ span::before { content: '點我隱藏文本框'; }
</style>
<label>
<input type="checkbox" />
<span></span>
<input />
</label>
優勢:Checkbox 完全隱藏,Label 內任意區域可觸發,文字提示動態切換。
id+for 關聯,或改用 <button type="button"> 觸發 JS 切換 class:has()、:parent(CSS4 草案中),只能控制同級後續元素。
opacity:0; position:absolute; pointer-events:none),保留焦點環<div class="tabs">
<input type="radio" name="tab" id="tab1" checked hidden>
<label for="tab1">Tab 1</label>
<div class="panel">內容 1</div>
<input type="radio" name="tab" id="tab2" hidden>
<label for="tab2">Tab 2</label>
<div class="panel">內容 2</div>
</div>
.tabs { display: flex; flex-wrap: wrap; }
.tabs > input { display: none; }
.tabs > label { order: 1; padding: 10px 20px; cursor: pointer; }
.tabs > .panel { order: 99; width: 100%; display: none; padding: 20px; border: 1px solid #ddd; }
#tab1:checked ~ .panel:nth-of-type(1),
#tab2:checked ~ .panel:nth-of-type(2) { display: block; }
| 場景 | 推薦度 | 備註 |
|---|---|---|
| 簡單開關/抽屜/下拉選單 | ⭐⭐⭐⭐⭐ | 零 JS、極輕量、語義尚可 |
| 標籤頁/手風琴 | ⭐⭐⭐⭐ | 需 Radio 配合,結構稍複雜 |
| 複雜表單驗證/聯動/異步提交 | ⭐ | 需 JS,強行純 CSS 反而難維護 |
| 無障礙嚴格項目 | ⭐⭐ | 需額外處理焦點、ARIA 屬性 |
純 CSS 交互是「漸進增強」的絕佳實踐:核心功能有 JS 兜底,簡單狀態切換用 CSS 承擔,減少主線程負擔,提升韌性。