CSS自定义属性(?.CSS变量)

161 阅读3分钟

什么是CSS的自定义属性

        对于变量,我们应该不会陌生,在每段JS代码里面都有它们的身影,CSS变量其实和JS里面的变量存在异曲同工。

        在2015年,一个名为“用作层叠式变量的自定义属性”(Custom Properties for Cascading Variables)的CSS规范终于发布为“候选推荐标准”(Candidate Recommendation)。这套规范引入了CSS中“变量”的概念,支持一种新的基于上下文的动态样式定义方式。你可以声明一个变量,再给它赋值,然后就可以在样式表的任何地方引用它。你可以通过这样的方式,减少样式表中的重复代码。

        CSS在很大程度上是一种声明式的语言,缺乏动态性。CSS自定义属性的引入,补上了这块短板。

css的自定义属性基本语法

        定义:用这样的方式来声明一个变量:--variable-name: variable-value;(变量名是大小写敏感的)。变量的值可以是颜色、字符串、多个值的组合等;

:root { 
    --main-color: #4d4e53;
    --main-bg: rgb(255, 255, 255);
    --logo-border-color: rebeccapurple;
    --header-height: 68px;
    --content-padding: 10px 20px; 
    --base-line-height: 1.428571429;
    --transition-duration: .35s;
    --external-link: "external link";
    --margin-top: calc(2vh + 20px);
}

        PS:如此丑陋的语言,是因为像$var这样的变量语法,已经被其他的CSS预编译语言使用了。

        用法:以这样的方式来使用一个变量: some-css-value: var(--variable-name [, declaration-value]);

        1)var()函数还可以使用第二个参数,表示变量的默认值。如果该变量不存在,就会使用这个默认值 

p {
    background-color: var(--main-bg,black);
}

        2)变量名不合法

p {
    --color: 10px;
    background-color: yellow;
    background-color: var(--color, green);
}
此时p的背景色是什么?
A rgba(0,0,0,0)  B 10px  C yellow  D gree

        作用域:自定义属性遵循CSS级联规则;`

        1)使用:root ,定义全局变量:`

:root { 
    --global-var: 'global';
}

        2)私有变量:只需要在特定的元素下定义变量

// html
<div class="header">
    <div class="header-inner">my header</div>
</div>
...
// CSS
.header {
    --header-height:2rem;
    height: var(--header-height,1.5rem);
}
.header-inner {
    height: var(--header-height,1rem);
    --header-inner-font-size:1rem;
    font-size:var(--header-inner-font-size,1rem);
}

        PS:可以配合calc(),在私有变量里面计算出属性的值,然后赋值。

        3)媒体查询也可以提供作用域:

@media screen and (min-width: 1025px) { 
    :root { 
        --screen-category: 'desktop'
    }; 
}

        伪类下的作用域(如:hover):

body { 
    --bg: #f00; 
    background-color: var(--bg); 
    transition: background-color 1s; 
} 
body:hover { 
    --bg: #ff0;
}

        变量组合:变量可以和其他变量组合使用,--variable-name: var(--another-variable-name); (注:对复杂的表达式要格外留心,它们很可能会影响到应用的性能 )

.block { 
    --block-text: 'This is my block'; 
    --block-highlight-text: var(--block-text)' with highlight'; 
} 
.block:before { 
    content: var(--block-text);
}
.block__highlight:before {
    content: var(--block-highlight-text); /*This is my block with highlight*/
}

        值的计算(calc()):

body {
  --size: 20;   
  font-size: calc(var(--size) * 1px);
}

        重置和继承:

// html
<div>header</div>
<div class="body">body</div>
...
// css
:root {
  --color: red;
  --border: 4px dashed blue;
  --bgcolor: yellow;
}

div {
  color: var(--color);
  border: var(--border);
  background-color: var(--bgcolor);
}

body {
  --bgcolor: initial;
  --color: green;
  --border: inherit;
}

        兼容性处理:

对于不支持的CSS变量的浏览器,可以采用下面的写法:
a {
  color: #7F583F;
  color: var(--primary);
}
也可以使用@support命令进行检测:
@supports ( (--a0)) {
  /* supported */
}

@supports ( not (--a0)) {
  /* not supported */
}

        在JS中的原生属性(getPropertyValue, setProperty) :

document.documentElement.style.setProperty('--color', blue);
document.documentElement.style.getPropertyValue('--color', blue);

CSS的自定义属性和现有CSS预编译语言的异同点

        现在比较流行的CSS预编译语言主要有Sass和Less,在很多的vue+webpack项目中都能看到它们的身影,在CSS预编译语言中,你可以设置变量,以及函数(calc)、嵌套、混入(mixin)等;

        接下来拿Sass和CSS的自定义属性作比较:

        Sass最普遍的用法就是变量,变量以美元符号开头,赋值方法与 CSS自定义属性的写法几乎一样:

$width: 5em;

直接使用即调用变量:

#main {
  width: $width;
}

对比CSS自定义属性的使用方法,是不是很相似,但是它们之间还是存在本质上的不同,CSS自定义属性是浏览器中直接可用的CSS属性,而预处理语言中的变量是需要编译后才能被浏览器所识别,CSS自定义属性还可以与JS进行交互,创造了更多的可能性,而预处理语言是做不到的!

在实际工作中的应用场景

        1)主题更换

        通过在root根节点定义主题背景颜色,字体颜色等的变量,在用户选择相关主题,通过JS原生属性setProperty更改对应的属性值,达到更换主题的效果;

        2)网页自适应

        很多时候,我们处理网页的自适应,更多的是考虑媒体查询(@media),现在CSS自定义属性跟我们提供了新的思路;

        3)动画

        CSS自定义属性可以通过定义动画的属性或者通过JS方法适时的改变对应CSS的属性,达到想要的动画效果

        4)减少对DOM 的频繁操作

// CSS
body {
  --background-color: #000;
}
 
.header {
  background-color: var(--background-color,'#000');
}
.footer {
  background-color: var(--background-color,'#000');
}
// JS
document.querySelector('body').style.setProperty('--background-color', '#fff');

            以上代码更改className为header和footer的背景色只需要获取到body的DOM,然后更新绑定的CSS自定义属性,减少了对DOM的操作;

css自定义属性的浏览器支持情况

        从目前来看,CSS自定义属性支持多数的主流浏览器,对于吉客云PC端项目可以直接原生使用(chrome版本49),但是为了安全起见,也需要考虑向下兼容,用@supports条件语法来判断。

总结

        CSS的自定义属性拓展了CSS和JS的通信途径,创造更多的可能性!

        CSS的世界还是有很多知识需要我们去学习掌握的,提升自己的技能和知识储备!