一个UI片段能否作为Block,取决于其功能独立性而非视觉复杂度;若删除后导致页面缺失完整功能(如search-form、user-avatar),即为Block,否则仅为临时容器。
不是看它多大、多复杂,而是删掉它,页面是否缺失某个完整功能。比如去掉 search-form,搜索功能就没了;去掉 user-avatar,用户身份标识就断了——这种就是 Block。反之,如果它只是视觉上“看起来像一块”,但没独立语义(如 section-2、main-content),那它大概率只是临时容器,不该建模为 Block。
常见误判点:
header-left-btn:带位置词,不是名词,无法跨上下文复用card__footer:如果 footer 里包含操作按钮、时间戳、状态标签,且这些在别处也复用(如列表项 footer、弹窗 footer),那它就不该是 Element,而该升格为 item-footer Blocknav__link:若 link 在页头、侧边栏、页脚都出现,且样式/行为一致,它就该是独立的 nav-link Block,而不是依附于某个 navcard__header__title 或 user-card__avatar__wrapper__inner 这类命名,违反 BEM 扁平层级原则,也暴露 DOM 实现细节。真正该问的是:这个“子结构”有没有可能被单独复用或控制状态?
实操判断清单:
.card .card__header .card__header__title)?→ 是,说明它已脱离父级语义约束__close)本身已是信号,应拆为 modal-close-button 或 search-clear-button
如果发现 button--error、input--error、alert--error 同时存在,而且样式几乎一样,那 --error 就不是某个 Block 的专属变体,而是跨组件的视觉状态——这时应该抽成 is-error 工具类,而非 Modifier。
Modifier 的合理使用边界:
button--primary ✔️:描述按钮自身变体,语义明确、可复用button--disabled ✔️:影响按钮自身渲染,移除后仍可显示默认态user-card--loaded ✖️:这是生命周期状态,不是视觉变体;JS 应控制 data-loaded 或 is-loaded 类card__title--highlight ✖️:Element 不该直接挂 Modifier;应由 card__title card__title--highlight 并列使用,且确保 highlight 是 card 内部可配置的视觉选项不要一上来就重写 HTML 结构。先做最小改动:
block__elem__sub 统一替换成 block__sub(前提是 sub 确实属于该 Block)card__badge 在用户卡片、通知气泡、商品标签里都出现),新建 badge Block,CSS 中删除所有 .card .card__badge 这类后代选择器,只保留 .badge 单类规则`card__${type}__icon`),这类必须拦截并替换为 card__icon card__icon--${type}
真正容易被忽略的是:第一个 __ 之后又出现 __,往往不是设计使然,而是“先加个 class 应急”的惯性结果。PR 评审时盯住这个信号,比事后重构管用十倍。