CSS变量及其与JS交互
CSS变量
CSS变量,即CSS variable。官方的名称是级联变量的CSS自定义属性,即CSS custom properties for cascading variables。类似于sass,less等预处理器的变量。css变量同样具备声明,引用,以及作用域等变量特性。CSS 引入了一种层级变量的概念,从而能够从容应对可维护性的挑战。这就会使得在整个 CSS tree 中都可以象征性的引用一个变量。
CSS变量有着天然优势。不同于预处理器,必须最终编译成普通的css代码,CSS变量可以被浏览器识别解析,甚至可以用javascript访问或重新赋值。比如,在线修改一个网站主题色,只需修改相应变量即可实现。某种意义上,这为css开启了一扇通向各种可能性的大门。可以自定义变量名称,使变量更有语义,更有可读性。毕竟primary-color比#0055aa更容易理解,特别是同样的颜色出现在不同的文件中的时候,颜色之间的关联关系更加直观。
CSS变量也叫CSS自定义属。即为属性,同样是由合法的标识和合法的值组成。不同于普通属性,自定义属性有"--"前缀,早期的标准也有采用"var-"作为前缀。之所以会采用"--",是因为通常变量声明常用的前缀"$"或者"@"已经被预处理器sass和Less占用了。为了保证css变量和预处理器变量不产生冲突,所以采用了"--"。
1 /*声明变量*/
2 :root{
3 --primary-color: green;
4 }
5 /*引用变量*/
6 .primary-button{
7 background: var(--primary-color)
8 }
var函数可以设置一个默认值,如果变量不存在直接使用默认值
1 /*定义了--color背景为绿色,否则使用默认值红色*/
2 :root {
3 --themeColor:green;
4 }
5 body {
6 background-color:var(--themeColor, red);
7 }
变量声明中,属性值不能直接进行数学运算,需要借助calc()函数,如果是字符串,则可直接拼接。
1 /*正确,数字可计算拼接*/
2 body {
3 --fontSize: 20;
4 margin-top: calc(var(--fontSize) * 1px);
5 }
6 /*正确,字符创可直接拼接*/
7 body {
8 --backgroundColor: green;
9 background: var(--backgroundColor, red) url(../../images/background.jpg) no-repeat fixed top;
10 }
11 /*错误,数字不可直接拼接*/
12 .box {
13 --size-one:14;
14 font-size:var(--size-one)px;
15 }
CSS变量可以用在任意css选择器中,甚至可以用在style以及@media中。读取的时候,优先级最高的声明生效,子元素的变量值会覆盖父元素的值,这与 CSS 的"层叠"(cascade)规则是一致的。
1 /*发生覆盖,最终为红色*/
2 :root {
3 --color: green;
4 }
5 body {
6 --color: red;
7 }
变量值可以是有效的css属性值,比如颜色,尺寸,定位,角度,字符串,数字等,也可以是多个字段的组合,甚至可以是javascript语句
1 :root{
2 --main-color: #4d4e53;
3 --main-bg: rgb(255, 255, 255);
4 --logo-border-color: rebeccapurple;
5 --header-height: 68px;
6 --content-padding: 10px 20px;
7 --base-line-height: 1.428571429;
8 --transition-duration: .35s;
9 --external-link: "external link";
10 --margin-top: calc(2vh + 20px);
11 --foo: if(x > 5) this.width = 10;
12 }
JS交互
CSS 里面定义的JS代码,对于CSS来说是无效值,但是可以被 JavaScript 读取。这意味着,CSS 变量提供了 JavaScript 与 CSS 通信的一种途径。
javaScript检测浏览器是否支持 CSS 变量
1 const isSupported =
2 window.CSS &&
3 window.CSS.supports &&
4 window.CSS.supports('--a', 0);
5
6 if (isSupported) {
7 /* supported */
8 } else {
9 /* not supported */
10 }
JS读取CSS变量
1 root.style.getPropertyValue('--color').trim();
但这种使用原生element的方式读取css属性的方法,仅仅读取root.style中声明的变量,并不能读取:root选择器中声明的变量,读取选择器中的变量,需要借助styleSheet或者getComputedStyle。
1 //获取变量
2 const root = document.documentElement;
3 let root_computed = getComputedStyle(root);
4 root_computed.getPropertyValue('--color').trim();
5 //设置变量
6 root.style.setProperty('--color','green');
7 //删除变量
8 root.style.removeProperty('--color');
针对更换主题的需求,我们可以这样
1 <style>
2 :root.global__style--primary {
3 --button-color: green;
4 --button-font-size:14px;
5 --button-text-color: #fffff;
6 }
7 :root.global__style--warning {
8 --button-color:orange;
9 --button-font-size:12px;
10 --button-text-color:#fffff;
11 }
12 .button {
13 background-color:var(--button-color);
14 font-size:var(--button-font-size);
15 color:var(--button-text-color);
16 }
17 </style>
18 <script>
19 //通过操作root的className,更新变量
20 let root = document.documentElement;
21 root.className = 'global__style--primary'
22 // or
23 root.className = 'global__style--warning'
24 </script>
监听事件:实现的简单鼠标跟随
1 <html>
2 <head>
3 <style>
4 .mover {
5 width: 50px;
6 height: 50px;
7 background: red;
8 position: absolute;
9 left: var(--mouse-x);
10 top: var(--mouse-y);
11 }
12 </style>
13 <script>
14 let root = document.documentElement;
15 root.addEventListener("mousemove", e => {
16 root.style.setProperty('--mouse-x', e.clientX + "px");
17 root.style.setProperty('--mouse-y', e.clientY + "px");
18 });
19 </script>
20 </head>
21 <body>
22 <div class="mover"></div>
23 </body>
24 </html>