header--fixed 修饰符必须直接作用于 header 块元素,表示其整体脱离文档流并固定于视口顶部;错误地应用于子元素会破坏 bem 语义、导致布局异常与层级错乱。

header--fixed 修饰符必须作用于 block 本身,不能加在子元素上
很多人误以为 header__nav--fixed 或 header__logo--fixed 能让整个头部固定,其实这是对 BEM 语义的破坏。BEM 中,--fixed 描述的是 header 这个块的整体行为状态——它是否脱离文档流、锚定视口顶部。这个状态属于块,不是某个内部元素。
常见错误现象:header__logo 看似“固定”了,但 header__nav 在滚动时消失;或者 JS 切换了子元素类名,却忘了同步控制 position: fixed 的生效范围。
-
header--fixed应直接加在<header class="header header--fixed"></header>上 - 对应 CSS 必须包含
position: fixed、top: 0、width: 100%和足够高的z-index - 避免给
header--fixed写height: auto—— 固定定位下高度需明确,否则可能塌陷或遮挡内容
使用 header--fixed 时必须同步处理 main-content 的 margin-top
当 header 变成 position: fixed,它就脱离了文档流,后续内容会顶到页面顶部,被遮盖。这不是 BEM 的问题,而是 CSS 定位的必然结果,但容易被忽略。
使用场景:移动端单页应用、后台仪表盘、长表单页——这些地方一旦启用 header--fixed,main-content 就必须主动“让出空间”。
- 推荐做法:为
main-content设置margin-top,值等于header的视觉高度(如60px) - 不要依赖 JS 动态计算高度——CSS 中用变量更稳定:
:root { --header-height: 60px; },然后.main-content { margin-top: var(--header-height); } - 如果
header高度响应式(比如移动端缩为48px),修饰符应配套响应:header--fixed-mobile或用媒体查询内联margin-top
header--fixed 不等于 sticky,别混用触发条件
position: sticky 和 position: fixed 行为完全不同。header--fixed 这个修饰符名,按 BEM 原则就该只对应 fixed 行为。若实际用了 sticky,语义就错位了——用户看到类名以为是常驻,结果一滚动就消失。
性能影响:移动端 position: sticky 在部分 Android WebView 中兼容性差,且滚动时有重绘抖动;fixed 更可控,但需手动处理滚动穿透(比如弹窗时禁止 body 滚动)。
- 如果真要用 sticky,应定义新修饰符:
header--sticky,并确保父容器有overflow-y: hidden或明确的高度限制 -
header--fixed的 CSS 中禁止出现top: 0以外的top值(如top: 10px),那已不是“固定于顶部”的本意 - 不要在同一个
header上同时写header--fixed header--sticky—— 状态冲突,样式不可预测
header--fixed 下的子元素需注意 z-index 层级关系
固定定位的 header 会创建新的层叠上下文(stacking context)。如果它的子元素(如下拉菜单、搜索框弹层)也用了 z-index,但值不够高,就会被同级的 main-content 内容盖住。
容易踩的坑:只给 header 设了 z-index: 999,却没给 header__dropdown 设更高值,导致下拉菜单被卡片、模态框遮挡。
-
header--fixed的z-index推荐设为1000起步,留出余量 - 所有需要浮在最上层的子元素(如
header__search-dropdown、header__notification-bell),z-index至少比header高10 - 避免用
z-index: 999999这类魔数——用变量管理:--z-header: 1000;、--z-header-dropdown: calc(var(--z-header) + 10);
--fixed,而是忘记它带来的连锁反应:内容偏移、层级覆盖、响应式断点错配。











