:checked 配合 label 和相邻兄弟选择器可实现无 JS 手风琴,但必须视觉隐藏而非 display: none 或 visibility: hidden,以确保可访问性;推荐结构为 input 与面板同级且相邻,用 max-height 过渡;单选可用 name 相同的 radio 替代;移动端需扩大 label 点击区域并优化动画性能。
直接用配合和相邻兄弟选择器(或)就能实现无 JS 手风琴,但隐藏 checkbox 本身不是目的——关键是它必须保持可交互、可聚焦、可被屏幕阅读器识别,否则会出兼容性和可访问性问题。
为什么不能直接 display: none 或 visibility: hidden?
这两者会让
完全脱离可访问树:键盘用户按 Tab 进不来,屏幕阅读器读不到,
状态也无法被触发(尤其在 Safari 和部分旧版浏览器中)。真实场景下常表现为点击 label 没反应、回车键无法切换、NVDA/JAWS 报“不可操作”。
正确做法是视觉隐藏但保留语义和交互能力:
用
或
确保
的
属性或包裹结构正确绑定到该
别忘了加
(如果 label 不是包裹结构,且 input 被移出视口)
手风琴 DOM 结构怎么组织才可靠?
必须保证
和要控制的面板之间存在 CSS 可选中的关系。最稳的是「同一父容器内,input 紧邻面板」,用
;或者用
(通用兄弟)配合合理嵌套。避免跨层级、跨组件、用 flex/grid order 打乱文档流——这些会让选择器失效。
立即学习
“
前端免费学习笔记(深入)
”;
推荐结构示例:
对应关键 CSS:
使用HTML,CSS,JavaScript开发Android应用程序 英文文字pdf版附源文件
如果你了解HTML,CSS和JavaScript,您已经拥有所需的工具开发Android应用程序。本动手本书展示了如何使用这些开源web标准设计和建造,可适应任何Android设备的应用程序 - 无需使用Java。您将学习如何创建一个在您选择的平台的Android友好的网络应用程序,然后转换与自由PhoneGap框架到一个原生的Android应用程序。了解为什么设备无关的移动应用是未来的潮流,并开始构建应用程序,提供更
下载
比
更安全(避免内容高度动态变化时撑开错位)
必须设在面板上,否则过渡动画会漏出
500px 是个保守上限值,可根据实际内容微调,或用
(但兼容性略差)
单选手风琴(一次只开一个)怎么搞?
CSS 本身不支持“互斥”,但可以利用
属性 + 同名 radio 替代 checkbox。虽然语义上 radio 是“单选”,但配合手风琴 UI 是完全合理的——用户直觉就是“点一个开一个、关其他”。
要点:
所有
设相同
,比如
每个
仍需唯一
,label 用
绑定
CSS 选择器改用
初始状态建议加一个默认选中的
,否则首次打开可能无响应
注意:radio 没有“取消选择”行为(不像 checkbox 可再点一次取消),所以需要额外一个「收起全部」按钮(这个就得靠 JS 了)。
移动端点击区域小、误触多,怎么优化?
label 默认点击热区太小,尤其在 iOS 上容易失焦。别只依赖文字区域:
给
加
扩大可点范围
用
提示可交互
避免 label 内嵌
或
后又重置样式,导致事件冒泡异常
在 iOS 上,如果 label 包含
或
,记得加
防止遮挡
另外,
动画在低端安卓机上容易卡顿,优先用
和
做过渡;若必须用
,就别加太多子元素的 box-shadow 或 filter,它们会触发全层重绘。
真正难的不是写对那几行 CSS,而是让
始终“隐形但在线”——它得扛住键盘导航、语音朗读、缩放、高对比度模式,还得在各种 zoom level 下保持 label 热区完整。这些细节一漏,手风琴就从便利功能变成障碍源头。
:checked+~:checkedposition: absolute; left: -9999px;clip: rect(0 0 0 0); clip-path: inset(100%);forinputtabindex="0"input+~
内容区
.accordion-panel { max-height: 0; overflow: hidden; transition: max-height 0.3s ease-out; }
#item1:checked + .accordion-panel { max-height: 500px; }max-heightheightoverflow: hiddenfit-contentnameinputnamename="accordion-group"inputidforinput[name="accordion-group"]:checked + .panelinput:checkedlabeldisplay: block; padding: 12px 16px;cursor: pointer;spandivimgsvgpointer-events: none;:checkedtransformopacitymax-heightinput