根据MDN--CSSProperty[1],@propertyCSSat-rule是CSSHoudiniAPI的一部分,它允许开发者显式定义他们的CSS自定义属性,允许属性类型检查、设置默认值以及定义此自定义属性是否可以被继承。什么是CSS胡迪尼?CSSHoudini向开发者开放了CSS的底层API,让开发者可以通过这套接口自行扩展CSS,并提供相应的工具让开发者干预浏览器渲染引擎的样式和布局过程。允许开发人员编写浏览器可以解析的CSS代码,从而创建新的CSS功能。当然,这不是本文的重点,但我不会过多描述。如何使用CSS属性?我们将从一些简单的例子快速上手,重点介绍它在CSS动画中的关键作用,以及它给CSS动画带来的巨大改进。示例通常,我们定义和使用CSS自定义属性的方式如下::root{--whiteColor:#fff;}p{color:(--whiteColor);}通过@property规则,我们还可以定义CSS自定义属性类似下面的代码:);}简单解释:@property--property-name@property--property-name中的--property-name是自定义属性的名称,可以在CSS中通过var(--property-name)供参考syntax:自定义属性的语法规则,也可以理解为表示定义的自定义属性的类型inherits:是否允许继承initial-value:初始值其中,syntax和inherits在@property规则中需要Descriptor。当然JavaScript中定义的写法也很简单,顺便说一下:支持的syntax语法类型syntax支持的语法类型非常丰富,基本上涵盖了你能想到的所有类型。lengthnumberpercentagelength-percentagecolorimageurlintegerangletimeresolutiontransform-listtransform-functioncustom-ident(自定义标识符字符串)+、#、|insyntax由符号定义的CSS@property变量的语法语法接受一些特殊的类型定义。syntax:'syntax:'syntax:'':acceptasinglelengthoraspace-separatedlistoflengthvaluesOK,铺垫了这么多,那为什么要用这么麻烦的语法来定义CSS自定义属性呢?CustomdefinedbyCSSHoudini变量有什么优点?让我们一一谈谈。使用colorsyntax语法类型作用于渐变我们来看这样一个例子,我们有这样一个渐变图案:
div{background:linear-gradient(45deg,#fff,#000);}我们改造上面代码下面,使用CSS自定义属性代替::root{--colorA:#fff;--colorB:#000;}div{background:linear-gradient(45deg,var(--colorA),var(--colorB));}结果仍然是相同的渐变图像:我们添加一个过渡效果::root{--colorA:#fff;--colorB:#000;}div{background:linear-gradient(45deg,var(--colorA),var(--colorB));transition:1sbackground;&:hover{--colorA:yellowgreen;--colorB:deeppink;}}看看鼠标悬停时会发生什么:虽然我们设置了一个1stransition动画transition:1sbackground,可惜css不支持背景渐变色的直接transition,我们得到的只是两帧之间的变化。使用CSS@property改造OK,接下来就是本文的主角,使用HoudiniAPI中的CSS自定义属性来替换原来的CSS自定义属性。简单修改,使用颜色语法语法类型:@property--houdini-colorA{syntax:'
';inherits:false;initial-value:#fff;}@property--houdini-colorB{syntax:'';inherits:false;initial-value:#000;}.property{background:linear-gradient(45deg,var(--houdini-colorA),var(--houdini-colorB));transition:1s--houdini-colorA,1s--houdini-colorB;&:hover{--houdini-colorA:yellowgreen;--houdini-colorB:deeppink;}}我们使用@property语法定义了两个CSSHoudini自定义变量--houdini-colorA和--houdini-colorB,悬停变化时改变这两种颜色。需要注意的是,我们设置的transition语句是transition:1s--houdini-colorA,1s--houdini-colorB。在这里,我们为CSSHoudini自定义变量设置过渡,而不是为背景设置过渡,再看看这次的效果:哇,成功了,渐变色的变化从两帧逐帧动画变成了补间动画,实现了从一种渐变色过渡到另一种渐变色的效果!而这一切,都得益于CSSHoudini自定义变量的强大能力!CodePenDemo--CSSHoudini自定义变量实现渐变色过渡动画[2]使用CSS@property实现渐变背景色过渡动画在上面的DEMO中,我们使用CSSHoudini自定义变量将原本定义在背景上的过渡效果移植到颜色,而CSS支持从一种颜色到另一种颜色的变换,所以我们巧妙地实现了渐变背景色的过渡动画。之前我们讨论过有多少方法可以在CSS中实现渐变背景色过渡动画——巧妙地制作背景色渐变动画![3],到今天为止,我们有另一种方法来实现它!@property--colorA{syntax:'';inherits:false;initial-value:fuchsia;}@property--colorC{syntax:'';inherits:false;initial-value:#f79188;}@property--colorF{syntax:'';inherits:false;initial-value:red;}div{background:linear-gradient(45deg,var(--colorA),var(--colorC),var(--colorF));animation:change10sinfinitelinear;}@keyframeschange{20%{--colorA:red;--colorC:#a93ee0;--colorF:紫红色;}40%{--colorA:#ff3c41;--colorC:#e228a0;--colorF:#2e4c96;}60%{--colorA:orange;--colorC:green;--colorF:teal;}80%{--colorA:#ae63e4;--colorC:#0ebeff;--colorF:#efc371;}}完整代码可以戳这里:CodePenDemo--CSSHoudini自定义变量实现渐变颜色过渡动画2[4]conic-gradient和CSS@property实现饼图动画OK,我们上面演示的语法是颜色语法类型。在文章的开头,我们也列举了很多语法类型。接下来我们试试其他的类型,用percentage百分比类型或者angle角度类型来实现饼图的悬停动画。如果还是用传统的写法,我们可以用角度渐变来实现不同角度的饼图:.normal{width:200px;height:200px;border-radius:50%;background:conic-gradient(yellowgreen,yellowgreen25%,transparent25%,transparent100%);transition:background300ms;&:hover{background:conic-gradient(yellowgreen,yellowgreen60%,transparent60.1%,transparent100%);}}会得到这样一个效果,由于conic-gradient不支持过渡动画,得到的是直接从一帧到另一帧的变化:OK,使用CSSHoudini自定义变量进行变换:@property--per{syntax:'';inherits:false;initial-value:25%;}div{background:conic-gradient(yellowgreen,yellowgreenvar(--per),transparentvar(--per),transparent100%);transition:--per300mslinear;&:hover{--per:60%;}}看看改造后的效果:CodePodeDemo--conic-gradientwithCSS@property实现饼图动画[5]以前只能用p实现的效果ureCSS很复杂,如果能轻松实现,不得不感慨一下CSS@property的强大能力!|symbolofsyntax在定义Houdini自定义变量时演示了一些稍微复杂的语法用法。在conic-gradient中,我们可以使用百分比或角度作为关键字。上面的DEMO也可以改成这样:@property--per{syntax:'|';inherits:false;initial-value:25%;}...表示我们的自定义属性可以百分比值或角度值。除了|symbol,有+和#符号接受空格分隔和逗号分隔的属性,有兴趣的可以自己试试。使用长度类型来处理一些长度变化。掌握了以上技巧后,我们就可以利用Houdini的自定义变量的能力来填充修复一些之前无法直接转场的效果了。以前我们想实现这样的下划线Hover效果:p{text-underline-offset:1px;text-decoration-line:underline;text-decoration-color:#000;transition:all.3s;&:hover{text-decoration-color:orange;text-underline-offset:10px;color:orange;}}因为text-underline-offset不支持转场动画,结果如下:使用Houdini自定义变量变换,将decay变成魔法:@property--offset{syntax:'';inherits:false;initial-value:0;}div{text-underline-offset:var(--offset,1px);text-decoration:underline;transition:--offset400ms,text-decoration-color400ms;&:hover{--offset:10px;color:orange;text-decoration-color:orange;}}可以获得丝滑的过渡效果:CodePenDemo-Underlineshovertransition(ChromesolutionwithHoudini)[6]让我们用css@property配合后台实现屏保动画嗯,因为css@property的存在,之前需要大量css代码的工作一下子变得简单了。我们尝试使用带背景的CSS@property来简单实现一个屏保动画。我们可以很容易的通过background得到这样的图形,代码如下:html,body{width:100%;height:100%;}body{background-image:radial-gradient(circleat86%7%,rgba(40,40,40,0.04)0%,rgba(40,40,40,0.04)50%,rgba(200,200,200,0.04)50%,rgba(200,200,200,0.04)100%),径向渐变(circleat15%16%,rgba(99,99,99,0.04)0%,rgba(99,99,99,0.04)50%,rgba(45,45,45,0.04)50%,rgba(45,45,45,0.04)100%),径向渐变(circleat75%99%,rgba(243,243,243,0.04)0%,rgba(243,243,243,0.04)50%,rgba(37,37,37,0.04)50%,rgba(37,37,37,0.04)100%),linear-gradient(rgb(34,222,237),rgb(135,89,215));}效果如下,依旧是一张静态的背景图:按照通常的方式,我们想让它动起来,但其实是需要一定的功夫的,现在通过CSS的@property,我们可以对一些我们想要动画的元素的细节进行变换,可以获得非常好的动画效果:body,html{width:100%;height:100%;}@property--perA{syntax:'';inherits:false;initial-value:75%;}@property--perB{syntax:'';inherits:false;initial-value:99%;}@property--perC{syntax:'';inherits:false;initial-value:15%;}@property--perD{syntax:'';inherits:false;initial-value:16%;}@property--perE{syntax:'';inherits:false;initial-value:86%;}@property--angle{syntax:'';inherits:false;初始值:0deg;}body{background-image:radial-gradient(circleatvar(--perE)7%,rgba(40,40,40,0.04)0%,rgba(40,40,40,0.04)50%,rgba(200,200,200,0.04)50%,rgba(200,200,200,0.04)100%),径向梯度(circleatvar(--perC)var(--perD),rgba(99,99,99,0.04)0%,rgba(99,99,99,0.04)50%,rgba(45,45,45,0.04)50%,rgba(45,45,45,0.04)100%),径向渐变(circleatvar(--perA)var(--perB),rgba(243,243,243,0.04)0%,rgba(243,243,243,0.04)50%,rgba(37,37,37,0.04)50%,rgba(37,37,37,0.04)100%),linear-gradient(var(--angle),rgb(34,222,237),rgb(135,89,215));动画:move30sinfinitealternatelinear;}@keyframesmove{100%{--perA:85%;--perB:49%;--perC:45%;--perD:39%;--perE:70%;--angle:360deg;}}效果如下(由于Gif上传大小限制,速度是加速的,截取了GIF的一部分,作为提示):整体效果还是不错的,完整的demo可以点这里:CodePenDemo--CSS@propertyPureCSSWrapper[7]参考:CSSProperties和值APILevell1[8]最后,本文到此结束。它引入了CSSHoudiniAPI中的CSS@property部分,并用它来实现一些以往不容易实现的动画效果。希望对你有所帮助:)更多精彩的CSS技术文章汇总在我的Github——iCSS[9],持续更新中。欢迎点个星订阅收藏。有什么问题或者建议可以多交流,万网告知。参考[1]MDN--CSSProperty:https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property[2]CodePenDemo--CSSHoudini自定义变量实现渐变过渡动画:https://codepen.io/Chokcoco/pen/eYgyWLB?editors=1100[3]巧妙制作背景色渐变动画!:https://github.com/chokcoco/iCSS/issues/10[4]CodePenDemo--CSSHoudini自定义变量实现渐变过渡动画2:https://codepen.io/Chokcoco/pen/Bapmzbd[5]CodePodeDemo--conic-gradientwithCSS@property实现饼图动画:https://codepen.io/Chokcoco/pen/QWdqMvo[6]CodePenDemo-Underlineshovertransition(ChromesolutionwithHoudini):https://codepen.io/Chokcoco/pen/jOymJZR[7]CodePenDemo--CSS@propertyPureCSSWrapper:https://codepen.io/Chokcoco/pen/VwPxMBP[8]CSS属性和值APILevel1:https://drafts.c??ss-houdini.org/css-properties-values-api-1/#at-property-rule[9]Github--iCSS:https://github.com/chokcoco/iCSS