CSS 自定义属性 7 个有用的小知识
CSS 自定义属性(又称 CSS 变量 - CSS variables)允许我们在样式表中存储并复用属性变量。如果你还不熟悉它们,你可能在 CSS 预处理器变量中使用过它们。这些天我正在我的工作中大量使用自定义属性,所以我想在这里总结一些使用情况。
这篇文章不是关于 CSS 自定义属性如何工作的深度教程,如果需要了解一些基础,阅读下面推荐的这些资源:
颜色函数
CSS 自定义属性不仅仅是属性值,它们也可以用于存储一组数据。一个常用的例子是 CSS 颜色函数值。HSLA 特别适合 CSS 自定义属性,允许开发者混合颜色时使用高级别的控制。
.some-element {
background-color: hsla(var(--h, 120), var(--s, 50), var(--l, 50), var(--a, 1));
}
.some-element.darker {
--l: 20;
}
我们也可以做一些非常酷的事像计算辅助颜色集。这篇文章是一篇使用 CSS 自定义属性操作颜色的深度教程,Sara Soueidan 也同样有一篇很棒的同类文章。
简写属性
如果你使用像 animation
这样的简写属性,并且需要更改不同元素的值,然后重写整个属性可能是错误方式并且额外的操作很繁重。使用 CSS 自定义属性可以很容易在简写属性中调整单个值:
.some-element {
animation: var(--animationName, pulse) var(--duration, 2000ms) ease-in-out infinite;
}
.some-element.faster {
--duration: 500ms;
}
.some-element.shaking {
--animationName: shake;
}
重复值
考虑我们有一个元素在它的内边距拥有相同的值,但是相同的值在它的外侧。像下面这样可能有一点单调乏味,特别是需要我们调整这些边距值的时候:
.some-element {
padding: 150px 20px 20px 20px;
}
@media (min-width: 50em) {
padding: 150px 60px 60px 60px;
}
使用 CSS 自定义属性意味着我们仅需要更改一次边距值。甚至,如果它是整个网站使用的标准值,我们可以在变量集中声明它,如配置文件或者网站的 design tokens。
:root {
--pad: 20px;
}
@media (min-width: 50em) {
:root {
--pad: 60px;
}
}
.some-element {
padding: 150px var(--pad) var(--pad) var(--pad);
}
复杂计算
CSS 自定义属性可以存储计算值(用于 calc
函数),甚至可以用于计算其它自定义属性。一个例子是先前提到的计算辅助颜色。另一个是计算属性的相反值。我使用 CSS 自定义属性为 CSS Tricks 写过一篇文章 calculating the reverse of an easing curve。
当需要计算路径 path 的相反量时,我经常与 clip-path
一起使用 CSS 自定义属性。下面的代码是使用两个伪元素的计算剪切路径分割一个元素。
<h1 style="--text: 'His Dark Materials'"><span>His</span> Dark Materials</h1>
<style>
.element {
--top: 20%;
--bottom: 80%;
--gap: 1rem;
--offset: calc(var(--gap) / 2);
}
.element::before {
clip-path: polygon(calc(var(--top) + var(--offset)) 0, 100% 0, 100% 100%, calc(var(--bottom) + var(--offset)) 100%);
}
.element::after {
clip-path: polygon(calc(var(--top) - var(--offset)) 0, calc(var(--bottom) - var(--offset)) 100%, 0 100%, 0 0);
}
</style>
交错动画
如果我们想要为一些子元素添加交错动画,我们可以通过简单声明自定义属性为每个元素优雅地设置不同的 animation-delay
值:
<div class="el"></div>
<div class="el"></div>
<div class="el"></div>
<style>
.el {
--delay: calc(var(--i, 0) * 500ms);
animation: fadeIn 1000ms var(--delay, 0ms);
}
.el:nth-child(2) {
--i: 2;
}
.el:nth-child(3) {
--i: 3;
}
</style>
具体效果查看 codepen.io
无奈的是我们当前不得不分配固定数量的变量,因为如果我们有不定数量的子元素就会有问题(无法分别声明延时值)。Splitting JS 是一个很棒的 JavaScript 库,其可以分配元素索引作为变量,在这种交错动画中非常有用。但是这导致不得不使用 JS。
Adam Argyle 最近提交了一个提案,该提案提出两个新的 CSS 功能 sibling-count()
和 sibling-index()
,这将是一个改变游戏规则,使得一大堆的可能的 CSS 新的东西。目前,它们还远未被任何浏览器所采用,但这将是一个非常强大的功能,因此请密切注意。
响应式布局网格
之前写过关于响应式网格的博客文章,但是自定义属性可以帮助我们使复杂布局更容易管理。假设我们有一个 8 列的网格,现在我们想要更改为标准的 12 列网格:
:root {
--noOfColumns: 8;
}
@media (min-width: 60em) {
:root {
--noOfColumns: 12;
}
}
.grid {
display: grid;
grid-template-columns: repeat(var(--noOfColumns), 1fr);
}
每当我们想要更新列数时,我们都不需要写入整个属性值 — 我们可以使用自定义属性。这是一个相对简单的示例,但是如果我们有一个更复杂的网格,它可能会更加有用。而且该技术也可以应用于轨道尺寸或物品放置位置。
浏览器前缀
在某些浏览器中一些属性(如 clip-path
)仍需要添加浏览器前缀 — 尽管值得庆幸的是,这个数字正在下降。如果需要编写浏览器前缀,然后要更改属性值,则还需要确保在前缀属性上也进行更改。使用自定义属性,我们可以改写为:
.some-element {
--clip: polygon(0 0, 100% 0, 50% 100%, 0 100%);
-webkit-clip-path: var(--clip);
clip-path: var(--clip);
}
现在我们只有一个地方需要更改。
总结
这些远非自定义属性的唯一用途,但我通常会发现它们是我在工作流程中所追求的,并且可以帮助你提高代码的效率和可维护性。毫无疑问,你将发现自己的更多用途!
本文由 吳文俊 翻译,原文地址 7 Uses for CSS Custom Properties