How to Manage Z-index

一个简单聪明的方法让你永远不用烦恼管理 Z-index 的问题

前言

最近看到一篇:Never Get Bit by z-index Again🔗 文章,作者提到用 CSS Variable 来赋予相对而非绝对数值的 z-index 值,真是优雅简洁的方法!完美的发挥了 CSS 变量的优势,促使我写下这篇文章。

问题背景

在许多情况下,我们需要调整不同元素的 z-index,以确保它们在叠加时显示的顺序是正确的。但使用固定的数值通常会导致代码的脆弱性,尤其是在大型项目中,不同部分可能会因为 z-index 冲突而导致难以追踪和维护的问题。通常会设置一个规范文件来统一规范数值,例如 Bootstrap 的 z-index 写成文件是这样规范的:

dropdown: 1000;
sticky: 1020;
fixed: 1030;
modal-backdrop: 1040;
offcanvas: 1050;
modal: 1060;
popover: 1070;
tooltip: 1080;

但只要是修改到代码都会需要查看这张表单,并且确保我们的数值不会和其他元素冲突。会需要不断的维护确保个别数值的关系正确:

  1. 文件与代码需相互同步
  2. 需要时刻确保数值间的权重正确

解决方法

一、解决代码与文件不同步问题

幸亏在今日原生的 CSS 变量有着很好的支援🔗,我们可以透过 CSS 变量直接定义 z-index 的数值解决了「需要额外文件或预处理器甚至是 JavaScript 来管理」这件事。

:root {
--dropdown-zindex: 1;
}
.dropdown {
/* 直接在 CSS 内引用定义 \O/ */
z-index: var(--dropdown-zindex);
}

二、解决数值间的权重问题

透过 CSS 变量的方式可以直接在代码中引用变量,而不需要再去查看文件。但是还是需要确保数值间的权重正确,这时候我们可以透过 CSS calc()🔗 来解决这个问题。

:root {
--dropdown-zindex: 1;
--sticky-zindex: calc(var(--dropdown-zindex) + 1);
}

为什么是 +1?因为 z-index 必须是整数,所以我们可以透过 +1 来确保 sticky 永远高于 dropdown,当然也可以抽离这个数值自行统一定义。

:root {
--gap-zindex: 10;
--dropdown-zindex: 1;
--sticky-zindex: calc(var(--dropdown-zindex) + var(--gap-zindex));
}

如此一来我们透过完全原生的方式建立了一个简单的 z-index 管理系统,不需要额外的文件或预处理器,也不需要 JavaScript,只需要一点点的 CSS 变量与计算就可以了。

结论

赋予相对的关系而非绝对的数值,让我们强烈联系元素之间的关系,而非取决于某个魔法数字

相较于给予绝对的数值,通过相对的关系来管理 z-index 让我更关注在「这个元素会放在那些元素之间」而非要去记住一个死数字,回归了使用 z-index 原先想达成的用意。

延伸阅读