学习CSS Variable(CSS变量)以及实现JS与CSS变
浏览器支持情况
请看浏览器支持状况,就目前国内而言,移动混合开发、微信开发,都支持CSS变量。PC端不可考虑。
基本用法
全局用法
这是全局作用域的css变量以及用法:
:root {
--main-color: #f40;
--block-font-size: 10px;
}
.aaa {
color: var(--main-color);
}
任何地方想使用变量,只需要var()
这个变量即可。
局部用法
这是局部作用域的css变量以及用法:
<style>
.a {
--main-color: #f40;
--block-font-size: 10px;
}
.aaa {
color: var(--main-color);
}
</style>
</head>
<body>
<div class="a">
<p class="aaa">否定伪类选择符 E:not(s)</p>
</div>
</body>
也就是说,变量可以像普通声明一样写在某个类(或其他任何选择器)里,就可以影响所有后代选择器。
变量名规定
css变量名跟js的变量名比起来宽松得多,比如可以使用数字作为变量名,但是一些IDE会有警告。所以,为了不引起歧义,还是尽量使用严苛的变量名起名法则,可以使用驼峰或者短横线写法,最后,别忘了前面加两个-
。
变量值规定
一句话,凡是css合法值,都可以作为变量值,并不限于单个值,比如20px 20px 20px
是合法的。
调用规定
必须按照语法var( <自定义变量名> [, <默认值 ]? )
来写,可以是var(--aa)
也可以是var(--aa, 20px 20px)
,逗号后面的值就是默认值,当变量名不存在的时候,默认值生效。
可以连续使用var拼接成一个css属性值:margin: var(--aa) var(--bb);
下面这个例子中,没有bb这个变量,但是后面的默认值本身又带有逗号,这种写法是否合法呢?
.aaa {
color: rgb(var(--bb, 255, 255, 255));
}
是合法的,也就是说,浏览器会把第一个逗号之后的内容一概当做默认值。
当变量值书写错误,那么就算引用变量的时候默认值纠正正确,也无济于事,会出错。比如:
body {
--color: 20px;
background-color: #369;
background-color: var(--color, #cd0000);
}
background-color是不可能值为20px
的,那么你用#cd0000
纠正也没有用,此时background-color会等于默认值rgba(0, 0, 0, 0)
,也就是透明。所以,千万别写错。
变量引用
一个变量比如--aa,可以被--bb引用:
body {
--aa: 3px;
--bb: var(--aa);
}
结合calc计算
一句话说,该怎么写就怎么写,变量值的变化会引起重新计算。
变量重新赋值
就像js变量一样,css变量可以重新赋值,这种重新赋值跟书写顺序相关,也跟js一样。比如:
<style>
.a {
--mar: 20px 20px;
}
.b {
margin: var(--mar);
}
.c {
--mar: 40px 40px;
}
.d {
margin: var(--mar);
}
</style>
</head>
<body>
<div class="a">
<div class="b">
<div class="c">
<div class="d"></div>
</div>
</div>
</div>
</body>
这里.d的margin就不是20px 20px。
需要强调的是,变量重新赋值会导致依赖它的其他变量的值也会改变,这跟js是一致的。比如:
.box {
--columns: 4;
--margins: calc(24px / var(--columns));
--space: calc(4px * var(--columns));
--fontSize: calc(20px - 4 / var(--columns));
}
@media screen and (max-width: 1200px) {
.box {
--columns: 3;
}
}
@media screen and (max-width: 900px) {
.box {
--columns: 2;
}
}
@media screen and (max-width: 600px) {
.box {
--columns: 1;
}
}
当浏览器宽度有变化的时候,--columns会变化,连带--margins、--space、--fontSize会一起发生变化,所以只需要改变--columns就可以了。
js向css传值
js给css变量传值的办法是使用el.style.setProperty()方法,比如:
<style>
.b {
color: var(--theme-color);
}
</style>
<div class="a">a
<div class="b">b
<div class="c">c
<div class="d">d</div>
</div>
</div>
</div>
<script>
const aEl = document.querySelector('.a');
aEl.style.setProperty('--theme-color', 'red');
</script>
给a元素设置变量,会影响自身和所有后代元素,但是如果.a自身并没有写color: var(--theme-color);
,那么就可以做到只影响后代元素,不影响自身。
如果想给自身和后代元素设置默认值(即blue),可以写一条:
.a {
--theme-color: blue;
}
js读取css变量
读取办法是使用window.getComputedStyle(el).getPropertyValue('--theme-color')方法。比如:
<style>
.a {
--theme-color: blue;
}
.b {
color: var(--theme-color);
}
</style>
<div class="a">a
<div class="b">b
<div class="c">c
<div class="d">d</div>
</div>
</div>
</div>
<script>
const el = document.querySelector('.a');
const themeColor = window.getComputedStyle(el).getPropertyValue('--theme-color');
console.log(themeColor); // blue
</script>