各位是否在工作中仅仅使用css处理器,比如sass,less在定义变量呢?殊不知css也已经支持定义变量,那么css变量要如何使用,有何优缺点呢,别着急,这篇文章带你快速入门css变量!
概念
首先来介绍下,CSS 变量是用来存储 CSS 值的自定义属性,其语法以 -- 开头,属于元素的 样式属性(Style Property) ,可以在 CSS 中像普通属性值一样被引用。
举个例子,下面代码里 --main-color 就是一个css变量:
.button {
--main-color: #e74c3c;
}
为什么选择用--表示变量呢?因为$foo被 Sass 用掉了,@foo被 Less 用掉了。为了不产生冲突,官方的 CSS 变量就改用两根连词线。🤪
定义了变量后,如何使用呢?这里我们要用到 css 提供的 var 函数,用法如下:
.button{
color:var(--main-color);
}
它有第二个参数,用于指定回退值,如果前面的变量不存在,则会使用默认值,如下:
.button{
color:var(--main-color,red);
}
// 多层嵌套也是可以的
.button{
color:var(--main-color,var(--second-color,red));
}
ok,现在你已经了解了如何定义和使用css变量,但是不要忘了下面这些注意事项:
变量是有作用域的,要存在于css块里(即{}中),最高优先级的生效,子元素会继承父元素
举个例子,来看下面代码:
// 不生效
--color:orange;
//会被上述定义错误的变量影响,也不会生效
:root { --color: blue; }
div { --color: green; }
#alert { --color: red; }
* { color: var(--color); }
除了没有在css块里的变量失效,紧随其后的样式也受到了影响。其他的则会根据优先级去匹配。
那么如何定义全局变量呢?一般是定义在:root下,也就是上面被影响到的那个。😅
变量可以是字符串,也可以是数值
比如下面这段代码,就是变量为字符串的情况:
:root{
--bar: 'hello';
--foo: var(--bar)' world';
}
body:after {
content: var(--bar)var(--foo);
}
这里要注意,首先变量不允许用作属性名,下面这样是无效的:
.foo {
--side: margin-top;
/* 无效 */
var(--side): 20px;
}
如果变量值带有单位,就不能写成字符串。比如下面的例子:
/* 无效 */
.foo {
--foo: '20px';
font-size: var(--foo);
}
/* 有效 */
.foo {
--foo: 20px;
font-size: var(--foo);
}
再举一个变量为数值的例子:
.foo {
--gap: 20;
margin-top: calc(var(--gap) * 1px);
}
这里使用calc函数是因为数值类型的变量不能直接和单位写在一起。
JS可以操作css变量
大致方法如下:
// 设置变量
document.body.style.setProperty('--primary', '#7F583F');
// 读取变量
document.body.style.getPropertyValue('--primary').trim();
// '#7F583F'
// 删除变量
document.body.style.removeProperty('--primary');
可以利用标签的style属性来定义变量,并且可以在css文件中直接使用
比如下面这个标签:
<div id="g-element" style="--bgColor: #000"></div>
在对应的css文件中,如果对应选择器匹配上上面这个div,就可以直接使用--bgColor。
只要语法是正确的,var函数都会解析,而不会关注值的合法性
如果变量值不合法,则采用默认值。
比如下面这段代码,最后背景颜色是什么呢?没错,是透明,即默认值
body {
--color: 20px;
background-color: #369;
background-color: var(--color, #cd0000);
}
解释下发生了什么,首先由于没有语法问题,因此最后生效的是background-color: var(--color, #cd0000);这里,然后,--color的值为20px,因此,对应的就是,background-color:20px,显然这是不对的,于是采用默认值,也就是透明,最后实际生效的样式如下图:
不要产生循环依赖
循环依赖产生有以下两个场景:
- 变量需要依赖其自身值。即,定义时就使用了
var()引用其值。如下:
:root {
--m: var(--m)
}
- 两个或两个以上的变量互相引用时
:root {
--one: calc(var(--two) + 10px);
--two: calc(var(--one) - 10px);
}
要避免上述两种情况。
使用场景
简单列举几个使用场景:
首先是响应式布局,CSS 是动态的,页面的任何变化,都会导致采用的规则变化。
利用这个特点,可以在响应式布局的media命令里面声明变量,使得不同的屏幕宽度有不同的变量值。如下:
body {
--primary: #7F583F;
--secondary: #F7EFD2;
}
a {
color: var(--primary);
text-decoration-color: var(--secondary);
}
@media screen and (min-width: 768px) {
body {
--primary: #F7EFD2;
--secondary: #7F583F;
}
然后是主题切换,在 antd 中就支持使用css变量的形式去修改主题,可以查看这个链接antd使用css变量修改主题
变量也可简化一些动画相关的代码,除了常规的抽取相同的值之外,我们还可以巧妙的将一些动画变换转为对变量的变换,比如下面这个例子:CodePen Home MASK conic-gradient 转场 其核心是下面这段代码:
@keyframes maskRotate {
@for $i from 0 through 100 {
#{$i}% {
mask: conic-gradient(#000 #{$i - 8 + '%'}, transparent #{$i + '%'}, transparent);
}
}
}
经过编译后,要生成101个关键帧,而采用css变量,则可以优化成这样:
@property --per {
syntax: '<percentage>';
inherits: false;
initial-value: -10%;
}
div {
position: relative;
width: 400px;
height: 400px;
background: url(https://picsum.photos/400/400?random=5) no-repeat;
&::before {
content: "";
position: absolute;
top: 0;left: 0; right: 0;bottom: 0;
background: url(https://picsum.photos/400/400?random=100) no-repeat;
mask: conic-gradient(
#000 0,
#000 var(--per),
transparent calc(var(--per) + 10%),
transparent
);
z-index: 1;
animation: maskRotate 5s ease-in forwards;
}
}
@keyframes maskRotate {
0% {
--per: -10%;
}
100% {
--per: 100%;
}
}
其中CSS @Property at-rule 是 CSS Houdini API 的一部分,它允许开发者显式地定义他们的 CSS 自定义属性,允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。
简单理解就是CSS 自定义属性(CSS 变量)。
通过这种方式将原先生成101个关键帧变为修改 css 变量,是不是很巧妙呢?
总结
相信通过这篇文章,大家一定对css变量有了更深入全面的理解,想不想立刻在自己的项目里使用下试试呢?快去操练起来吧!😎
(ps.感谢大家阅读,看到这,不妨点个赞在走吧,十分感谢!😍)