通用工具类必须带u-前缀,仅用于组件外层布局节点;不带u-的mt-4、px-2等会与第三方库、旧样式冲突;u-类须声明在@layer utilities中,数值映射设计系统变量,禁止在元素内部(如card__content)使用。

通用工具类必须带u-前缀,且只出现在组件外层布局节点
不带u-的mt-4、px-2在BEM项目里是危险信号——它和第三方库、旧样式、团队其他人的工具类直接冲突,DevTools里查不到谁在起作用。u-是命名空间隔离线,不是缩写习惯。真正的工具类必须用u-打头,比如u-mt-4,且只能加在块级容器上(如<div class="card u-mb-6">),不能进到<code>card__content这种元素内部。
常见错误现象:card__content u-mt-2导致复用时空白错位;user-card__avatar u-rounded把视觉控制权下放到底层,破坏块的封装性。
-
u-类必须声明在@layer utilities中,确保层叠优先级高于组件样式 - 数值必须映射设计系统变量,如
u-mt-4→margin-top: var(--space-4),禁用硬编码1rem - 高频场景:页面级间距、网格间隙、响应式断点切换(如
u-hidden-below-md)
BEM修饰符只表达组件自身变体,不承担布局责任
card--horizontal、button--disabled这类修饰符描述的是组件的固有状态或意图,不是“给它加个外边距”。它们只影响挂载节点本身的样式,不穿透、不继承、不控制子元素位置。
典型误用:card--with-margin——这其实是布局意图,应由外层u-mb-4承担;list__item--spaced——列表项不该决定自己和兄弟的距离,该由list--compact统一控制gap或margin-bottom。
立即学习“前端免费学习笔记(深入)”;
- 修饰符名必须语义化,避免
--small、--blue等样式描述,改用--compact、--theme-dark - 禁止修饰符内写媒体查询,响应式行为由
_breakpoints.scss统一包裹已有修饰符 - 多个修饰符可共存(
button button--primary button--loading),但不可连缀(button--primary-loading)
当工具类和修饰符功能重叠时,以职责分离为判断标准
比如都实现“顶部留空”,u-mt-4表示“与上一区块分隔”,card--stacked表示“卡片采用堆叠布局”——前者是布局关系,后者是组件形态。二者可以同时存在,但不能互相替代。
容易踩的坑:card--stacked u-mt-4写在一起没问题,但若把u-mt-4逻辑塞进card--stacked的CSS规则里,就模糊了边界:下次想改堆叠布局但保留原有间距,就得拆开重写。
- 工具类负责“哪里放”,修饰符负责“长什么样”
- 工具类可跨组件复用(
u-mt-4用于card、form、section),修饰符只属于特定块(card--stacked对form无效) - 性能影响:工具类是原子规则,无嵌套;修饰符常带上下文依赖(如
.card--stacked .card__content),选择器略重
React/Vue中动态拼接类名时,必须守住这条线
用clsx或classnames拼接时,u-类和BEM类要分层管理。比如:clsx('card', 'u-mb-6', { 'card--featured': isFeatured })——u-mb-6是独立布局指令,card--featured是组件状态,二者不能混进同一个条件对象里。
错误写法:clsx({ 'card u-mb-6': true, 'card--featured': isFeatured }),这样u-mb-6会随isFeatured开关,违背其“稳定布局”的本意。
- 工具类应作为静态基础类传入,修饰符才参与条件判断
- 禁止在JS里拼出
card__content u-mt-2——元素层级禁用工具类,这是硬性约束 - 如果框架组件需要透传布局控制,应通过
layoutProps单独接收u-类,而非混在className里
u-,还是组件自身的--modifier。一旦混淆,后续所有复用、主题切换、响应式调整都会变成连环雷。


















