选中态应挂载在 element 或 block 层,如 .rating__star--selected 或 .select--has-value;它必须由 js 显式控制,不可用 :checked/:focus 替代,且需与 --hovered/--focused 语义分离、样式独立。

选中态该挂在哪一层:block、element 还是 modifier
选中态不是独立存在的视觉效果,而是某个可交互单元的明确状态反馈。BEM 中必须用 --selected 修饰符,且它只能作用于 **element**(如 .rating__star--selected)或 **block**(如 .select--has-value),不能脱离上下文单独写 .selected。直接给元素加 .is-selected 或 .active 是破坏 BEM 语义的典型错误——它让样式失去归属,JS 切换时也难定位作用域。
为什么不能只靠 :checked 或 :focus 实现 --selected
:checked 只对原生 <input type="checkbox"> 有效,而现代下拉、评分、Tab 等组件基本都用自定义 DOM 渲染;:focus 表示键盘焦点,不等于用户已确认选择。这两个伪类无法表达「已被用户点中并生效」这一业务含义。
-
--selected必须由 JS 显式控制:el.classList.add('rating__star--selected') - 禁用态要同步移除:
if (el.hasAttribute('disabled')) return,否则点击无效却仍能加类 - 多选场景下,
--selected应配合data-value或aria-checked="true"保持语义一致
常见踩坑:--selected 和 --hovered / --focused 混用
三者语义完全不同,但容易在 CSS 中被写成同一套样式规则,导致行为错乱:
-
--hovered:仅鼠标悬停时临时反馈,松开即消失,不改变值 -
--focused:键盘导航时聚焦某项,可用tabindex="0"触发,与是否选中无关 -
--selected:用户已完成操作,状态需持久化,且应触发数据变更
错误写法:.rating__star:hover, .rating__star--selected { color: gold; } —— 这会让悬停高亮覆盖掉已选中的视觉判断。正确做法是分开声明,且 --selected 的样式权重不低于 --hovered。
复杂组件中 --selected 的归属逻辑怎么定
关键看「谁承担选中后的职责」。比如下拉选择器中,.select__option--selected 负责标记哪一项被选中,但整个组件是否已有值,应由 .select--has-value 控制 .select__trigger 的外观(如清除按钮显隐、占位符隐藏)。评分组件同理:.rating__star--selected 标记星数,.rating--readonly 则禁用全部交互。
这个分层一旦写反,比如把 --selected 加到 .select 上,就会导致无法区分“第几项被选中”,后续扩展搜索、多选、清空等逻辑全得重写。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











