自定义属性和现代 CSS

你选择一个品牌蓝色,将其输入四十条不同的规则中,然后发布网站。一个月后营销部门希望使用一个略有不同的蓝色。现在你必须查看每个样式表,希望能找到全部四十处,而不会漏掉那两个大写拼写的地方。自定义属性解决了这个问题:你给颜色命名一次,在任何地方使用这个名字,然后在一个地方修改它。这个单一习惯是主题化、设计令牌和能够经受住重新设计的样式表的开始。
声明和使用变量
一个**自定义属性**是一个你给它起名字以便重复使用的值。你用两个破折号写名字,将其设置为一个值,然后稍后用 var() 读回它:
:root {
--color-brand: #2563eb; /* 在一个名字下声明值一次 */
}
.button {
background: var(--color-brand); /* 在这里读回它 */
}
.link {
color: var(--color-brand); /* 在这里也读回,相同的值 */
}--color-brand 是名字(两个破折号是必需的),var(--color-brand) 是你如何使用它。在 :root(即 <html> 元素,页面的顶部)声明它会使名字在任何地方都可用。修改 :root 上的那一行,每个读取它的规则都会更新。
--color-brand 这样的形式,然后用 var(--color-brand) 读回它。把它放在 :root 上这样整个页面都能使用它。修改那一行,每个读取这个名字的规则都会与它一起更新。 它们级联和继承
如果你在另一种语言中使用过变量,下一部分是个惊喜:自定义属性不是固定的。它遵循与任何其他 CSS 属性相同的规则,这意味着它**继承**到子元素,你可以在一个地方给它一个不同的值而不触及其余部分。
:root {
--color-text: #1f2937; /* 整个页面的默认值 */
}
.callout {
--color-text: #92400e; /* 一个不同的值,仅在 .callout 内部 */
color: var(--color-text);
}
p {
color: var(--color-text); /* 通常是深灰色,在标注内是琥珀色 */
}相同的 var(--color-text) 在大多数段落中给你深灰色,但在标注内是琥珀色,因为标注设置了它自己的值。这就是使主题化成为可能的原因,你在 CSS 如何工作 中看到了它背后的级联。
var(--color-text) 可以是大多数段落中的灰色,在标注内是琥珀色。在容器上重新定义名字,其中的所有东西都会获取新值。 回退值和 calc()
var() 可以取第二个值,仅在自定义属性从未设置时使用。这是**回退值**,它会在令牌缺失时保持规则工作:
.card {
gap: var(--gap, 1rem); /* 如果 --gap 存在则使用它,否则使用 1rem */
}你也可以使用 calc() 对自定义属性进行数学运算。如果你有一个基础间距值,你可以从它构建一个更大的值,而不是硬编码第二个数字:
:root {
--space-md: 16px;
}
.section {
padding: calc(var(--space-md) * 2); /* 32px,从基础派生 */
}像这样派生值意味着对 --space-md 的一个改变会波及所有基于它的东西。
var(--gap, 1rem) 在令牌存在时使用它,不存在时回退到 1rem,所以当值缺失时规则保持工作。而 calc() 让你从令牌构建值,像 calc(var(--space-md) * 2) 一样加倍基础间距。改变基础,所有基于它的东西都会跟随。 主题化
因为自定义属性可以在树的下方重新定义,你可以通过在一个类下改变令牌来构建暗色主题,并将每个组件规则单独留下:
:root {
--color-bg: #ffffff;
--color-text: #1f2937;
}
.theme-dark {
--color-bg: #0f172a; /* 相同的名字,新值 */
--color-text: #e2e8f0;
}
body {
background: var(--color-bg);
color: var(--color-text);
}将 class="theme-dark" 添加到页面,每个读取 --color-bg 或 --color-text 的规则都会翻转到暗色值。你从未接触过 body 规则,或任何组件,来做主题切换。这是将 颜色 命名为令牌而不是直接写入十六进制代码的回报。
.theme-dark 这样的类下有不同的值。设置 class="theme-dark",每个读取那些令牌的规则都翻转,不编辑一个单一组件。这就是为什么你将颜色命名为令牌而不是直接在每个规则中输入十六进制代码。 
