BEM不建议使用标签选择器,因其使样式与HTML语义强绑定,导致组件复用困难、易冲突失效;应改用如.btn--submit等归属明确的类名以保障可迁移性与协作安全。
直接写 button、ul、h2 这类标签选择器,等于主动放弃样式归属权——它让 CSS 和 HTML 语义强绑定,一旦结构微调或组件复用,样式立刻失效或冲突。
比如写 button:hover,浏览器会匹配页面里所有 <button>,不管它属于登录表单、弹窗还是第三方组件。真实项目中,Ant Design 的 button 和你写的 button:hover 必然互相覆盖;Cypress 测试靠类名定位,button 匹配整个页面,根本没法精准点击。
.btn--submit:hover 只作用于提交按钮,换到卡片或弹窗里照样生效ul 无法区分导航菜单、评论列表、侧边栏链接——三者语义不同,但标签相同,样式必然冲突ul 没有命名空间,极易被全局重置样式(如 normalize.css)意外干预开发者常以“HTML 语义化”为由保留 article h2,但这其实是混淆:HTML 的 <h2> 表示层级重要性,而 CSS 需要回答“这个标题属于哪个模块、什么状态”。article h2 把样式绑死在 <article> 内,挪到卡片或弹窗就失效;card__title 则只认类名,跟标签和位置无关。
form input[type="text"] 无法表达“搜索输入框”还是“用户名输入框”,且 React/Vue 可能封装为自定义组件,标签根本不是 input
svg path 样式应归属 icon--search,换用 iconfont 或 <img> 就崩h2 的样式可能因语义调整(如改用 div role="heading")而全部失效BEM 的核心是把模块关系编码进类名:search-form__input--disabled 明确声明了归属(search-form)、角色(input)、状态(disabled)。而 button.search-form__submit 这种写法,表面加了类名,实际仍依赖标签,框架一换标签(比如用 <span> 模拟按钮),样式就断。
.search-form .search-form__submit:这是后代选择器,触发 DOM 回溯,权重变高,结构一动就失效button.search-form__submit:标签 + 类名组合,既污染全局,又让样式无法移植真正难的不是记住“别写 button”,而是每次敲下它时,是否清楚自己正在交出哪部分控制权——是交给了某个具体组件,还是交给了整个 HTML 规范。