搜索
首页web前端css教程关于 CSS 变量的一些你可能不了解的事!

本篇文章带大家了解一下CSS 变量,介绍下没人告诉你关于 CSS 变量的那些事。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。

关于 CSS 变量的一些你可能不了解的事!

CSS 变量很不错哦,但是你知道它们的详情?【推荐学习:css视频教程

1. 小心 !important

CSS 变量一起使用 !important 有点诡异,如下面的示范:

p {
  --color:red !important;

  color:var(--color);
  color:blue;
}

上面的 p 元素会是什么颜色呢?你会认为是 red 红色吧,认为按如下代码执行:

p {
  color: red !important;
  color: blue;
}

但是,并不是 red 红色,因为实际执行是这样:

p {
  color: red;
  color: blue;
}

在这种情况下,!important 并不是 color 的一部分,而是增加了 --color 变量的特性。规范中指明:

注意:自定义属性可以包含 !important ,但是会被 CSS 解析器自动从属性中删除,这将自定义的属性 important 变成层级。换言之, !important 并不是不会起作用,而是在语法检查之前就被忽略了。

下面这个例子你会更容易明白:

p {
  --color: red !important;
  --color: blue;
  
  color: var(--color);
}

上面的代码会赋予 p 元素红色,解析如下:

  • 我们对 --color 属性有两次的声明,所以我们需要解决其层级的问题。第一次的定义带有 !important ,所以它的层级相对高

  • 接着 var(--color) 将会应用 red !important

  • 所以我们会得到 color: red

再来看一段代码:

p{
  --color: red !important;
  --color: blue; 

  color:var(--color);  color: pink; <!-- 这里我改写的颜色值 -->
}

按照上面的逻辑,我们最后会得到粉红色 pink 的段落颜色。

一个很重要的规则是应当将 CSS 变量(自定义属性)看作普通属性,而不仅仅是存储值的变量

自定义属性是普通属性,所以它们可以被定义在任何的元素上,可以使用普通属性的继承和联级规则解决,可以使用 @media 和其他条件规则进行条件处理,可以用于 HTMLstyle 属性,可使用 CSSDOM 读取和设置等等。

2. 它们不可以存储 urls

总有一天你会偶然发现这个常见的限制。

你不能这样做 ❌

:root {
  --url:"https://picsum.photos/id/1/200/300";
}
.box {
  background:url(var(--url));
}

你应该这样做 ✅

:root {
  --url:url("https://picsum.photos/id/1/200/300");
}
.box {
  background:var(--url);
}

这个限制有关 url() 是怎么解析的。解析起来有点棘手,推荐你到 Stack Overflow Answer 上找答案。正如你所见,我们修复起来很容易,把 url() 整个赋予变量即可。

3. 它们可以无效的值变有效

这也是我喜欢的点之一,也是让人头疼的点。

我们以一个基础的案例入手:

.box {
  background: red;
  background: linaer-gradient(red, blue);
}

.box 元素将会有一个红蓝渐变的效果,对吧?然而却是纯红色。嗯,我打错了 linear-*。我可以很容易发现这个错误,因为浏览器划掉了这一行并启用了上一行的背景样式。

1.png

现在,让我们来介绍变量:

.box {
  --color:red;
  background: var(--color);
  background: linaer-gradient(var(--color), blue);
}

测试这段代码,你会发现背景颜色变成了透明。我们的第二个背景颜色并没有被浏览器划掉,反而是第一个背景样式被划掉了。因为第二个背景样式重写了第一个。

2.png

为什么会发生这样的事情 ?

当我们使用变量作为属性,浏览器只会在 "计算值时间" 去评估值,因为我们需要首先知道变量的内容。在这种例子中,当浏览器做联级时,会认为属性值是有效的,之后才会变成无效。

在我们的例子中,浏览器做级联时,认为最后一个声明是有效的。但是到评估值的时候,最后一个声明被认定是无效的,所以它被忽略。我们不会回头查看,因为我们在级联的时候已经处理过了,所以我们最后会得到一个透明的背景颜色。

你可能认为这种行为不符合逻辑的,但是它确符合逻辑。因为一个值是有效还是无效时基于 CSS 变量的,所以浏览器一开始时不能真正知道。

.box {
  --color:10px; /* a "valid" variable */
  background: red; /* a "valid" declaration */
  background:linear-gradient(var(--color),blue); /* a "valid" declaration that will override the first one  */
  /* The result is an "invalid" value ... */ 
}

如果一个属性包含一个或者更多的 var() 函数,而且这些函数都是语法有效的,必须假定整个属性的语法在解析时有效。当 var() 函数被替代后,在“计算值时间”才做语法检查。

简单来说:CSS 变量将属性的状态作为一个后备,知道我们对其进行评估值。当评估值之后,我们可以说它是有效的或者无效的了。如果它是无效的,那么久太晚了,因为我们不会再回头使用上一个。

4. 它们可以不被使用单位

大多数的教材或课程都会展示下面的代码给你:

:root {
 --p: 10px;
}
.box {
  padding: var(--p);
}

但是,你也可以这么做:

:root {
 --p: 10;
}
.box {
  padding: calc(var(--p)*1px);
}

变量中拥有单位并不是强制的。

5. 他们可以动起来

最初,CSS 变量被定义是没有动画属性的。

Animatable: no

但是,事情发生了变化,我们通过 @property 修饰,CSS 变量可以做一些动画或者渐变。这个特性目前浏览器支持比较低,但是也是时候了解下了。

6. 它们不可以存储 <span style="font-size: 18px;">inherit</span>

我们考虑下面的例子:

<div class="box">
  <div class="item"></div>
</div>
.box {
  border:2px solid red;
}
.item {
  --b:inherit;
  border:var(--b);
}

直觉告诉我们,.item 将会即成父元素的 border,因为 --b 包含 inherit,但是并不是。

正如我们在第1点上说到的,我们错误认为 CSS 变量会简单存储值,然后供我们往后使用,然而并不会。CSS 变量(自定义的属性)是普通属性,所以 inherit 会被应用并不会存储值。

例子:

.box {
  --b:5px solid blue; /* we define the variable on the parent */
}
.item {
  --b:inherit; /* the child will inherit the same value so "5px solid blue"*/
  border:var(--b); /* we will have "5px solid blue" */
}

正如你所看到的,公共属性应用,逻辑上才可以继承 inherit

上面的写法是鸡肋的,因为 CSS 变量默认是继承的。

7. 它们可以是空值

是的,你可以想下面这么做:

.box {
  --color: ;
  background:var(--color); 
}

笔记:6595bb9e2ff3221d72e7d6daea14afcc 声明值必须代表一个标记,所以变量空值需要有一个空格。比如 --foo: ; 是有效的,var(--foo) 将会返回一个空格。--foo:; 是无效的。如下:

.box {
  --color:; ❌
  background:var(--color); 
}

3.png

这个小技巧可以配合预设特性实现一些想不到的效果。

一个例子你就会明白这个技巧:

.box {
  background:
   linear-gradient(blue,transparent)
   var(--color,red); # 没有发现--color,取默认值 red
}
<div class="box">
  I will have `background:linear-gradient(blue,transparent) red;`
</div>
<div class="box" style="--color:green">
  I will have `background:linear-gradient(blue,transparent) green;`
</div>
<div class="box" style="--color: ;">
  I will have `background:linear-gradient(blue,transparent)  ;`
</div>
  • 第一个 box 没有定义变量,所以预设值被使用

  • 第二个有定义的变量,所以它被使用

  • 最后一个设定了一个空的变量值,所以空值被使用。使用后就好比不需要 var(--color, red) 一样

空值允许我们移除属性中 var() 声明,在一个复杂的值中使用 var() 作用挺大。

8. CSS 变量不是 C++ 变量

很不幸的是,很多开发者趋向于比较 CSS 变量和其他语言的变量,然后在他们逻辑上有一大堆的问题。正是这个原因,我都不想叫他们变量而是自定义属性,因为他们确实是属性。

很多人都想这么做:

:root {
  --p:5px;
  --p:calc(var(--p) + 1px); /* let&#39;s increment by 1px */
}
:root {
  --x: 5px;
  --y: 10px;
  /* let&#39;s do a variable switch */
  --c: var(--y);
  --y: var(--x);
  --x: var(--c);
}
.box {
  --s: 10px;
  margin:var(--s); /* I want 10px of margin */
  --s: 20px;
  padding:var(--s): /* then 20px of padding */
}

以上的示范都不能工作。第一个和第二个都有无效值,因为它们都有嵌套依赖。最后一个例子,paddingmargin 都是 20px,因为级联会获取第二个 --s: 20px 的变量去应用。

这很不幸,你应该停止用 C++, Javascript, Java 等语言的思维去思考 CSS 变量,因为它们有自己逻辑的自定义属性。

9. 它们只能从父元素传递给子元素

请记住这个黄金规则:CSS 变量总是从父元素(或者说祖先元素)传递给子元素,不会从子元素传递给父元素或兄弟元素

:root {
  --c1: red;
  --c2: blue;
  --grad: linear-gradient(var(--c1),var(--c2);
}
.box {
  --c1: green;
  background:var(--grad);
}

你可以会认为 .box 背景颜色是 linear-gradient(green, blue) ? 不,背景颜色会是 linear-gradient(red, blue)

root 元素是 DOM 元素的最上层,所以它是 box 的祖先元素,我们应用上面的黄金规则知道,子元素的 --c1 是跑不到 linear-gradient(var(--c1),var(--c2) 中的。

10. 它们可以有奇怪的语法

最后一个也是有趣的一个。

你知道你能像下面这样写么?

body {
  --:red;
  background:var(--);
}

很神奇,对吧?是的,CSS 变量可以仅使用两节虚线定义。

你会认为上面已经很疯狂了?看下下面这个:

body {
 --?:red;
 --?:green; 
 --?:blue;
 --?:orange;
}

是的,你还可以用表情来定义一个变量。

CSS 变量允许你以 -- 开头的任何内容。比如:

body {
  ---------:red;
  background:var(---------);
}

又比如:

body {
  --‎:red;
  --‎:blue;
  background:linear-gradient(90deg, var(--‎),var(--‎));
}

其实上面是这样的:

4.png

当然你不会使用这么稀奇古怪的东西在你的实际项目中,除非你想让你的老板或合作开发者发疯

总结

不知不觉有很多的内容了,你不需要马上就记住所有的内容。我尽力将这些不为人知的 CSS 变量整理了出来。如果有一天你工作中需要这些知识点,你可以回头来看。

英文原文地址:https://dev.to/afif/what-no-one-told-you-about-css-variables-553o

本文是译文,采用意译。

(学习视频分享:web前端

以上是关于 CSS 变量的一些你可能不了解的事!的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:掘金社区。如有侵权,请联系admin@php.cn删除
@rules具有多少特异性,例如@keyframes和@media?@rules具有多少特异性,例如@keyframes和@media?Apr 18, 2025 am 11:34 AM

前几天我得到了这个问题。我的第一个想法是:奇怪的问题!特异性是关于选择者的,而在符号不是选择器,那么...无关紧要?

您可以嵌套@Media和@support查询吗?您可以嵌套@Media和@support查询吗?Apr 18, 2025 am 11:32 AM

是的,您可以,而且它并不重要。不需要CSS预处理器。它在常规CSS中起作用。

快速吞噬缓存破坏快速吞噬缓存破坏Apr 18, 2025 am 11:23 AM

您应该肯定会在CSS和JavaScript(以及图像和字体以及其他内容)等资产上设置遥远的高速缓存标头。告诉浏览器

寻找可以监视CSS质量和复杂性的堆栈寻找可以监视CSS质量和复杂性的堆栈Apr 18, 2025 am 11:22 AM

许多开发人员写了如何维护CSS代码库的文章,但并没有很多关于如何测量该代码库质量的文章。当然,我们有

数据学家用于建议不执行值的值数据学家用于建议不执行值的值Apr 18, 2025 am 11:08 AM

您是否曾经有一种需要接受简短而任意的文本的表格?喜欢名字或其他。那完全是用的。有很多

苏黎世的最初会议苏黎世的最初会议Apr 18, 2025 am 11:03 AM

我很高兴能前往瑞士苏黎世参加前界(Love the Name and URL!)。我以前从未去过瑞士,所以我很兴奋

使用CloudFlare工人建立全栈无服务器应用程序使用CloudFlare工人建立全栈无服务器应用程序Apr 18, 2025 am 10:58 AM

我在软件开发方面最喜欢的发展之一是无服务器的出现。作为一个倾向于陷入细节的开发人员

在NUXT应用程序中创建动态路由在NUXT应用程序中创建动态路由Apr 18, 2025 am 10:53 AM

在这篇文章中,我们将使用我构建和部署的电子商务商店演示来进行Netlify,以展示如何为传入数据制作动态路线。这是一个公平的

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热工具

SublimeText3 英文版

SublimeText3 英文版

推荐:为Win版本,支持代码提示!

Dreamweaver Mac版

Dreamweaver Mac版

视觉化网页开发工具

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能