
本文介绍如何利用 css 通用兄弟选择器(~)与:focus伪类,无需 javascript 即可实现“根据父级 id 动态显示同组子项”的侧边栏展开逻辑,适用于 htmx 等现代前端框架的无 js 交互增强场景。
本文介绍如何利用 css 通用兄弟选择器(~)与:focus伪类,无需 javascript 即可实现“根据父级 id 动态显示同组子项”的侧边栏展开逻辑,适用于 htmx 等现代前端框架的无 js 交互增强场景。
在构建响应式侧边栏时,常需将结构组织为“分组标题 + 同组子项”的扁平化 <li> 序列(以兼容 htmx 的 takeClass() 等 DOM 操作),同时避免嵌套破坏语义或干扰交互逻辑。此时,若希望点击/聚焦某个带 id 的 <li>(如 id="group-1")后,自动显示其后所有 data-sidebar-group="group-1" 的兄弟 <li>,而不依赖 JavaScript 查询匹配,CSS 提供了一种简洁、声明式的解决方案。
核心思路是:利用 :focus 触发样式变更,并借助兄弟选择器的“后续匹配”特性,结合层级遮蔽规则实现条件筛选。关键在于三点:
-
默认隐藏所有子项:
*[data-sidebar-group] { display: none; } -
对任意获得焦点的元素,显示其后所有带
data-sidebar-group的兄弟元素:*:focus ~ *[data-sidebar-group] { display: block; } -
关键过滤:当两个可聚焦项(如
tabindex="0")之间存在另一个可聚焦项时,中断显示链——即仅显示紧邻其后的同组项,而非全部后续项:*:focus ~ *[tabindex] ~ *[data-sidebar-group] { display: none; }
该规则生效的前提是 HTML 结构严格遵循“可聚焦分组项 → 同组子项 → (可选)下一可聚焦分组项”的线性顺序。例如:
- Group 1
- Item 1
- Item 2
- Group 2
- Item 1
- Item 2
✅ 此时聚焦 #group-1,仅 data-sidebar-group="group-1" 的两项显示;
✅ 聚焦 #group-2,则仅其后的两项显示;
❌ 若在 #group-1 和其子项之间插入另一个 tabindex 元素,则子项将被第三条规则隐去。
⚠️ 注意事项:
- 必须确保
tabindex="0"(或tabindex属性存在)仅用于分组标题项,不可误加于子项; - 该方案依赖 DOM 顺序,不支持跨层级或乱序结构;
- 若需键盘导航支持,建议配合
:focus-visible提升可访问性; - 在 htmx 场景中,此 CSS 方案与
hx-on:click行为完全解耦,既可独立使用,也可与htmx.takeClass()协同实现视觉高亮+内容展开双重反馈。
综上,虽 CSS 无原生“属性值动态匹配”能力(如 li[data-sidebar-group=id]),但通过 :focus + ~ + 层级遮蔽的组合技巧,我们实现了高效、可维护的条件兄弟选择逻辑——让样式层真正承担起部分本属 JS 的状态驱动职责。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











