内容简介:CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?其实CSS自定义属性还有很多小名,比如说到变量,在SCSS\LESS等CSS预处理器中大家都已经经常运用,说来有几点好处:
CSS自定义属性?听着怎么那么神奇呢,属性还可以自定义,那不是可以放肆地玩耍?我自己定义的属性浏览器都能认识?
一、基础
(一)名字和用途
其实CSS自定义属性还有很多小名,比如 CSS变量 、 原生变量 、 CSS自定义属性级联变量 ,这些指的都是同个东西。
说到变量,在SCSS\LESS等CSS预处理器中大家都已经经常运用,说来有几点好处:
1、能使用颜色变量统一风格;
2、可以采用一致的组件属性,包括布局和定位等;
3、避免代码冗余。
那既然SCSS就能做到的东西,我们还有这个所谓的CSS自定义变量干什么呢?人家自然有它的独到之处。
1、比如可以在运行时改写,具备动态性;
2、比如方便使用JS读取和改写;
3、比如可继承、可组合、同时具有作用域。
在这几个方面,预处理器完全被CSS自定义变量KO了。
(二)声明变量
语法很简单,分成两步, 声明变量 和 使用变量 。
声明变量使用的是 --
前缀。
:root{ --*: xxxx; /* --variety-name: variety-value; */ } 复制代码
这里需要注意几个点:
-
:root
匹配的就是HTML中的<html>
元素,具有最高的权重,:root
声明的变量就是全局变量; - CSS自定义变量对大小写敏感,
--color
和--Color
是两个变量; - 变量必须声明在{}中,如果在这里把它理解为属性就更好记忆了,毕竟我们不会把CSS属性写到括号外边去;
- *号代表的就是我们给变量起的名字。起名字这事真的很烦人,还好CSS变量的名称限制很少,除了一些特殊关键字符不能使用,正常来说你用数字/字母/下划线_/短横线-都是没问题的,据说还可以使用中文、日文和韩文。
: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的背景色为透明,取的是这个属性的默认值 */ } 复制代码
(四)作用域和权重
1、如果你需要定义一个全局的变量,那么可以放在 :root
根元素下面;
2、如果只需要在部分元素/组件下使用,就定义在相关的类下面;
3、另外还可以在 @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); /* 通过计算后传递 */ } 复制代码
二、在JS中使用
读: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自定义变量
介绍了这么多,那么CSS自定义变量到底都在什么场景下应用呢?
一、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体验一下吧。
codepen.io/Apollozz/pe…二、主题色处理
预处理器提供了很多高级的颜色方法,可以实现颜色的高亮、变暗或去饱和等等;
$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改变颜色
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))); } 复制代码codepen.io/Apollozz/pe…
(二)使用hsl改变颜色
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%)); } 复制代码codepen.io/Apollozz/pe…
(三)使用遮罩改变颜色
如果不通过改变色值来改变颜色的话,可以选择遮上一个半透明的蒙层来改变颜色,加深颜色则选择黑色半透明蒙层,提亮颜色则选择白色半透明蒙层。
.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); } } 复制代码codepen.io/Apollozz/pe…
三、兼容性
目前CSS自定义变量的兼容性还是比较可观的,新的主流浏览器都支持。
PC端主要是IE这块硬石头,而移动端则主要是低端机型系统例如ios9.2及以下/安卓4.4及以下不支持,这样的兼容性已经足以允许让我们在项目中开始使用CSS自定义属性,并对一些低端版本进行降低兼容处理。
对于不支持的浏览器可以采用下列兼容方式:
方案1:直接设置一个默认颜色
直接使用普通的属性定义,兼容所有的浏览器,保证显示正常。
button{ background: #F00; /* 默认颜色,若不支持CSS自定义属性则应用该默认颜色 */ background: var(--THEME-COLOR, #F00); /* 在实践中发现有些机型虽然能识别到CSS自定义变量但是无法获取正确颜色,只能获取到默认值 */ } 复制代码
方案2:CSS根据@supports判断是否兼容并适配
低端机型也无法正确识别@supports,@supports的兼容性只比CSS自定义变量好一丢丢。
@supports ( (--a: 0)) { /* supported */ } @supports ( not (--a: 0)) { /* not supported */ } 复制代码
方案3:js根据@supports判断是否兼容并适配
const isSupported = window.CSS && window.CSS.supports && window.CSS.supports('--a', 0); if (isSupported) { /* supported 引入支持自定义变量的CSS,允许更改CSS自定义变量 */ } else { /* not supported 引入兼容的CSS文件 */ } 复制代码
四、注意事项
- 在一些浏览器中,针对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> 复制代码
五、小结
- CSS自定义变量目前已支持各主流浏览器,低端版本可以采用兼容方案;
- SCSS变量和CSS自定义变量有本质上的区别,用来解决不同场景下的问题,CSS自定义属性用于动态主题,预处理器变量用于静态模板,项目中可以根据情况结合运用效果更佳;
- 在媒体查询中使用自定义变量的话,这样响应式设计相关的逻辑与正常的设计虽然分离,但是无论我们在哪里看到var( )声明语句,我们都能很明显的知道这个属性会发生变化。而使用传统的CSS方式,我们是无法察觉这一点的,这样代码的可读性就高了很多。
参考资料
以上所述就是小编给大家介绍的《[CSS] 自定义变量带你随心所欲,一键换肤》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- CVPR 2018论文:「随心所欲」换装换姿态
- UKUI 3.0 揭秘 - 控制面板,随心所欲的沟通
- CVPR 2020 | 看图说话之随心所欲:细粒度可控的图像描述自动生成
- Proxy-Go v6.6 发布,智能模式设置让你随心所欲!
- Proxy-Go v6.6 发布,智能模式设置让你随心所欲!
- 黑客眼中的智能家居啥样?全是漏洞,出入随心
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。