Z-index 管理与堆叠
令牌化 z-index 阶与堆叠上下文,终结 z-index 军备竞赛。
响应式设计进阶
为什么
处处 z-index: 9999 是竞赛:每个新覆盖需更大数,模态最终在工具提示后。令牌阶加堆叠上下文意识使分层可预测。
StatCounter 2024 数据显示 58% 的网络流量来自移动端。CSS 容器查询(2023 基线)和 subgrid(2024 基线)消除了大多数媒体查询 hack,减少 30-50% 的响应式 CSS。
何时使用
有 3+ 重叠层(粘性头、下拉、模态、toast)时采用 z-index 阶。别等工具提示藏在头后的 bug。
如何做
1. 令牌阶 — --z-base: 0、--z-dropdown: 100、--z-sticky: 200、--z-modal: 300、--z-toast: 400
2. 步 100 — 留插入层空间(下拉在粘性上但模态下)无需重编号
3. 堆叠上下文 — 任何带 z-index 的定位元素,或 transform/filter/opacity<1,创建一个
4. 隔离 — 区段上 isolation: isolate 创建新堆叠上下文,包含其 z-index
5. portal — 模态/toast 渲染在 body 末 portal 以逃祖先堆叠上下文
6. 上下文内 — 子仅与同上下文同级竞争,非整页
7. 强制 — stylelint-declaration-strict-value 禁原始 z-index,仅允许 var(--z-*)
示例
:root {
--z-base: 0;
--z-dropdown: 100;
--z-sticky: 200;
--z-drawer: 300;
--z-modal: 400;
--z-toast: 500;
}
.header { position: sticky; top: 0; z-index: var(--z-sticky); }
.dropdown{ position: absolute; z-index: var(--z-dropdown); }
.modal { position: fixed; z-index: var(--z-modal); } /* 渲染在 portal */
.toast { position: fixed; z-index: var(--z-toast); } /* 渲染在 portal */
/* 隔离小部件使其内部 z-index 不泄漏 */
.widget { isolation: isolate; position: relative; }
/* stylelint — 禁原始 z-index */
"declaration-property-value-allowed-list": {
"z-index": ["/var\\(--z-/"]
}
常见问题
- ⚠魔数 — z-index: 9999 然后 99999 然后 999999,无人知谁赢
- ⚠模态在粘性头后 — 模态 z-index 低因在嵌套堆叠上下文
- ⚠opacity: 0.99 '修' 分层 — 意外创建堆叠上下文困住子级
最佳实践
- ✓用步 100 的令牌阶 — 留插入层空间无需重编号
- ✓顶层覆盖渲染在 portal — 完全逃祖先堆叠上下文
- ✓用 isolation: isolate 包含小部件 z-index — 内部不泄漏