间距工具类必须用u-前缀并绑定CSS变量,如u-mt-4对应var(--space-4);BEM组件内禁用,外距由父级block修饰符统一控制;多u-margin类共存时仅最后一个生效,方向类须严格分离。

间距工具类必须用 u- 前缀且绑定 CSS 变量
没加 u- 的 mt-4 或 margin-top-2 在 BEM 项目里等于埋雷——它和第三方库、旧样式、同事写的工具类直接冲突,DevTools 里根本查不到谁在起作用。u-mt-4 才是唯一合法入口,这是命名空间隔离线,不是缩写习惯。
数值也不能自由发挥:u-mt-4 必须对应 margin-top: var(--space-4),而 --space-4 得在 :root 或主题上下文中明确定义为 0.5rem(或其他设计系统约定值)。否则换暗色模式、切主题、调字号时,所有间距就脱节了。
-
u-mt-1到u-mt-8推荐覆盖0.25rem步长的 scale(0,0.25rem,0.5rem…) - 禁用
u-mt-half这类非数字命名——JS 动态拼接cn('u-mt-', size)会失效 - 别把
u-mt-4硬写成margin-top: 1rem,绕过 CSS 变量等于放弃主题适配能力
BEM 组件内部禁止使用 u-margin 类
在 .card__content 里写 u-mt-2 是典型误用。__element 只管自身尺寸、内边距、颜色,不该承担布局责任。一旦 .card__content 自带 u-mt-2,把它复制进 .modal__body 就会多出一段空白,破坏复用性。
正确做法是让最外层 .card 这个 block 通过修饰符接管布局意图,比如 .card_margin-bottom-m,其 CSS 只声明 margin-bottom: var(--space-m)。这样所有子元素保持干净,间距逻辑收口在 block 层,改起来也只动一处。
立即学习“前端免费学习笔记(深入)”;
- 禁止出现
.card__content_u-mt-2这种嵌套工具类写法 - 高频组件(如
.list)提供.list--compact等修饰符,切换的是gap或单侧margin-bottom,而非每个__item单独调 - 若用 fallback 方案(老浏览器),用
.list > .list__item:not(:last-child) { margin-bottom: var(--space-2); },但必须确保.list自身不设margin-top防塌陷
多个 u-margin 类同时使用不会叠加,只生效最后一个
u-mt-2 u-mt-4 u-mt-6 一起写在同一个元素上,最终生效的只有 u-mt-6——CSS 层叠规则决定后者覆盖前者。这不是 bug,是设计使然:工具类是状态开关,不是数值堆叠器。
如果你本意是“顶部留 2,再加 6”,说明语义错了。应该拆成两个独立意图:u-mt-2 表示“与上一区块分隔”,u-mb-6 表示“为下方留出呼吸空间”。方向类必须严格分离:u-mt-* 只设 margin-top,不碰 margin-bottom;u-mb-* 同理。
- 禁止在同一元素混用相反方向修饰符,如
u-mt-2 u-mt-4,靠 lint 工具拦截 - 跨组件间距必须由父容器用外部修饰符控制,比如
.layout__area_margin-bottom-l,禁止子组件写margin-top去“对齐”另一个组件 - Flex/Grid 容器内别混用
margin和gap,行为不可预测,尤其在响应式断点切换时
跨组件与父子级间距必须由 Block 修饰符统一声明
当 .card 和 .button 相邻时,谁来决定它们之间的距离?答案不是它们自己,而是包裹它们的父块,比如 .page-section 或 .form-layout,并通过类似 .page-section__content_card-above-button 的修饰符声明意图。
常见错误是:.card 内部写了 margin-bottom: 1rem,.button 又加了 margin-top: 0.5rem——两者叠加,视觉间距变成 1.5rem,且无法被父级统一收口;更糟的是,把 .button 换到模态框里,这段 margin-top 就成了多余空白。
- 修饰符名必须体现布局语义(
_margin-bottom-l),而非数值(_mb-16)或组件名(_card-after-button) - CSS 实现必须绑定 CSS 变量:
.layout__area_margin-bottom-l { margin-bottom: var(--space-l); } - 避免修饰符叠加导致间距失控,比如
.card_margin-top-s _margin-bottom-m,实际生效的是两个方向的 margin,而不是“取最大值”
真正麻烦的从来不是写多少类,而是哪一层该声明哪一种间距意图——Block 修饰符是唯一可信的出口,其他地方写 margin 就是让系统开始松动。


















