什么是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 ( (--a: 0)) {
/* supported */
}
@supports ( not (--a: 0)) {
/* 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的世界还是有很多知识需要我们去学习掌握的,提升自己的技能和知识储备!