骨架屏元素应使用独立 block 层级,命名为 o-skeleton,其子项为 o-skeleton__item、o-skeleton__avatar 等,不复用业务组件 bem 结构,实现物理隔离与语义化占位。

骨架屏元素该用哪个BEM层级?
骨架屏不是真实内容的复刻,而是结构示意,所以类名应反映「占位」语义,而非业务模块。别直接照搬 .product-card__title 这类真实组件的 BEM 结构——预加载阶段它还没数据,__title 也不渲染文字,只是个灰色矩形。
正确做法是按容器层级定义骨架结构:外层用 o-skeleton(o- 表示 object,表示这是一个独立可复用的占位对象),内部区块用 o-skeleton__item、o-skeleton__avatar、o-skeleton__text-line 等语义化子项。这些类名不依赖业务逻辑,只描述视觉区块类型。
-
o-skeleton是根容器,负责整体尺寸、动画和 fallback 行为 -
o-skeleton__item用于列表项级占位(如每条商品骨架) -
o-skeleton__text-line应带height和width可调参数,方便在不同上下文中复用(比如标题行高 20px,段落行高 16px)
如何避免 BEM 命名与真实组件冲突?
如果项目里已有 .product-card 模块,再写 .product-card--skeleton 看似合理,但会埋坑:CSS 优先级易失控,JS 切换状态时要同时操作两套类名,且骨架样式可能被 .product-card 的 font-size 或 padding 意外影响。
更稳妥的是物理隔离:骨架屏 CSS 文件独立引入(如 o-skeleton.css),所有类名以 o- 或 u-(utility)开头,并确保不依赖任何业务命名空间。
- 禁止在骨架样式中写
.product-card .o-skeleton这类组合选择器 - 如果必须嵌套在业务容器中(如
<div class="product-list"><div class="o-skeleton"></div></div>),用o-skeleton自身的display和margin控制布局,不靠父容器样式“帮忙” - 构建时可通过 PostCSS 插件自动为
o-类加哈希后缀,彻底规避全局污染风险
响应式骨架屏怎么用 BEM 表达断点差异?
BEM 本身不处理媒体查询,但你可以用修饰符表达不同视口下的结构变化。例如桌面端显示三列头像+文字,移动端只留一列头像——这不是“变体”,而是结构级差异,适合用 o-skeleton--mobile 这类修饰符控制显隐。
关键原则:修饰符只控制「是否渲染某区块」或「切换布局方向」,不用于微调尺寸。尺寸应由 o-skeleton__text-line 自身的内联 style 或 CSS 自定义属性控制(如 --line-height: 16px)。
- 用
o-skeleton--has-avatar替代o-skeleton__avatar--hidden,前者更符合“结构存在性”的语义 - 避免写
o-skeleton--sm/o-skeleton--lg,这种尺寸修饰符会让类名失去可读性,也难以维护 - 媒体查询规则统一收口在
o-skeleton.css底部,不分散在各业务文件中
预加载时机下 BEM 类名要不要动态生成?
不要。骨架屏通常由 HTML 模板直出(SSR)或 JS 在 DOMContentLoaded 前注入,此时 DOM 已存在,类名必须静态、确定、可预测。动态拼接类名(如 o-skeleton__${type})会导致 SSR 和 CSR 不一致,也可能让 CSS-in-JS 工具无法提取对应样式。
真正需要动态的只有少数几个行为:是否启用脉冲动画、是否显示边框、是否使用圆角。这些应该用自定义属性控制,而不是新增 BEM 类名。
- 用
style="--skeleton-pulse: 1.2s"控制动画时长,而非o-skeleton--pulse-fast - 用
data-skeleton-type="list"做 JS 行为区分(如懒加载触发逻辑),但不参与 CSS 样式定义 - 构建时若需差异化打包,应通过配置项生成不同版本的
o-skeleton.css,而不是运行时改类名
最常被忽略的一点:骨架屏的 BEM 类名一旦上线,就和真实组件的 DOM 结构强耦合。改一个 __text-line 的宽高,可能影响十几个页面的占位效果——所以它的 CSS 必须有明确的单元测试覆盖,不能只靠“看起来差不多”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











