bem应按复用性判断是否启用:组件出现在≥2个路由或父组件中才建模为block;子结构不单独使用才定义为element;modifier需对应js逻辑变更,纯视觉调整宜用css变量;页面独有容器(如home-hero)用单class即可。

小项目里硬套 BEM 是自找麻烦,不是规范有问题,而是用错了地方。该用的时候用,不该用的时候就别用。
怎么判断一个组件值不值得上 BEM
只看复用性,不看视觉复杂度。一个按钮如果只在登录页出现一次,它就不需要 login-form__submit-button--primary 这种写法;但如果它同时出现在注册页、重置密码弹窗、第三方授权流程里,那它就得是独立的 button Block,并带自己的 button__label 和 button--loading。
- 组件是否出现在 ≥2 个不同路由或父组件中?是 → 按 BEM 建模
- 它的子结构(如 icon、badge)是否从不单独抽离使用?否 → 那它大概率不该是 element,而该是独立 block
- 是否存在“改一个 modifier 就得同步改 JS 判断逻辑”?存在 → modifier 合理;若只是纯视觉微调(比如边框粗细),直接用 CSS 自定义属性更轻量
页面级样式别塞进 BEM 结构
像 home-hero、about-section 这类只在一个页面里出现、不会被其他模块复用的容器,直接用单 class 即可。加 home__hero 不但没带来隔离收益,反而让 HTML 和 CSS 更啰嗦。
- 纯页面独有样式(如
home-hero)可直接用单 class,不加 block 前缀 - 临时状态类(如
is-loading、has-error)保持全局工具类语义,不塞进某个 block 下 - Vue 单文件组件中,若
<template></template>仅被本组件使用,其内部 class 可简化为card-title而非card__title,前提是card不作为跨组件 Block 发布
构建时按需启用 BEM 约束
别让整个项目被一套规则绑架。BEM 是一种建模手段,不是语法强制标准。
- Webpack/Vite 构建时,用
postcss-bem插件仅处理/components/目录下的 CSS,跳过/pages/和/layouts/ - Sass 中,只对明确标记为
@use "bem-mixins"的文件启用嵌套规则,其余样式文件保持扁平结构 - HTML 层也一样:不强求每个
<div> 都带 block class,而是只在真正需要作用域隔离的位置加,例如模态框内容区、表单字段组、卡片容器这些天然具备复用潜力的节点 <p>最容易被忽略的一点:BEM 的“过度感”往往来自把页面容器和功能 Block 混为一谈。比如把整个 <code>dashboard-page当成一个 Block,然后往里塞dashboard-page__user-card__header__title——其实user-card和dashboard-page是组合关系,不是隶属关系。拆开之后,HTML 更轻,CSS 更易维护,连 JS 绑定事件都更干净。











