oocss是面向对象的设计思想,bem是可落地的命名约定:oocss专注样式组织(分离结构与皮肤、容器与内容),不限定类名形式;bem通过block__element--modifier三段式强制作用域隔离与单类匹配,二者混用时bem管组件边界,oocss管原子级视觉微调。

OOCSS 和 BEM 不是同一类东西:OOCSS 是一种面向对象的设计思想,BEM 是一套可落地的命名约定。混淆它们,容易在项目里既写不出清晰结构,又用不好工具类。
OOCSS 不规定 class 名怎么写,只管“怎么组织样式”
OOCSS 的核心是两个原则:分离结构和皮肤、分离容器和内容。它不强制你用 __ 或 --,也不要求每个 class 必须带 block 前缀。一个 .box 可以是结构(定义 padding/margin/display),一个 .box--success 是皮肤(定义背景色、边框色),组合起来就是 class="box box--success"。
常见错误现象:
- 把
.btn当成“块”,然后硬套 BEM 规则写成btn__text——这违背 OOCSS “结构可复用” 的本意 - 在同一个 class 里混写布局 + 颜色 + 圆角,比如
.card-header同时控制 padding、font-size、border-bottom —— 这会让后续换主题或改间距变得困难
真正关键的不是名字长不长,而是你能不能一眼看出这个 class 负责哪一层职责。
BEM 强制用三段式命名,天然隔离作用域
BEM 的 block__element--modifier 不是风格偏好,是作用域控制手段。它默认拒绝嵌套选择器,也拒绝靠 DOM 路径定位样式。比如 .modal__close--disabled 这个 class,不管它在 <div class="modal"> 里还是 <code><section></section> 里,样式都生效且不会影响其他 close。
使用场景明确:
- 你在写 Vue/React 组件库,需要确保
el-button__icon不会和业务代码里的button__icon冲突 - 团队新人刚来,靠 class 名就能猜出 HTML 结构,不用翻源码
- 你想禁用 CSS 权重竞争,所有样式都基于单 class 匹配
参数差异上,BEM 推荐加统一前缀(如 el-、myapp-),而 OOCSS 工具类通常无前缀(f14、mt-8),这是设计出发点不同导致的自然结果。
混用时,BEM 管边界,OOCSS 管微调
真实项目里,90% 的成熟方案都是混合用:用 BEM 划清组件边界,用 OOCSS 思想写内部原子样式。例如:
.card {}
.card__header {}
.card__body {}
<p>/<em> 这些是 OOCSS 工具类,只负责视觉原子属性 </em>/
.f16 { font-size: 16px; }
.p-12 { padding: 12px; }
.bb-c { border-bottom: 1px solid #ccc; }</p>
但要注意一条铁律:card__header 的 padding 和 display 必须由 BEM class 控制,不能靠 p-12 或 flex 工具类去覆盖——否则组件就失去了封装性,别人改工具类会意外破坏你的布局。
最容易被忽略的点是:没人告诉你哪个 class 该归 BEM,哪个该归 OOCSS。这不是语法问题,是团队对 UI 粒度的理解问题。比如 input--search 是修饰符还是独立 skin?form-group 是 block 还是 OOCSS structure?答案不在规范里,在你们 daily sync 的白板上。











