资讯专栏INFORMATION COLUMN

CSS变量(自定义属性)使用指南 — SitePoint

light / 1622人阅读

摘要:预处理器可以让你设置变量,并且在函数循环和数学操作等中使用。不同之处在于变量是运行在浏览器中的动态属性,而预处理器变量会被编译成普通的代码。变量提供了更多可能性但这并不是说你需要在二者之间选择其一你可以同时使用变量和预处理器变量的强大功能。

CSS预处理器,如Sass和Less,使得CSS代码易于组织和维护。通过提供变量、混合、循环等特性,使得CSS具有动态编写的能力,从而减少重复性工作,提高开发速度。

最近,CSS开始添加一些动态特性。CSS变量(自定义属性)已经加入规范,并且获得了大多数浏览器的支持。但是CSS混合特性还在进行中。

在这篇文章中,我们将会向你展示怎么把CSS变量应用到开发中,从而使得样式表更加可维护和DRY (Don’t Repeat Yourself)。

让我们现在开始!

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

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

total也是一个变量,存储number1和number2变量的和,在这个例子中是5。你可以动态更新这些变量的值,并且在程序的任何地方使用更新后的值。在上面的代码片段中,我把number1的值更新为4,当我使用相同的变量再次执行加法操作时,存储在total中的值就变成7,而不是5了。

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

CSS主要是一门声明式语言,缺乏动态性。你可能会说给CSS添加变量会与CSS本身相矛盾。如果前端开发仅仅关注语义,那么给CSS添加变量确实会与CSS本身矛盾。幸运的是,网络语言更像动态语言,它会随着周围环境和开发者的需求不断变化。CSS也不例外。

总而言之,变量已经成为CSS中令人激动的实现,你很快也会发现,学习和使用它非常直观。

使用CSS变量有什么好处?

在CSS中使用变量的好处和在编程语言中没有特别大的不同。

下面是规范对上述问题的回答:

[使用CSS变量]使大文件更易于阅读,因为看起来很随意的值有了一个提示信息的名字,并且编辑这些文件更加简单,更不易于出错。因为你只需要在自定义属性处修改一次,然后这个修改就会自动应用到使用该变量的任何地方。
W3C规范.
换句话说:

通过与项目相关的方式命名变量,管理和维护代码会变得更加容易。例如,如果项目的主色调保存在--primary-color中,修改项目的主色调就会变得很容易,仅仅改变该变量的值就可以,而不用去修改遍布在代码各处、不同CSS属性中的颜色值。

CSS变量和预处理器变量的不同之处?

在给网站添加样式时,你可能已经通过预处理器,如Sass和Less,体验过变量的灵活性带来的好处。

预处理器可以让你设置变量,并且在函数、循环和数学操作等中使用。这是不是意味着CSS变量就没有什么用处了?

不完全是,主要是因为CSS变量和预处理器变量并不一样。

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

这就意味着你可以更改样式表、行内样式属性和SVG展示型属性中的CSS变量,或者使用JavaScript操作它们。这是预处理器变量做不到的。CSS变量提供了更多可能性!

但这并不是说你需要在二者之间选择其一:你可以同时使用CSS变量和预处理器变量的强大功能。

CSS变量的语法

为了简单起见,在这篇文章中我使用了CSS变量这个术语,但是官方文档给出的是级联变量的CSS自定义属性。CSS自定义属性形式如下:

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

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

级联变量部分包括使用var()函数应用自定义属性,形式如下:

`var(--my-cool-background)`

自定义属性的使用范围是CSS选择器的内部,var()像一个真正的CSS属性值被使用。

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

上面的代码片段把--my-cool-background自定义属性定义在:root伪元素内,这使得自定义属性的值全局可用(:root匹配元素内的任何元素)。然后使用var()函数把值应用到ID是foo的容器的background-color属性上,然后这个容器就会得到一个淡蓝色背景。

除此之外,还可以把淡蓝色应用到多个HTML元素的其他颜色属性上,如color,border-color等。你需要做得仅仅是通过var(--my-cool-background)获取自定义属性的值,然后应用到相应的属性上。当然,你需要好好考虑CSS变量的命名规范,使你的变量名能更好地反映变量的内容。

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

查看CodePen上SitePoint(@SitePoint)的CSS变量运行实例。

你也可以在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演示。

查看CodePen上SitePoint(@SitePoint)的在CSS变量中使用另一个CSS变量。

最后,在使用CSS变量的时候,还可以添加一个或多个后备值,举例如下:

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

在上面的代码片段中,#333是一个后备值。如果没有提供后备值,当自定义属性无效或者没有赋值的时候,会使用继承值。

CSS变量是大小写敏感的

和一般的CSS属性不一样,CSS变量是大小写敏感的。

例如,var(--foo)和var(--Foo)使用的是两个不同的自定义属性,分别是--foo和--Foo。

CSS变量是级联的

类似一般的CSS属性,CSS变量也会继承。例如,我们定义一个值是blue的自定义属性:

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

根元素内的所有元素如果应用--main-color就会继承值blue。

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

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

.alert {
  --main-color: red;
}

p {
  color: var(--main-color);
}
<--! HTML -->

  
    
  
  
    

blue paragraph.

red paragraph.

上面的标记语言中的第一个段落会继承全局--main-color的值,所以字体颜色是蓝色。

具有.alert类的div元素内部的段落元素的字体颜色是红色的,因为它继承了局部范围内的--main-color变量,这个变量的值是red。

查看CodePen上SitePoint(@SitePoint)的CSS变量继承的简单例子。

现在了解了规则,让我们开始实践吧!

在SVG中使用CSS变量

CSS变量和SVG可以很好的一起工作!你可以使用CSS变量来修改内联SVG中的样式和展示型属性。

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

下面是相关代码:

/* 图标的内联SVG symbol */

  
    
    x
  


/* 图标的第一个实例  */

  

上面的标记语言使用了标签,使用它可以创建不可见的SVG图形。然后使用标签实例化了一个上述图形的可见版本。使用这种方式通过简单地引用元素的ID(#close-icon)就能创建大量的图标,然后再根据你的喜好对图标进行自定义。这比重复的写同一段代码要简便的多。如果你想复习这个技术,Massimo Cassandro在他的创造你自己的SVG图标中提供了一个快速教程。

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

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

图标现在的样子如下:

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

举个例子,把上面图标的一个实例放在一个有类.success的div中。

HTML:

现在,在.success选择器内给--icon-color变量赋值green,然后看下效果。

CSS:

.success {
  --icon-color: green;
}

现在,图标的颜色变成了绿色:

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

查看CodePen上SitePoint(@SitePoint)的SVG图标和CSS变量的基本使用。

在@keyframes动画中使用CSS变量

CSS变量可以和CSS动画一起使用,不论是在一般的HTML元素还是内联SVG元素上。只需要记住在想添加动画的元素的选择器上定义自定义属性,然后使用var()函数在@keyframes中引用。

比如,给SVG的一个有类.bubble的元素添加动画,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演示:

查看CodePen上SitePoint(@SitePoint)的使用CSS变量和SVG的简单动画。

使用JavaScript操作CSS变量

一件更酷的事情是你可以直接通过JavaScript代码访问CSS变量。

假设有一个叫--left-pos的CSS变量,它的值的100px,定义在CSS文档的.sidebar类中:

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

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

// 获取你想添加动画的元素
const sidebarElement = document.querySelector(".sidebar");

// 把侧边栏元素的样式存储在cssStyles变量中
const cssStyles = getComputedStyle(sidebarElement);

// 获取CSS变量--left-pos的值
const cssVal = String(cssStyles.getPropertyValue("--left-pos")).trim(); 

// 在控制台打印CSS变量的值
// 控制台会输出变量的值为100px
console.log(cssVal);

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

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

上面的代码片段把侧边栏元素的--left-pos变量设置成200px。

相对于改变大量的类或者重写全部的CSS规则,使用CSS变量给网站添加交互更直接,也更易于维护。

查看下面的CodePen演示,你可以通过侧边栏来改变混合模式属性和背景颜色,而这仅仅需要CSS变量和JavaScript:

查看CodePen上SitePoint(@SitePoint)的混合模式,CSS变量和JavaScript。

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

除了IE11(不支持)和Microsoft Edge(buggy支持),在本文编写的时候,所有主流浏览器都完全支持CSS变量。

适配有问题的浏览器的方式之一是使用@supports进行条件查询:

section {
  color: gray;
}

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

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

所以,在Chrome和其他支持CSS变量的浏览器中,

元素内部的文本是蓝色的:

IE11不支持CSS变量,文本会被渲染成灰色:

查看在线演示:

查看CodePen上SitePoint(@SitePoint)的@supports和CSS变量。

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

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/54920.html

相关文章

  • CSS变量定义属性使用指南SitePoint

    摘要:预处理器可以让你设置变量,并且在函数循环和数学操作等中使用。不同之处在于变量是运行在浏览器中的动态属性,而预处理器变量会被编译成普通的代码。变量提供了更多可能性但这并不是说你需要在二者之间选择其一你可以同时使用变量和预处理器变量的强大功能。 CSS预处理器,如Sass和Less,使得CSS代码易于组织和维护。通过提供变量、混合、循环等特性,使得CSS具有动态编写的能力,从而减少重复性工...

    yankeys 评论0 收藏0
  • 【翻译】PostCSS简介

    摘要:许多开发人员花时间在使用的预处理器上如和。传统的预处理器的问题不能扩展。有些预处理器提供诸如的功能,可以彻底不使用它们。每个预处理器已经有了自己的标准。如下它被翻译成嗯我从来没有说过所有的插件都是有用的结束语和预处理器是伟大的。 许多开发人员花时间在使用CSS的预处理器上如less,sass和stylus。这些工具已经成为Web开发的重要组成部分。写一个网站的样式,不使用嵌套,变量或混...

    Lsnsh 评论0 收藏0
  • CSS变量定义属性)实践指南

    摘要:和这样的预处理器,让我们的代码保持良好的结构和可维护性。这是否意味着变量已经无关紧要了呢那可未必,主要是因为,变量与预处理器中的变量其实是不同的东西。而你是无法对预处理器中的变量做上面这些操作的。 本文翻译自:https://www.sitepoint.com/practical-guide-css-variables-custom-properties/ 转载请注明出处:葡萄城官网,葡萄城...

    番茄西红柿 评论0 收藏0
  • 了解并使用CSS中的rem单位

    摘要:写了一篇文章,里面记录了他在实际使用单位过程中的一些感受。他的解决方式充分利用了到目前为止我们遇到的三种单位。根元素的长度单位依旧采用,模块用单位,模块内的元素使用单位。随后在中单位的强大之处提出了他的观点。 什么是 rem 可能在你使用收音机或者用其他音乐播放器之前,就已经听过R.E.M.这个词了。在这个乐队眼中,这个词是浅睡眠时眼球的快速转动的缩写,而在 css 中,rem 代表着...

    BWrong 评论0 收藏0
  • 19+ 个 JavaScript 快速编程技巧 — SitePoint

    摘要:常规写法速记法判断变量是否存在速记法这可能会有些琐碎,但是值得一提。常规写法速记法注意这两个例子并不是完全相等,只要变量是一个真值,该表达式就是成立的。 19+ 个 JavaScript 快速编程技巧 — SitePoint 这确实是一篇针对于基于 JavaScript 语言编程的开发者必读的文章。在过去几年我学习 JavaScript 的时候,我写下了这篇文章,并将其作为 JavaS...

    RobinTang 评论0 收藏0

发表评论

0条评论

light

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<