根本问题是未将列表项视为独立可复用单元;BEM 仅显性化该意图,.list__item 必须自包含、不依赖 DOM 结构与父级状态,样式只控自身尺寸/内边距/行高,外距由父容器统一管理。

为什么直接写 .list li 会让人改着改着就崩溃
因为样式污染和耦合太强:一个页面里多个列表共用 li,改侧边栏的 li 间距,结果轮播图也跟着缩进;更糟的是,团队里有人加了 ul li a { font-size: 12px },你根本不知道它从哪冒出来的。
根本问题不是“要不要用 BEM”,而是“有没有把列表项当作独立可复用单元来设计”。BEM 只是让这个意图显性化。
-
.list__item必须能脱离父容器单独存在——比如复制到另一个页面,不改 class 就能渲染出一致外观 - 避免使用元素选择器嵌套:
.list ul li或.list > li都不行,它们绑定 DOM 结构,一旦换成div包裹就失效 - 状态类名必须挂载在
__item上,而不是靠父级传递:.list--loading .list__item是错的;应该用.list__item--loading
怎么给 list__item 写真正可复用的样式
关键不是“写得多”,而是“约束得准”:只控制自身尺寸、内边距、文字行高、基础颜色,其他全交给修饰符或上下文。
- 默认
.list__item只设padding和line-height,不设margin—— 外边距由父容器(.list)统一控制,比如用gap或flex-direction: column - 图标、徽标、操作按钮等附加内容,必须用
--with-icon、--with-badge这类修饰符控制,而不是靠子选择器.list__item .icon - 如果需要不同密度(紧凑/宽松),不要写两套
.list__item,而是加修饰符:.list--dense .list__item→ 改padding和font-size,且只影响自身
.list__item {
padding: 8px 12px;
line-height: 1.4;
}
.list__item--with-icon {
padding-left: 32px; /* 图标占位 */
}
.list--dense .list__item {
padding: 4px 8px;
font-size: 12px;
}遇到 display: flex 列表时,BEM 的坑在哪
Flex 容器常被误当成“样式层”,其实它是布局契约。一旦你把 .list 写成 display: flex,所有子项就自动获得 flex 项目行为,这时候再给 .list__item 加 width: 100% 就可能冲突。
立即学习“前端免费学习笔记(深入)”;
- 别在
.list__item里写flex相关属性(flex-grow、align-self等),这些属于容器职责 - 如果某类列表项需要撑满(比如导航菜单项),用修饰符:
.list__item--full-width,内部只设flex: 1,不碰width - 响应式断点要落在
.list上,而不是.list__item:移动端改成垂直排列,是.list--mobile .list__item,不是.list__item--mobile
当后端返回的数据结构不统一,怎么让 list__item 依然稳定
真实场景里,API 可能返回 { id, title, url },也可能返回 { id, name, href, status },甚至字段名大小写都不一致。这时候硬写 .list__item__title 就容易漏渲染或报错。
- 模板层不依赖字段名,用统一映射:前端接收到数据后,先 normalize 成固定结构
{ id, label, link, meta },再传给列表组件 -
.list__item内部只认标准化字段,不写.list__item__url或.list__item__href,统一用.list__item__link - 空状态处理放最外层:用
.list--empty控制整个容器,而不是让每个.list__item自己判断label是否为空
扩展性真正的考验不在 CSS,而在你愿不愿意把“不确定”拦在样式层之外。一旦开始用字段名写 class,就等于把后端接口细节焊进了 UI 层。


















