CSS自定义属性?听着怎么那么神奇呢,属性还能够自定义,那不是能够放肆地玩耍?我本身定义的属性浏览器都能认识?css
其实CSS自定义属性还有不少小名,好比CSS变量、原生变量、CSS自定义属性级联变量,这些指的都是同个东西。html
说到变量,在SCSS\LESS等CSS预处理器中你们都已经常常运用,说来有几点好处:ios
一、能使用颜色变量统一风格;
二、能够采用一致的组件属性,包括布局和定位等;
三、避免代码冗余。css3
那既然SCSS就能作到的东西,咱们还有这个所谓的CSS自定义变量干什么呢?人家天然有它的独到之处。web
一、好比能够在运行时改写,具有动态性;
二、好比方便使用JS读取和改写;
三、好比可继承、可组合、同时具备做用域。小程序
在这几个方面,预处理器彻底被CSS自定义变量KO了。浏览器
语法很简单,分红两步,声明变量和使用变量。bash
声明变量使用的是--
前缀。wordpress
:root{
--*: xxxx;
/* --variety-name: variety-value; */
}
复制代码
这里须要注意几个点:函数
:root
匹配的就是HTML中的<html>
元素,具备最高的权重,:root
声明的变量就是全局变量;--color
和--Color
是两个变量;:root{
--黑色:#000;
}
body{
background: var(--黑色);
}
复制代码
手贱如我试了一下,真的能够识别。可是,为了世界和平请答应我不要这么写。
很简单,就是咱们很熟悉的var
关键字。
/* 定义变量 */
:root{
--*: #000;
/* 例如 --color-bg: #000; */
}
/* 使用变量 */
body{
background: var(--*);
/* 例如 background: var(--color-bg); */
}
复制代码
还有一种设置默认值的使用,就是在变量名称后面,加上一个默认值。
.div{
background: var(--变量名称,[默认值]);
/* 例如 background: var(--color-bg, #000); */
}
复制代码
也就是说,当这个变量没有被声明过的话,就会使用默认值,不至于没着没落的。
注意这里的状况是变量没有被声明过,要是变量是声明过的,可是使用起来是不合法的,那么就会采用原来属性的缺省默认值,并非后面这个你设定的默认值。
p{
background-color: var(--color, #000);
/* --color没有声明过,因此这里的p元素背景颜色时候用了默认值#000 */
}
复制代码
div{
--color: 20px;
background-color: var(--color, #000);
/* 很明显,background-color: 20px;是有语法错误的,因此这里div的背景色为透明,取的是这个属性的默认值 */
}
复制代码
一、若是你须要定义一个全局的变量,那么能够放在
:root
根元素下面;
二、若是只须要在部分元素/组件下使用,就定义在相关的类下面;
三、另外还能够在@media
媒体查询中或者:hover
等伪类中使用。
理解了做用域,那么权重也是一样的道理,由于CSS自定义变量是能够继承的,因此权重跟咱们平时的属性权重理解是同样的。
这里引用一下张鑫旭大神的例子给你们出道题。
:root{
--color: purple;
}
div{
--color: green;
}
#alert{
--color: red;
}
*{
color: var(--color);
}
复制代码
<p>请问我是什么颜色</p>
<div>请问我是什么颜色</div>
<div id="alert">
请问我是什么颜色
<p>请问我是什么颜色</p>
<p style="--color: grey;">请问我是什么颜色</p>
</div>
复制代码
答案以下:
除了上述的一些用法,CSS自定义变量也可使用calc()
函数进行计算,或者进行字符串拼接。
这里举了三个例子,具体的说明在注释中。
p{
--fz: 50;
font-size: var(--fz)px;
/* 不要太天真,这样是错的 */
}
复制代码
p{
--fz: 50;
font-szie: calc(var(--fz) * 1px);
/* 若是你必定要这么用,可使用calc计算函数 */
}
复制代码
p::after{
--text: "hellp";
content: var(--text) " word";
/* 可是字符串的拼接是能够实现的 */
}
复制代码
固然,变量不止能够直接使用,直接或者经过计算把值传递给另外一个变量也是可行的。
p{
--fz: 20px;
--fz-lg: var(--fz);
font-size: var(--fz-lg);
/* 直接传递 */
}
复制代码
p{
--fz: 20px;
--fz-lg: calc(var(--fz) * 1.5);
font-size: var(--fz-lg);
/* 经过计算后传递 */
}
复制代码
读:getPropertyValue( )
写:setProperty( )
好比说,你在:root
上定义了一个color变量,用于设置页面的主题色,那么经过下面的JS,你就能够很简单地改变color变量的值,从而改变页面的主题色。换个皮肤,so easy。
// 读取数据
const rootStyles = getComputedStyle(document.documentElement);
const varValue = rootStyles.getPropertyValue('--color').trim();
// 改写数据
document.documentElement.style.setProperty('--color', value);
复制代码
固然用处不止用来换肤,充分发挥你的想象力,看看CSS变量与JS的结合能产生什么样奇妙的效果~附上大漠老师的小DEMO。
介绍了这么多,那么CSS自定义变量到底都在什么场景下应用呢?
最强的应用固然是一键换肤啦!
通常状况下,咱们如果想根据不一样的合做方或者不一样的应用更换主题颜色,通常使用预处理器先定义一个全局主题颜色,如:
$theme-color: #f00;
button{
background: $theme-color;
}
复制代码
最后编译获得一个定制的CSS文件,如:
button{
background: #f00;
}
复制代码
这样咱们就能够经过引入这个特殊的CSS文件,获得一套主题色为红色的页面样式。
第一种形式适用于,功能通用可是最后根据配置输出一个产品的独立管理台、一个独立小程序等,这样用本身一套独有的CSS文件就很方便。
可是若是咱们提供一个通用的产品去接入不一样的合做方,接入方都有定制主题的需求,就能够选择预处理器或CSS自定义属性。
/* 预处理器方式,先定义不一样的主题色 */
$theme-color-a: #f00;
$theme-color-b: #0f0;
/* 在页面层级最外层加上定制的类名,类名中全部样式都须要从新覆盖一遍 */
.project-a{
button{
background: $theme-color-a;
}
a{
color: $theme-color-a;
}
}
.project-b{
button{
background: $theme-color-b;
}
a{
color: $theme-color-b;
}
}
/* 或者在媒体查询中须要重置样式 */
$fz-sm: 12px;
$fz-md: 14px;
button{
font-size: $fz-sm;
}
a{
font-size: $fz-sm;
}
@media (min-width: 375px){
button{
font-size: $fz-md;
}
a{
font-size: $fz-md;
}
}
复制代码
:root{
--FZ: 12px;
}
/* 照常写一套样式 */
button{
background: var(--THEME-COLOR, #fff);
}
a{
color: var(--THEME-COLOR, #fff);
}
/* 根据不一样的接入方设置主题色 */
.project-a{
--THEME-COLOR: #f00;
}
.project-b{
--THEME-COLOR: #0f0;
}
@media (min-width: 375px){
:root{
--FZ: 14px;
}
}
复制代码
这种需求在CSS预处理器中没法实现一个没有复制代码的方案,老是须要覆盖实现的值和规则,这也常常会致使CSS冗余。
使用CSS自定义属性,解决方案是尽量的简洁,也避免复制和粘贴代码,由于只要从新定义变量的值,不须要去覆盖一次样式。
第二种方式中两个方式的区别则是,预处理器中变量的做用域是没法继承的,而CSS自定义变量则相对灵活,这样一旦接入方多了以后,两种方式的代码量就会有质的区别。
以上两种方式都仍是直接把主题色配置在CSS中。可是若是须要接入管理台,让合做方直接在管理台设置主题色的话,预处理器这种静态的方式就直接退出了竞争,CSS自定义属性的绝对优点就出来了。
:root{
--THEME-COLOR: #fff;
}
button{
background: var(--THEME-COLOR);
}
a{
color: var(--THEME-COLOR);
}
复制代码
let value = #f00; //或者经过请求获取配置的主题色
document.documentElement.style.setProperty('--THEME-COLOR', value);
复制代码
第三种方式则很是灵活,咱们能够经过管理台或者其余配置的方式,传递合做方主题色,一键应用便可。
历史性的时刻诞生了,今后接入就是分分钟的事,直接读取管理台的配置,更改CSS自定义属性。来个小DEMO体验一下吧。
预处理器提供了不少高级的颜色方法,能够实现颜色的高亮、变暗或去饱和等等;
$color: #f00;
.lighten{
background: lighten($color,10%);
}
.darken{
background: darken($color,10%);
}
.desaturate{
background: desaturate($color,10%);
}
复制代码
这样编译出来的结果就是
.lighten{
background: #ff3333;
}
.darken{
background: #cc0000;
}
.desaturate{
background: #f20d0d;
}
复制代码
这些方法没法直接使用在CSS自定义属性中,可是咱们能够经过rgb( )或者hsl( )来调整主题颜色的色调或亮度。
rgb颜色变亮变暗的原理相对简单,只需修改--COLOR-R
/--COLOR-G
/--COLOR-B
的值,利用calc函数对rgb的值进行线性增减便可。
:root{
--COLOR-R: 25;
--COLOR-G: 153;
--COLOR-B: 112;
--DARKEN: 30; // 加深程度
--LIGHTEN: 30; // 变亮程度
--THEME-COLOR: rgb(var(--COLOR-R), var(--COLOR-G), var(--COLOR-B));
--THEME-COLOR-DARKEN: rgb(calc(var(--COLOR-R) - var(--DARKEN)), calc(var(--COLOR-G) - var(--DARKEN)), calc(var(--COLOR-B) - var(--DARKEN)));
--THEME-COLOR-LIGHTEN: rgb(calc(var(--COLOR-R) + var(--LIGHTEN)), calc(var(--COLOR-G) + var(--LIGHTEN)), calc(var(--COLOR-B) + var(--LIGHTEN)));
}
复制代码
rgb咱们可能相对熟悉,可是hsl用得比较少,下面简单介绍一下hsl的原理,详细内容请点击连接。
与RGB使用的三色光不一样,HSL一样使用了3个份量来描述色彩,HSL色彩的表述方式是:H(hue)色相,S(saturation)饱和度,以及L(lightness)亮度。
HSL的H(hue)份量,表明的是人眼所能感知的颜色范围,这些颜色分布在一个平面的色相环上,取值范围是0°到360°的圆心角,每一个角度能够表明一种颜色。
HSL的S(saturation)份量,指的是色彩的饱和度,它用0%至100%的值描述了相同色相、明度下色彩纯度的变化。数值越大,颜色中的灰色越少,颜色越鲜艳,呈现一种从理性(灰度)到感性(纯色)的变化。
HSL的L(lightness)份量,指的是色彩的明度,做用是控制色彩的明暗变化。它一样使用了0%至100%的取值范围。数值越小,色彩越暗,越接近于黑色;数值越大,色彩越亮,越接近于白色。
通常来讲,咱们须要按钮在hover状态时加深颜色,此时应用的原理是将颜色的hsl值中的L也就是亮度调低。
:root{
--COLOR-H: 29;
--COLOR-S: 100;
--COLOR-L: 50;
--DARKEN: 0.15;
--THEME-COLOR: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * 1%));
--THEME-COLOR-DARKEN: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * (1 - var(--DARKEN)) * 1%));
--THEME-COLOR-LIGHTEN: hsl(var(--COLOR-H), calc(var(--COLOR-S) * 1%), calc(var(--COLOR-L) * (1 + var(--DARKEN)) * 1%));
}
复制代码
若是不经过改变色值来改变颜色的话,能够选择遮上一个半透明的蒙层来改变颜色,加深颜色则选择黑色半透明蒙层,提亮颜色则选择白色半透明蒙层。
.button_color{
position: relative;
color: #fff;
background: var(--THEME-COLOR);
border: 1px solid var(--THEME-COLOR);
&:after{
content: "";
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transition: all 0.2s;
}
/* 黑色半透明蒙层 */
&:hover:after{
background: rgba(0,0,0,0.05);
}
/* 白色半透明蒙层 */
&.lighten:hover:after{
background: rgba(255,255,255,0.1);
}
}
复制代码
目前CSS自定义变量的兼容性仍是比较可观的,新的主流浏览器都支持。
PC端主要是IE这块硬石头,而移动端则主要是低端机型系统例如ios9.2及如下/安卓4.4及如下不支持,这样的兼容性已经足以容许让咱们在项目中开始使用CSS自定义属性,并对一些低端版本进行下降兼容处理。
对于不支持的浏览器能够采用下列兼容方式:
直接使用普通的属性定义,兼容全部的浏览器,保证显示正常。
button{
background: #F00;
/* 默认颜色,若不支持CSS自定义属性则应用该默认颜色 */
background: var(--THEME-COLOR, #F00);
/* 在实践中发现有些机型虽然能识别到CSS自定义变量可是没法获取正确颜色,只能获取到默认值 */
}
复制代码
低端机型也没法正确识别@supports,@supports的兼容性只比CSS自定义变量好一丢丢。
@supports ( (--a: 0)) {
/* supported */
}
@supports ( not (--a: 0)) {
/* not supported */
}
复制代码
const isSupported =
window.CSS &&
window.CSS.supports &&
window.CSS.supports('--a', 0);
if (isSupported) {
/* supported 引入支持自定义变量的CSS,容许更改CSS自定义变量 */
} else {
/* not supported 引入兼容的CSS文件 */
}
复制代码
calc()
运算可能不能工做;calc()
运算时,最好能提供默认值:calc(var(--base-line-height, 0) * 1rem)
;@media screen and (min-width: var(--desktop-breakpoint) ) {
};
复制代码
url( var(--image-url) )
,不会生效;html
,并经过上述方法修改自定义属性的值;.container{
--THEME-COLOR: #f00;
}
复制代码
<view class="container" style="--THEME-COLOR: #0f0;">
<!-- 该结构下的元素,重置为行内样式的主题色 -->
</view>
复制代码