当前位置: 首页 > 科技观察

使用CSS变量,让你的CSS更精彩

时间:2023-03-21 01:26:47 科技观察

前言“CSS变量”也叫“CSS自定义属性”。怎么突然提这个很少人用的东西?因为最近重构了自己的官网,不知道为什么突然喜欢用“CSS变量”。或许它隐藏的魅力让笔者为之倾倒吧。说到CSS为什么要用变量,我们举个栗子,估计大家一看就明白了。/*不使用CSS变量*/.title{background-color:red;}.desc{background-color:red;}/*使用CSS变量*/:root{--bg-color:red;}.title{background-color:var(--bg-color);}.desc{background-color:var(--bg-color);}看完之后,你可能会觉得使用“CSS变量”的代码量是有点多,不过有想不到有一天,邪恶的策划师兄和设计小姐姐说要做一个换皮功能。按照通常的思路,估计有的同学会根据默认的颜色主题添加一个新的颜色主题CSS文件进行对比。每次有新的需求要同时维护好几套主题色是多么的麻烦啊。这时候,“CSS变量”就派上用场了。可以事先和设计小姐姐指定需要更改的颜色,通过“CSS变量”定义,通过JS批量操作这些定义好的“CSS变量”。这也是“换主题色”的解决方案之一。好处是只需要写一套CSS代码。["red","blue","green"].forEach(v=>{constbtn=document.getElementById(`${v}-theme-btn`);btn.addEventListener("click",()=>document.body.style.setProperty("--bg-color",v));});这里总结一下在CSS中使用变量的好处:减少样式代码的重复增加样式代码的可扩展性提高样式代码的灵活性增加一种CSS和JS之间的通信方式,无需深入遍历DOM来改变某个style可能有同学会问,Sass和Less都已经实现了变量的特性,何必呢。但是仔细想想,“CSS变量”相对于Sass和Less的变量还是有它的优势的。浏览器的原生特性可以直接运行DOM对象的一个??成员,不需要任何的翻译,极大的方便了CSS和JS的衔接如果有很多,感觉没必要。贴上阮一峰老师写的教程《CSS变量教程》。同时笔者也对“CSS变量”的细节进行了整理,方便大家记忆。声明:--变量名读作:var(--变量名,默认值)typenormal:只能作为属性值,不能作为属性名字符:与字符串“Hello,”连接var(--name)value:使用带有数值单位的calc(),使用var(--width)*10px作用域:在当前元素块作用域及其子元素块作用域范围内有效优先级:内联样式>ID选择器>类选择器=属性选择器=伪类选择器>标签选择器=伪元素选择器下面通过几个特殊场景来展示“CSS变量”的魅力。还是那句话,“有使用场景的东西,自然就有它的价值”,用的人会越来越多。使用场景事实上,“CSSVariables”有一个特别有用的场景,那就是可以和List元素的集合结合使用。如果您不明白这是什么,请继续阅读。下面所有的demo代码都是基于vue文件,但是html、css、js是分开写的。为了简化CSS编写,使用Sass进行预处理,方便代码演示。一个barloadingbar通常由几行组成,每行对应同一个动画不同的延时,通过时间差运行同一个动画产生loading效果。估计大部分同学可能会把CSS代码写成下面这样。.loading{width:200px;height:200px;li{border-radius:3px;width:6px;height:30px;background-color:#f66;animation:beat1sease-in-outinfinite;&+li{margin-left:5px;}&:nth-child(2){animation-延迟:200ms;}&:nth-child(3){animation-delay:400ms;}&:nth-child(4){animation-delay:600ms;}&:nth-child(5){animation-delay:800ms;}&:nth-child(6){animation-delay:1s;}}}分析代码发现每个

  • 只是animation-delay不同,其余代码完全一样,换成其他类似的List如果有10个
  • ,写10:nth-child。显然,这种方式不够灵活,也不容易封装成组件。如果能像JS一样封装成一个函数,根据参数输出不同的样式效果就更好了。说了这么多,显然是为了铺垫“CSS变量”的开发技巧。对于HTML部分的修改,让每个
  • 在自己的作用域下都有一个“CSS变量”。对于CSS部分的修改,需要分析哪些属性随着索引的增加有规律的变化,将规律变化的部分替换为“CSS变量”表达式。
  • /ul>.strip-loading{width:200px;height:200px;li{--time:calc((var(--line-index)-1)*200ms);border-radius:3px;width:6px;height:30px;background-color:#f66;animation:beat1.5sease-in-outvar(--time)infinite;&+li{margin-left:5px;}}}代码中可以获取源码链接文章末尾的变量--line-index和--time使每个
  • 都有自己的作用域。比如第二个
  • 中,--line-index的值为2,--time的计算值为200ms。换成第三个
  • 后,这两个值又会不一样了。这是由于“CSS变量”的作用域(在当前元素及其子元素的块作用域下有效),所以在.strip-loading的块作用域下调用--line-index是无效的。/*flex属性无效*/.loading{display:flex;align-items:center;flex:var(--line-index);}通过使用“CSS变量”,CSS代码也从29行减少到15行,对于那些包含多组List元素的场景,效果更明显。而且这种写法更美观,也更容易维护。有一天,据说加载效果的时间差不明显。只需将calc((var(--line-index)-1)*200ms)中的200ms调整为400ms。无需修改每个:nth-child(n)。心形加载条前段时间在用掘金的时候看到陈大鱼头哥的心形加载条,觉得很漂亮,也很有意思。通过动画分析,发现每行的背景色与动画延迟不一致,动画的高度也不一致。细心的话,你可能还会发现第1条和第9条的高度相同,第2条和第8条的高度相同,以此类推,得到同类型高度变换的公式:对称指数=总数+1-指数。背景色使用滤镜的hue-rotate功能,使颜色过渡更自然;动画延迟设置和上面barloadingbar的设置一致。让我们根据您看到的动画使用“CSS变量”来实现它。
  • .heart-loading{width:200px;height:200px;ul{display:flex;justify-content:space-between;width:150px;height:10px;}li{--Θ:calc(var(--line-index)/var(--line-count)*.5turn);--time:calc((var(--line-index)-1)*40ms);border-radius:5px;width:10px;height:10px;background-color:#3c9;filter:hue-rotate(var(--Θ));animation-duration:1s;animation-delay:var(--time);animation-iteration-count:infinite;}.line-1,.line-9{animation-name:line-move-1;}.line-2,.line-8{动画名称:line-move-2;}.line-3,.line-7{动画名称:line-move-3;}.line-4,.line-6{animation-name:line-move-4;}.line-5{animation-name:line-move-5;}}源码链接可在文末一波后获取的操作,会有如下效果。与陈大鱼头的心形加载条相比,颜色、波动曲线和跳动频率都有些不同。随着暖色的蔓延和肾上腺素的激增,这是一种心跳加速的感觉。想起自己曾经写过的一首诗:见之怜惜,放不下。标签导航栏上的两个加载栏演示了CSS中“CSS变量”的使用和一些神奇的技巧。现在,通过标签导航栏来演示“CSS变量”在JS中的使用。JS中操作“CSS变量”的API主要有3个,看起来简单易记,分别是:读取变量:elem.style.getPropertyValue()设置变量:elem.style.setProperty()删除变量:elem.style.removeProperty()先上传效果图。该效果主要使用“CSS变量”来标记各个Tab的背景色,切换Tab的显示状态。
    内容{{i+1}}
    .tab-navbar{display:flex;overflow:hidden;flex-direction:column-reverse;border-radius:10px;width:300px;height:400px;nav{display:flex;height:40px;background-color:#f0f0f0;line-height:40px;text-align:center;a{flex:1;cursor:pointer;transition:all300ms;&.active{background-color:#66f;字体粗细:粗体;颜色:#fff;}}}div{flex:1;ul{--tab-index:0;--tab-width:calc(var(--tab-count)*100%);--tab-move:calc(var(--tab-index)/var(--tab-count)*-100%);display:flex;flex-wrap:nowrap;width:var(--tab-宽度);高度:100%;转换:翻译e3d(var(--tab-move),0,0);transition:all300ms;}li{display:flex;justify-content:center;align-items:center;flex:1;background-color:var(--bg-color);font-weight:bold;font-size:20px;color:#fff;}}}exportdefault{data(){return{index:0,list:["#f66","#09f","#3c9"]};},方法:{select(i){this.index=i;this.$refs.tabs.style.setProperty("--tab-index",i);}}};源码链接可在文末获取。在