accordion__header--is-open必须加在header元素上,因展开/收起是用户对header的操作反馈,BEM要求状态类须落在承载交互的DOM元素上;加在content上会导致动画失效、JS无响应、键盘聚焦反馈错位。

必须把激活态类加在 header 元素上,而不是 content;否则动画不触发、JS 切换无响应、键盘聚焦反馈错位。
为什么 accordion__header--is-open 必须加在 header 上
展开/收起是用户对标题区域的操作反馈,BEM 要求状态类必须落在承载该交互的 DOM 元素上。把 accordion__header--is-open 加在 accordion__content 上,会导致:
- CSS 选择器无法匹配到真实状态(比如
.accordion__content--is-open写了但没生效) - max-height 过渡直接跳变,因为浏览器没感知到“状态已切换”
- 键盘用户按 Enter 展开后,焦点仍在 header,但视觉样式却没变化
如何正确同步 header 与 content 的状态
JS 必须同时控制两个类,且它们职责分离:
-
accordion__header--is-open:负责 icon 旋转、背景色、字体粗细等交互反馈 -
accordion__content--expanded:只管布局响应,比如max-height或transform: scaleY() - 两者由同一事件触发,例如:
headerEl.classList.toggle('accordion__header--is-open')和contentEl.classList.toggle('accordion__content--expanded')
max-height 动画失效的常见原因和解法
max-height: 0 → max-height: auto 不会动画,因为 auto 不可插值。实际表现是硬切。
立即学习“前端免费学习笔记(深入)”;
- 固定高度方案:设具体值,如
max-height: 300px,确保大于所有可能内容 - 动态高度方案:改用
transform: scaleY(0)+overflow: hidden,更可靠且 GPU 加速 - 务必加
will-change: transform,尤其在 iOS Safari 中,否则动画掉帧 - 别给
accordion__content设height: auto或依赖 padding-top/bottom 参与动画——它不参与 transform 插值
多级折叠面板的状态命名陷阱
嵌套的折叠面板不是上层 accordion 的子元素,而是独立组件。不能写成 accordion__body--nested 或 accordion__body__header。
- 必须定义新 block,如
nested-accordion - 它的状态修饰符只能是
nested-accordion--expanded,绑定在最外层容器上 - 禁止把修饰符挂在
__header或__body上,否则 JS/CSS 维护点分裂,极易不同步 - DOM 结构要保证父子紧邻,否则点击热区断裂,移动端触摸不灵敏
最容易被忽略的是:状态类名本身不是魔法,它只是 JS 和 CSS 之间的一份契约。漏掉一个 --、加错一个层级、或让两个状态类共用同一个元素却没显式处理组合效果,都会让动画卡在半途、焦点反馈消失、或者构建时被 PurgeCSS 误删。


















