이 글에서는 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
和其他条件规则进行条件处理,可以用于HTML
的style
属性,可使用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-*
css 동영상 튜토리얼
CSS
와 함께 사용하세요 변수 !important
는 다음 데모에서 볼 수 있듯이 약간 이상합니다.
.box { --color:red; background: var(--color); background: linaer-gradient(var(--color), blue); }
위의 p
요소는 어떤 색상이 될까요? red
빨간색이라고 생각하고 다음과 같이 실행된다고 생각하세요.
.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 ... */ }하지만 실제 실행은 다음과 같기 때문에
red
빨간색은 아닙니다.
:root { --p: 10px; } .box { padding: var(--p); }이 경우
!important
는 color
의 일부가 아니지만 --color
변수의 특성을 추가합니다. 사양에 지정됨 :
참고: 맞춤 속성에는🎜다음 예를 보면 이해하기 쉽습니다. 🎜!important
가 포함될 수 있지만CSS
파서에 의해 속성에서 자동으로 제거됩니다. 중요한 속성 레이어가 되어 보세요. 즉,
!important
가 작동하지 않는 것이 아니라 구문 검사 전에 무시되는 것입니다.
:root { --p: 10; } .box { padding: calc(var(--p)*1px); }🎜위 코드는
p
요소에 빨간색을 부여하며 분석은 다음과 같습니다. 🎜--color
속성에 대해 두 개의 선언이 있으므로 🎜level🎜 문제를 해결해야 합니다. 첫 번째 정의에는 !important
가 있으므로 그 수준이 상대적으로 높습니다🎜var(--color)
가 적용됩니다red !important🎜color: red
🎜<div class="box"> <div class="item"></div> </div>🎜 위의 논리에 따르면 최종적으로 분홍색
분홍색
의 단락 색상을 얻게 됩니다. 🎜🎜매우 중요한 규칙은 🎜CSS 변수(사용자 정의 속성)는 값을 저장하는 변수🎜가 아니라 일반 속성으로 취급되어야 한다는 것입니다. 🎜🎜사용자 정의 속성은 🎜일반 속성🎜이므로 모든 요소에 정의할 수 있으며 일반 속성의 상속 및 계단식 규칙을 사용하여 해결할 수 있습니다.🎜🎜2. URL을 저장할 수 없습니다.🎜🎜🎜언젠가 여러분은 이 일반적인 제한 사항을 발견하게 될 것입니다. 🎜🎜이 작업을 수행할 수 없습니다 ❌🎜@media
및 기타 조건부 사용이 가능합니다. 규칙은 조건부 처리를 수행하며HTML
의style
속성에 사용할 수 있고CSSDOM
등을 사용하여 읽고 설정하는 데 사용할 수 있습니다. 🎜
.box { border:2px solid red; } .item { --b:inherit; border:var(--b); }🎜이 작업을 수행해야 합니다 ✅🎜
.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" */ }🎜이 제한 사항은
url()
을 구문 분석하는 방법과 관련이 있습니다. 구문 분석하기가 약간 까다롭습니다. Stack Overflow Answer🎜에서 답을 찾아보세요. 보시다시피 전체 url()
을 변수에 할당하면 이 문제를 쉽게 해결할 수 있습니다. 🎜🎜🎜3. 유효하지 않은 값을 유효하게 만들 수 있습니다🎜🎜🎜이 점은 제가 가장 좋아하는 점이자 골치 아픈 점 중 하나입니다. 🎜🎜기본적인 경우부터 시작해 보겠습니다. 🎜.box { --color: ; background:var(--color); }🎜
.box
요소는 빨간색-파란색 그라데이션 효과를 갖습니다. 그렇죠? 그래도 완전 빨간색이에요. 글쎄요, 제가 linear-*
를 잘못 입력했습니다. 브라우저가 행을 지우고 이전 행의 배경 스타일을 활성화하기 때문에 이 오류를 쉽게 발견할 수 있습니다. 🎜🎜🎜🎜🎜이제 변수를 소개하겠습니다. 🎜.box { --color:; ❌ background:var(--color); }🎜이 코드를 테스트하면 배경색이 투명해지는 것을 확인할 수 있습니다. 두 번째 배경색은 브라우저에서 지워지지 않았지만 첫 번째 배경 스타일은 지워졌습니다. 두 번째 배경 스타일이 첫 번째 배경 스타일보다 우선하기 때문입니다. 🎜🎜🎜🎜🎜🎜왜 이런 일이 발생하나요? 🎜🎜🎜변수를 속성으로 사용하면 먼저 변수의 내용을 알아야 하기 때문에 브라우저는 "값 계산 시간"에만 값을 평가합니다. 이 예에서는 브라우저가 연결을 수행할 때 속성 값이 유효한 것으로 간주한 다음 유효하지 않게 됩니다. 🎜
在我们的例子中,浏览器做级联时,认为最后一个声明是有效的。但是到评估值的时候,最后一个声明被认定是无效的,所以它被忽略。我们不会回头查看,因为我们在级联的时候已经处理过了,所以我们最后会得到一个透明的背景颜色。
你可能认为这种行为不符合逻辑的,但是它确符合逻辑。因为一个值是有效还是无效时基于 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); }
笔记:
<declatation-value></declatation-value>
声明值必须代表一个标记,所以变量空值需要有一个空格。比如--foo: ;
是有效的,var(--foo)
将会返回一个空格。--foo:;
是无效的。如下:
.box { --color:; ❌ background:var(--color); }
这个小技巧可以配合预设特性实现一些想不到的效果。
一个例子你就会明白这个技巧:
.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's increment by 1px */ }
:root { --x: 5px; --y: 10px; /* let'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 */ }
以上的示范都不能工作。第一个和第二个都有无效值,因为它们都有嵌套依赖。最后一个例子,padding
和 margin
都是 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(--)); }
其实上面是这样的:
当然你不会使用这么稀奇古怪的东西在你的实际项目中,除非你想让你的老板或合作开发者发疯
总结
不知不觉有很多的内容了,你不需要马上就记住所有的内容。我尽力将这些不为人知的 CSS
变量整理了出来。如果有一天你工作中需要这些知识点,你可以回头来看。
英文原文地址:https://dev.to/afif/what-no-one-told-you-about-css-variables-553o
本文是译文,采用意译。
(学习视频分享:web前端)
위 내용은 CSS 변수에 대해 당신이 몰랐을 수도 있는 것들!의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!