base层只放根字号、基础颜色变量和全局排版规则;layout层定义容器约束而非页面结构;module层命名须带业务语义,禁止跨层引用变量。

Base 层该放什么,别塞重置样式
很多人把 normalize.css 或一堆 * { margin: 0; padding: 0 } 往 _Base 里一扔就完事,结果后续所有组件的内边距、行高全得反复覆盖。Base 不是清道夫,是基础契约层。
它只该包含三类东西:根字号与单位基准(html 的 font-size)、基础颜色变量(--color-text、--color-border)、以及真正全局生效的排版规则(如 p、h1 到 h6 的默认行高和间距)。重置行为属于 Layout 或更底层的初始化逻辑,不该污染 Base。
-
_Base里避免出现任何选择器带具体语义(比如.btn、.card),也不该有媒体查询 - 颜色变量必须是中性、可复用的抽象名,不是
--red-error这种场景化命名(那是 Module 层的事) - 如果项目用 CSS 自定义属性做主题切换,Base 是唯一允许声明
:root变量的地方
Layout 层不是“页面结构”,而是容器约束系统
看到 _Layout 就写 .header、.main、.footer?这是最常见误用。Layout 层不描述页面区域,而是定义「容器如何承载内容」——比如最大宽度、居中方式、栅格断点、安全边距(env(safe-area-inset-*))等。
它的核心是「布局上下文」,不是视觉区块。一旦你发现某个 class 同时出现在多个页面且作用完全一致(比如统一的卡片容器宽度限制、响应式列数控制),它才该进 Layout。
立即学习“前端免费学习笔记(深入)”;
- 所有栅格类(如
.grid-cols-3、.container)属于 Layout,但.page-header不属于 - Layout 文件里可以有媒体查询,但不能有颜色、字体、圆角等表现细节
- 移动端适配相关的
padding(如顶部留出状态栏空间)也归 Layout,不是靠 JS 动态加 class
Module 层命名必须带业务语义,拒绝通用词
写个按钮叫 .button,写个卡片叫 .card,上线后三个月,全项目出现二十个不同版本的 .button,没人敢动。Module 层的 class 名不是 HTML 标签复述,而是业务角色声明。
比如登录页的提交按钮,应该叫 .login-form-submit;商品列表里的价格标签,叫 .product-card-price。名字越长越准,因为 Module 的本质是「这个东西在当前上下文里干什么」。
- 禁止使用
.btn、.item、.wrapper这类无上下文的泛称 - Module 文件里可以有伪类(
:hover)、状态类(.is-loading)、甚至小范围媒体查询,但不能影响其他 Module - 如果两个 Module 外观高度相似(比如后台和前台的表格),宁可复制一份样式,也不要强行抽成一个通用
.table
层级之间不允许跨级引用,尤其别在 Module 里 import Base 变量
看似方便的 @import '../Base/variables.css'; 在 Module 文件里出现,等于把整个样式系统的耦合度拉满。Base 变量本该通过 :root 注入全局,Module 只需用 var(--color-primary),而不是手动引入。
真正的分层失效,往往始于一个“顺手”的 import。CSS 预处理器(如 Sass)的 @use 也不是万能解药——Module 层只能 @use Layout 提供的栅格 mixin,不能 @use Base 的颜色 map。
- 构建工具(如 PostCSS、Vite)应配置路径别名,让所有文件统一从
src/css/下按逻辑路径引用,而非相对路径 - 如果发现某个 Module 需要频繁修改 Base 变量来适配,说明它其实承担了 Layout 职责,该重构
- 最隐蔽的坑:用 JS 动态读取
getComputedStyle(document.documentElement).getPropertyValue('--color-bg')——这会让 CSS 变量失去热更新能力,调试时值永远滞后
分层不是目录建得漂亮就行,是每一行声明都清楚自己在哪一层、能碰什么、不能碰什么。稍不注意,_Module 就会变成新的全局污染源。










