React 项目中的容器划分规范:从架构到落地命名(CSS Modules / Tailwind 版)
本文面向 React 项目实践,系统讲清两件事:
- 容器(Container)到底怎么划分:页面、布局、模块、组件各层职责边界是什么?
- 在 CSS Modules / Tailwind 下怎么命名与组织容器类:做到可读、可维护、可复用。
如果你经常在代码评审里看到“又多包了一层 div”,或者 PRD 里写“外面那一层”,这篇文章会帮你把命名和分层体系建立起来。
一、React 中“容器”的核心概念:职责驱动,不是 div 驱动
在 React 项目里,“容器”本质不是 DOM 元素,而是承担某类职责的层。
同一个容器可能是
divmain/section一个容器的职责通常来自以下一种或多种:
- Layout:结构布局(header/sidebar/content)、flex/grid、响应式
- Spacing:统一边距、对齐、最大宽度
- Scroll:滚动区域、sticky、可视区控制
- State / Data:请求、缓存、分页、筛选、表单状态
- Interaction Layer:overlay、modal、tooltip 等脱离文档流的层
二、React 项目推荐的容器层级(由外到内)
目标:每一层“能说清楚它为什么存在”。
一个“可解释”的页面结构通常是:
<RoutePage> <PageShell> // 页面框架:头/侧/底(可选) <PageContainer> // 控制 max-width / padding / 居中(常用) <ContentLayout> // grid / flex 结构(可选) <Section> // 业务区块:可拆分、可复用 <FeatureModule> // 特性模块:带状态/逻辑(可选) <Widget/> // 纯 UI 组件 ```1) Route Page(路由页组件)
命名:
UsersPage.tsxUserDetailPage.tsx- 与路由绑定、组装页面
- 放页面级 meta、埋点、权限判断
- 不做复杂 UI 细节
2) PageShell(页面壳/框架)
命名:
DashboardShellAppShell- 页头、侧边栏、底部、全局布局
- 处理整体布局栅格(例如 sidebar + main)
3) PageContainer(页面容器)
命名:
PageContainerContainer- 最大宽度、居中、统一 padding
- 通常是全局通用组件(复用率高)
4) ContentLayout(内容布局容器)
命名:
TwoColLayoutSplitLayoutGridLayout- 仅布局(grid/flex),不带业务含义
5) Section(业务区块容器)
命名:
ProfileSectionFiltersSection- 一个页面中的一块区域
- 通常对应一个子标题/卡片块
6) FeatureModule(功能模块容器,Container Component)
命名:
UserListContainerUserFiltersContainer- 请求数据、管理状态、拼装 UI
- 将“数据与展示”解耦:容器负责数据,子组件负责展示
三、React 中常用容器划分规范(建议直接写进团队规范)
规范 A:页面组件只做“组装”,业务逻辑下沉到 Feature
Page 负责:
- 布局骨架
- 把 Feature 按区域放进去
Feature 负责:
- 请求、分页、筛选、表单、状态机
- 暴露清晰的 props 给 UI
✅ 优点:页面稳定、模块可复用、测试更容易。
规范 B:布局容器和业务容器分离
不要把
display: gridmax-widthpadding- :只管宽度/边距code
PageContainer - :只管 grid/flexcode
Layout - :只管业务语义与内容code
Module/Section
✅ 优点:视觉改版时只动 layout/container,不伤业务组件。
规范 C:滚动容器明确标注(特别是后台系统)
当你使用“局部滚动”而不是 body 滚动时,一定要显式命名:
- code
ScrollArea - code
Scrollable - code
ContentScroll
并且统一管理:
- 谁滚动
- 哪些元素 sticky
- scroll restoration 是否需要
规范 D:Overlay 层必须单独抽象(Portal + z-index 体系)
浮层相关组件建议统一从
OverlayProviderPortalRoot命名上要明确:
- code
Overlay - code
Backdrop - code
ModalLayer - code
FloatingLayer
四、CSS Modules 下的容器命名策略(强烈推荐)
CSS Modules 的关键是:类名局部作用域,你不需要用很长的前缀避免冲突,但仍然要让“语义清晰”。
1) 建议的命名模型:code角色 + 可选修饰
角色 + 可选修饰- code
container - code
wrapper - code
layout - code
content - code
section - code
header - code
body - code
footer - code
scrollArea - code
overlay - code
backdrop
示例(UserList.module.css):
.container {}
.header {}
.body {}
.footer {}
.filtersSection {}
.tableSection {}
.scrollArea {}
.emptyState {}
.loadingState {}一个模块的 CSS Modules 文件里,推荐出现一个
作为根类,其余按区域拆分。codecontainer
2) 状态类统一用语(推荐)
在 CSS Modules 中状态类非常好用:
- code
isLoading - code
isEmpty - code
isDisabled - code
isActive - code
hasError
示例:
.container {}
.isLoading {}
.hasError {}在组件中:
<div className={clsx(styles.container, loading && styles.isLoading)} />3) 结构类命名:遵循“DOM 结构可视化”
你看到类名就能在脑内画出 DOM:
- ,code
header,codetoolbarcodeactions - ,code
content,codemaincodeaside - ,code
left(仅在布局组件中出现)coderight - ,code
row(仅在 grid/flex 布局组件中出现)codecol
4) 不推荐的 CSS Modules 命名(反例)
❌
box1box2leftBoxwrapwrap2containerAcontainerB五、Tailwind 下的容器命名策略(核心:命名组件,而不是命名 class)
Tailwind 的世界里,你往往不会写
.container {}<div className="mx-auto max-w-6xl px-6">但当页面复杂后,你必须用“命名组件/变量”来替代“命名 class”,否则 class 会爆炸。
策略 1:把“容器语义”抽成组件(最推荐)
例如统一页面容器:
export function PageContainer({ children }: { children: React.ReactNode }) {
return <div className="mx-auto w-full max-w-6xl px-6">{children}</div>;
}统一 section:
export function Section({ title, children }: { title?: string; children: React.ReactNode }) {
return (
<section className="rounded-2xl border p-4">
{title && <h2 className="mb-3 text-lg font-semibold">{title}</h2>}
{children}
</section>
);
}Tailwind 下最好的“命名策略”是:把语义放到组件名里。
策略 2:对重复 class 使用常量/组合函数
当不想抽组件时,用常量也行:
const pageContainer = "mx-auto w-full max-w-6xl px-6";
const sectionCard = "rounded-2xl border bg-white p-4";策略 3:用 tailwind-variants / clsx 做语义化变体
(你不用立刻上库,思路先记住)
- : size / tone / layoutcode
variant - : loading / disabled / selectedcode
state
策略 4:用 Tailwind 的约定命名“语义块”
即使不写 CSS,你也要在组件层表达:
- code
PageShell - code
ContentLayout - code
Sidebar - code
Toolbar - code
ScrollArea - code
Overlay
Tailwind 的可维护性来自组件分层,而不是 class 的整洁。
六、CSS Modules vs Tailwind:容器命名的统一原则
无论你用哪一种,统一遵循这条:
命名表达职责,不表达实现。
✅
scrollAreaoverflowAutoDiv✅
layouttwoColLayoutgridDiv七、推荐的团队级“容器词汇表”(直接贴到规范里)
结构容器
- ,code
page,codeshell,codecontainer,codecontent,codelayout,codesectioncodemodule
组件包裹
- ,code
wrapper,coderoot,codeinnercodeouter
交互 / 浮层
- ,code
overlay,codebackdrop,codelayer,codeportalRootcodefloating
滚动与定位
- ,code
scrollArea,codestickyHeader,codeaffixcodeviewport
区域与动作
- ,code
header,codetoolbar,codeactions,codebody,codefooter,codeasidecodemain
八、一个完整示例(React + 容器分层 + 命名)
UsersPage
└── DashboardShell
└── PageContainer
├── PageHeaderSection
├── FiltersSection
└── UsersTableSection
└── UsersTableContainer
└── UsersTableView你会发现:
- Page:只组装
- Shell/Container/Layout:只管结构
- Section/Module:表达业务区域
- Container Component:承载数据逻辑
- View/UI:纯展示
九、落地检查清单(写代码前 10 秒自检)
- 这一层存在的理由是什么?(宽度/布局/滚动/状态/浮层?)
- 它是否应该抽为通用容器组件?
- 命名是否表达职责?(container/section/layout/overlay/scroll)
- Tailwind 中是否出现“重复 class”?是否该抽组件/常量?
- CSS Modules 中是否出现“无语义命名”?(box1/wrap2)
结语
容器分层与命名不是“洁癖”,它解决的是三个核心问题:
- 让页面结构可解释
- 让布局与业务解耦
- 让多人协作沟通成本下降
当你把
container / layout / section / module / overlay / scrollArea你可以继续扩展的方向(可选)
- React Server Components / Next.js App Router 下的容器分层
- Design System 中容器组件库的抽象方法
- z-index 管理与 overlay 体系(Portal Root 规范)
---
如果你还想更“工程化”,我可以再给你补两块(都很实用,直接能进团队规范):
1) **一个推荐的目录结构**(pages/features/components/layouts/styles)
2) **一套容器组件库模板**(PageContainer / Section / ScrollArea / Overlay)带 TypeScript 类型
你要我继续把这两块也写成 md 吗?