CSS变量(自定义属性)实用指南

栏目: CSS · 发布时间: 6年前

内容简介:像 Sass 和 Less 这样的预处理器有助于保持CSS代码的组织和可维护性。 通过变量,混合,循环等特性 – 为CSS编码添加动态功能 – 有助于最大限度地减少重复并加快开发速度。近年来,一些动态特性已经开始成为 CSS 语言本身的一部分。在本文中,您将了解如何开始将CSS变量集成到CSS开发工作流程中,让你的样式表更好维护,且
CSS变量(自定义属性)实用指南

像 Sass 和 Less 这样的预处理器有助于保持CSS代码的组织和可维护性。 通过变量,混合,循环等特性 – 为CSS编码添加动态功能 – 有助于最大限度地减少重复并加快开发速度。

近年来,一些动态特性已经开始成为 CSS 语言本身的一部分。 CSS变量 – 官方的术语为 “自定义属性” – 已经已经加入规范并且具有很好的浏览器支持,而 CSS mixins 目前正在开发中

在本文中,您将了解如何开始将CSS变量集成到CSS开发工作流程中,让你的样式表更好维护,且 减少重复

让我们一起深入了解吧!

什么是CSS变量?

如果您使用过任何编程语言,那么您已经熟悉了变量的概念。变量用于存储和更新你的程序所需要的值,以便使它运行。

例如,请考虑以下JavaScript代码段:

let number1 = 2;
let number2 = 3;
let total = number1 + number2;
console.log(total); // 5
number1 = 4;
total = number1 + number2;
console.log(total); // 7

nubmer1number2 是两个变量,分别存储着数字 2 和 3 。

total 同样是变量,存储着 number1number2 之和。在这里它的值就是 5。你可以动态地修改变量里的值,并在程序中使用它们。在上面的代码中,我把 number1 的值更新为 4,然后再进行求和。使用相同的变量,这个时候 total 里存储的值就不再是 5 ,而是 7 了。

变量的好处在于你可以把值存储在一个地方,然后在你需要的地方修改它。这样你就不用在程序的不同地方为不同的值添加不同的变量: 所有变量更新使用同一个存储地址,比如你的变量。

CSS在很大程度上是一种声明式的语言,缺乏动态性。你也许会认为,让 CSS 拥有变量,似乎让上面的说法自相矛盾。如果前端开发仅仅关注语义,那可以这么说。幸运的是,Web的编程语言很像生活中的语言,它们会随着周围环境和实践需求而不断进化与适应。CSS也不例外。

总而言之,变量已经成为 CSS 中令人激动的实现,你很快也会发现,对于这个厉害的新技术,学习和使用起来都非常直观。

使用CSS变量有什么好处?

使用CSS变量的好处,跟在其他编程语言中使用变量的好处没什么大的区别。

以下是规范对此的说法:

[使用CSS变量]可以更容易地阅读大文件,因为看似任意的值,现在具有信息性名称,并且使此类文件更容易编辑,且更不容易出错,因为,你只需要在自定义属性中改变一次值,所有应用了这个变量的地方都会自动跟着一起改变。 W3C 规范

换句话说:

通过给变量起一个对你来说在项目中有意义的名字,你能更容易的管理和维护你的代码。例如,当你为项目中的主色调设置一个变量名 --primary-color ,那么你后面再修改这个主色调时,只需要改动一处,而不需要在不同位置的多个CSS文件中去手动多次修改这个值。

CSS变量和预处理器中的变量有什么不同?

你可能已经在CSS预处理器中尝试过使用变量而带来的好处了,比如Sass 和 Less

预处理器让你能设置变量,以及在函数、循环、数学计算等等地方中使用它们。这是否意味着CSS变量已经无关紧要了呢?

那可未必,主要是因为,CSS变量与预处理器中的变量其实并不是同样的东西。

不同之处在于CSS变量是运行在浏览器中的动态CSS属性,而预处理器变量会被编译成普通的CSS代码。因此,浏览器并不知道预处理器变量的存在。

这意味着,你可以在样式表,内联样式和SVG的标签中直接更新CSS变量,或者使用JavaScript操作它们。这是预处理器变量做不到的。CSS变量提供了更多可能性!

但这并不是说你需要在二者之间选择其一:没有什么东西限制你,你可以同时使用CSS变量和预处理变量,并享有它们各自带来的巨大好处。

CSS变量:语法

虽然本文为了简洁,我使用了CSS变量(CSS variables)这个术语,但是官方的规范把它们称作为 级联变量的CSS自定义属性CSS自定义属性 形式如下:

--my-cool-background: #73a4f4;

在自定义属性前面添加双横线前缀,然后像普通的CSS属性一样给它赋值。在上面的代码片段中,我给 --my-cool-background 自定义属性赋了一个颜色值。

级联变量(cascading variable) 的部分,由通过 val() 来使用你的自定义属性,形式如下:

var(--my-cool-background);

自定义属性的作用范围限定在 CSS 选择器中, val() 部分用作实际 CSS 属性的值:

:root {
--my-cool-background: #73a4f4;
}
/* CSS文件的其他部分 */
#foo {
background-color: var(--my-cool-background);
}

上面的代码片段把 --my-cool-background 自定义属性的作用域定义在 :root 这个伪类中,这让该自定义属性能在全局可用(它匹配 <html> 元素内的所有内容)。然后,使用 val() 函数把 ID 为 foo 的容器的 background-color 设置为自定义属性的值,这时该容器就有了浅蓝的背景色。

除此之外,还可以把淡蓝色应用到多个HTML元素的其他颜色属性上,如 colorborder-color 等。方法很简单,就是通过 var(--my-cool-background) 获取自定义属性的值,然后给相应的CSS属性设置上去。(当然,我建议在事情变得混乱之前考虑一下CSS变量的命名约定):

p {
color: var(--my-cool-background);
}

See the Pen Basic Workings of CSS Variables by SitePoint ( @SitePoint ) on CodePen .0

你也可以在CSS变量中使用另一个CSS变量,例如:

--top-color: orange;
--bottom-color: yellow;
--my-gradient: linear-gradient(var(--top-color), var(--bottom-color));

上面的代码创建了一个 --my-gradient 变量,是一个渐变样式,它的值是使用 --top-color--bottom-color 变量创建的一个渐变。现在,你可以在任何地方通过仅仅改变变量的值来修改渐变,而不必到处在样式表中创建渐变实例。

下面是一个在线CodePen演示。

See the Pen Setting Value of CSS Variable with Another CSS Variable by SitePoint ( @SitePoint ) on CodePen .0

最后,你可以在CSS变量中加入一个或多个备用值,例如:

var(--main-color, #333);

上面的代码中,#333是一个备用值。如果未设置备用值,则在自定义属性无效或未设置的情况下,将应用继承的值。

CSS变量是区分大小写的

与普通CSS属性不同,CSS变量是区分大小写的。

例如, var(--foo)var(--FOO) 是获取两个不同的自定义属性(分别是 --foo--FOO )的值。

CSS变量受级联关系影响

和普通CSS属性一样,CSS变量是可继承的。例如,我们定义了一个属性,值为 blue

:root {
--main-color: blue;
}

当你在 </html><html> 标签中的任意元素指定 --main-color 变量时,它们都会继承到blue这个值。

如果你在另一个元素里面给自定义属性赋了一个不同的值,这个元素的所有子元素就会继承这个新值,例如:

:root {
--main-color: blue;
}
.alert {
--main-color: red;
}
p {
color: var(--main-color);
}
<--! HTML -->
<html>
<head>
<!-- head code here -->
</head>
<body>
<div>
<p>blue 的段落</p>
<div class="alert">
<p>red 的段落</p>
</div>
</div>
</body>
</html>

在上面的标签中,第一个段落会继承到全局的 --main-color 值,它是蓝色。

在div标签中拥有 .alert 类的段落会是红色,因为它的值继承自局部作用域里的 --main-color ,这个变量的值是 red

See the Pen Simple Example of CSS Variables Inheritance by SitePoint ( @SitePoint ) on CodePen .0

现在了解这些规则足够,让我们来编码吧!

如何在SVG中使用CSS变量

CSS变量和SVG配合得很好。你可以使用CSS变量去修改SVG中的样式,以及和呈现相关的属性。

比如,你想通过SVG图标元素的父元素来给它一个不同的颜色。你可以在父元素内设置一个局部的CSS变量,然后把它赋值成你想要的颜色,然后,父元素内的图标就能从父元素继承到合适的颜色。

下面是相关代码:

/* 图标的内联SVG symbol */
<svg>
<symbol id="close-icon" viewbox="0 0 200 200">
<circle cx="96" cy="96" r="88" fill="none" stroke="var(--icon-color)" stroke-width="15" />
<text x="100" y="160" fill="var(--icon-color)" text-anchor="middle" style="font-size:250px;">x</text>
</symbol>
</svg>
/* 图标的第一个实例  */
<svg>
<use xlink:href="#close-icon" />
</svg>

上面的代码使用了 <symbol> 标签,它让你创建一 SVG 图形的不可见的版本。然后再使用 <use> 标签生成一个可见的副本。这种方法可以让你根据自己的喜好创建任意多个自定义的图标,也就是通过它的ID( #close-icon )指向那个 <symbol> 。这比一遍又一遍地写重复的代码创建图形更加简便。如果你想提高这方便的技术,Massimo Cassandro在他的 创造你自己的SVG图标 中提供了一个快速教程。

注意 SVG中的圆形元素的 stroke 属性值和文本元素的 fill 属性值:它们都使用了一个CSS变量, --icon-color ,这个变量定义在CSS文档的 :root 选择器上,如下所示:

:root {
--icon-color: black;
}

这是当前图标看起来的样子:

CSS变量(自定义属性)实用指南

如果你现在把SVG图标放到不同的容器中,然后在每个父元素的选择器中给这个变量赋不同的颜色值,你就能在不添加任何样式规则的情况下创建不同颜色的图标。这很酷!

为了展示这一点,我们把上面图标的一个实例放在一个有 .success 类的 div 中。

HTML 代码:

<!-- html -->
<div class="success">
<svg>
<use xlink:href="#close-icon" />
</svg>
</div>

现在,让 --icon-color 变量局部化,即把它放在 .success 中,并设置一个 green 值。我们来看看发生的变化:

CSS 代码:

/* css */
.success {
--icon-color: green;
}

这个图标的颜色就变成了绿色:

CSS变量(自定义属性)实用指南

查看下面完整的演示示例:

See the Pen Basic Use of SVG Icon and CSS Variables by SitePoint ( @SitePoint ) on CodePen .0

如何在@keyframes中使用CSS变量

CSS变量可以在CSS动画中使用,不论是在一般的HTML元素还是内联SVG元素上。只需要记得,你得知道让什么元素动,把它视为目标元素,然后创建对该目标元素的选择器,在选择器的作用范围中定义你的CSS变量,然后,使 val() 获取这些变量,把它们设置到 @keyframes 代码块中。

例如,让SVG中 .bubble 类里面的 <ellipse> 元素动起来,你的CSS可能会看起来像这样:

.bubble {
--direction-y: 30px;
--transparency: 0;
animation: bubbling 3s forwards infinite;
}
@keyframes bubbling {
0% {
transform: translatey(var(--direction-y));
opacity: var(--transparency);
}
40% {
opacity: calc(var(--transparency) + 0.2);
}
70% {
opacity: calc(var(--transparency) + 0.1);
}
100% {
opacity: var(--transparency);
}
}

注意到这是如何借助 CSS的 calc() ,并用 var() 函数进行计算的。它们增强了你代码的灵活性。

这个例子简洁的地方在于,利用CSS属性,你可以简单的修改相应选择器里变量值而调整动画,而不需要挨个去查找 @keyframes 里的属性了。

下面是完整的CodePen演示:

See the Pen Simple Animation with CSS Variables and SVG by SitePoint ( @SitePoint ) on CodePen .0

如何通过JavaScript操作CSS变量

另一个超级酷的事情就是,你可以直接通过JavaScript代码访问CSS变量。

假设在你的CSS文件中,有一个叫做 --left-pos 的变量,作用在 .sidebar 选择器中,值为 100px

.sidebar {
--left-pos: 100px;
}

那么,使用类似下面的 JavaScript 代码获取 --left-pos 的值:

// 缓存你即将操纵的元素
const sidebarElement = document.querySelector('.sidebar');
// 缓存sidebarElement的样式于cssStyles中
const cssStyles = getComputedStyle(sidebarElement);
// 获取 --left-pos CSS变量的值
const cssVal = String(cssStyles.getPropertyValue('--left-pos')).trim();
// 将CSS 变量的值打印到控制台: 100px
console.log(cssVal);

使用类似下面的JavaScript代码给CSS变量赋值:

sidebarElement.style.setProperty('--left-pos', '200px');

上面的代码将sidebar元素中 --left-pos 变量的值设置为 200px

请看看CodePen中的如下示例,你可以交互式地点击侧边栏,修改 blend mode 属性和背景色。这些实现只用到了CSS变量和JavaScript。

See the Pen Blend Modes, CSS Variables and JavaScript by SitePoint ( @SitePoint ) on CodePen .0

浏览器对CSS变量的支持情况

除了IE11(它不支持CSS变量),所有主流浏览器都 对CSS变量有全面地支持

对于不支持CSS变量的浏览器,一个变通的方案是使用具有虚拟查询条件(dummy conditional query)的 @supports代码块 :

section {
color: gray;
}
@supports(--css: variables) {
section {
--my-color: blue;
color: var(--my-color, 'blue');
}
}

因为IE/Edge支持 @supports ,所以上面的代码会生效。如果在 var() 函数中添加一个后备值,你的代码将会更加健壮,在支持的更加不好的浏览器中也能优雅降级。

所以,在Chrome和其他支持CSS变量的浏览器中, <section> 元素内部的文本是蓝色的:

CSS变量(自定义属性)实用指南

在IE11中,由于它不支持CSS变量,页面将显示灰色文本:

CSS变量(自定义属性)实用指南

查看在线演示:

See the Pen @supports with CSS Variables by SitePoint ( @SitePoint ) on CodePen .0

这种方式的缺点是如果你在项目中使用了大量的CSS变量,但是该项目主要通过不支持CSS变量的浏览器打开,那么代码不仅会变得有点儿复杂,维护也将会是噩梦。

在这种情况下,你可以选择使用支持 cssnext 的PostCSS,然后你就可以编写尖端的CSS代码了,兼容不支持的浏览器交给PostCSS去做就可以了,这有点儿像JavaScript的编译器。如果你想了解PostCSS,SitePoint Premium为其所有成员提供了有关此主题的精彩 视频课程

资源

想了解更多CSS变量的细节,包括浏览器兼容问题的解决方案和有趣的例子,查看下面的资源:

有趣的例子

你还在等什么?尝试使用CSS变量并通过评论让我知道你的想法!

原文链接: https://www.sitepoint.com/practical-guide-css-variables-custom-properties/


以上所述就是小编给大家介绍的《CSS变量(自定义属性)实用指南》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Data Structures and Algorithms in Java

Data Structures and Algorithms in Java

Robert Lafore / Sams / 2002-11-06 / USD 64.99

Data Structures and Algorithms in Java, Second Edition is designed to be easy to read and understand although the topic itself is complicated. Algorithms are the procedures that software programs use......一起来看看 《Data Structures and Algorithms in Java》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具