CSS @property,让不可能变可能
创始人
2024-02-17 06:17:03

本文主要讲讲 CSS 非常新的一个特性,CSS @property,它的出现,极大的增强的 CSS 的能力!

根据 MDN -- CSS Property,@property CSS at-rule 是 CSS Houdini API 的一部分, 它允许开发者显式地定义他们的 CSS 自定义属性,允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。

CSS Houdini 又是什么呢,CSS Houdini 开放 CSS 的底层 API 给开发者,使得开发者可以通过这套接口自行扩展 CSS,并提供相应的工具允许开发者介入浏览器渲染引擎的样式和布局流程中,使开发人员可以编写浏览器可以解析的 CSS 代码,从而创建新的 CSS 功能。当然,它不是本文的重点,不过多描述。

CSS Property 如何使用呢?我们将通过一些简单的例子快速上手,并且着重介绍它在 CSS 动画中起到的关键性的作用,对 CSS 动画带来的巨大提升。

示例

正常而言,我们定义和使用一个 CSS 自定义属性的方法是这样的:

:root {--whiteColor: #fff;
}p {color: (--whiteColor);
}
复制代码

而有了 @property 规则之后,我们还可以像下述代码这样去定义个 CSS 自定义属性:


复制代码

简单解读下:

  • @property --property-name 中的 --property-name 就是自定义属性的名称,定义后可在 CSS 中通过 var(--property-name) 进行引用
  • syntax:该自定义属性的语法规则,也可以理解为表示定义的自定义属性的类型
  • inherits:是否允许继承
  • initial-value:初始值

其中,@property 规则中的 syntax 和 inherits 描述符是必需的。

当然,在 JavaScript 内定义的写法也很简单,顺便一提:


复制代码

支持的 syntax 语法类型

syntax 支持的语法类型非常丰富,基本涵盖了所有你能想到的类型。

  • length
  • number
  • percentage
  • length-percentage
  • color
  • image
  • url
  • integer
  • angle
  • time
  • resolution
  • transform-list
  • transform-function
  • custom-ident (a custom identifier string)

syntax 中的 +#| 符号

定义的 CSS @property 变量的 syntax 语法接受一些特殊的类型定义。

  • syntax: '' :接受逗号分隔的颜色值列表
  • syntax: '' :接受以空格分隔的长度值列表
  • syntax: '':接受单个长度或者以空格分隔的长度值列表

OK,铺垫了这么多,那么为什么要使用这么麻烦的语法定义 CSS 自定义属性呢?CSS Houdini 定义的自定义变量的优势在哪里?下面我们一一娓娓道来。

使用 color syntax 语法类型作用于渐变

我们来看这样一个例子,我们有这样一个渐变的图案:

复制代码
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: 1s background;&:hover {--colorA: yellowgreen;--colorB: deeppink;}
}
复制代码

看看鼠标 Hover 的时候,会发生什么:

虽然我们设定了 1s 的过渡动画 transition: 1s background,但是很可惜,CSS 是不支持背景渐变色的直接过渡变化的,我们得到的只是两帧之间的之间变化。

使用 CSS @property 进行改造

OK,接下来我们就是有本文的主角,使用 Houdini API 中的 CSS 自定义属性替换原本的 CSS 自定义属性。

简单进行改造一下,使用 color syntax 语法类型:

@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 语法,定义了两个 CSS Houdini 自定义变量 --houdini-colorA--houdini-colorB,在 hover 变化的时候,改变这两个颜色。

需要关注的是,我们设定的过渡语句 transition: 1s --houdini-colorA, 1s --houdini-colorB,在这里,我们是针对 CSS Houdini 自定义变量设定过渡,而不是针对 background 设定过渡动画,再看看这次的效果:

Wow,成功了,渐变色的变化从两帧的逐帧动画变成了补间动画,实现了从一个渐变色过渡到另外一个渐变色的效果!而这,都得益于 CSS Houdini 自定义变量的强大能力!

CodePen Demo -- CSS Houdini 自定义变量实现渐变色过渡动画

使用 CSS @property 实现渐变背景色过渡动画

在上述的 DEMO 中,我们利用了 CSS Houdini 自定义变量,将原本定义在 background 的过渡效果嫁接到了 color 之上,而 CSS 是支持一个颜色变换到另外一个颜色的,这样,我们巧妙的实现了渐变背景色的过渡动画。

在之前我们有讨论过在 CSS 中有多少种方式可以实现渐变背景色过渡动画 -- 巧妙地制作背景色渐变动画!,到今天,我们又多了一种实现的方式!


@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: change 10s infinite linear;
}@keyframes change {20% {--colorA: red;--colorC: #a93ee0;--colorF: fuchsia;}40% {--colorA: #ff3c41;--colorC: #e228a0;--colorF: #2e4c96;}60% {--colorA: orange;--colorC: green;--colorF: teal;}80% {--colorA: #ae63e4;--colorC: #0ebeff;--colorF: #efc371;}
}
复制代码

完整的代码可以戳这里:

CodePen Demo -- CSS Houdini 自定义变量实现渐变色过渡动画2

conic-gradient 配合 CSS @property 实现饼图动画

OK,上面我们演示了 syntaxcolor 语法类型的情况。在文章一开头,我们还列举了非常多的 syntax 类型。

下面我们尝试下其他的类型,使用 percentage 百分比类型或者 angle 角度类型,实现一个饼图的 hover 动画。

如果我们还是使用传统的写法,利用角向渐变实现不同角度的饼图:

复制代码
.normal {width: 200px;height: 200px;border-radius: 50%;background: conic-gradient(yellowgreen, yellowgreen 25%, transparent 25%, transparent 100%); transition: background 300ms;&:hover {background: conic-gradient(yellowgreen, yellowgreen 60%, transparent 60.1%, transparent 100%); }
}
复制代码

将会得到这样一种效果,由于 conic-gradient 也是不支持过渡动画的,得到的是一帧向另外一帧的直接变化:

好,使用 CSS Houdini 自定义变量改造一下:

@property --per {syntax: '';inherits: false;initial-value: 25%;
}div {background: conic-gradient(yellowgreen, yellowgreen var(--per), transparent var(--per), transparent 100%); transition: --per 300ms linear;&:hover {--per: 60%;}
}
复制代码

CodePode Demo -- conic-gradient 配合 CSS @property 实现饼图动画

以往使用纯 CSS 非常复杂才能实现的效果,如果可以轻松的达成,不得不感慨 CSS @property 强大的能力!

syntax 的 | 符号

顺便演示一下定义 Houdini 自定义变量时 syntax 的一些稍微复杂点的用法。

conic-gradient 中,我们可以使用百分比也可以使用角度作为关键字,上述的 DEMO 也可以改造成这样:

@property --per {syntax: ' | ';inherits: false;initial-value: 25%;
}
...
复制代码

表示,我们的自定义属性即可以是一个百分比值,也可以是一个角度值。

除了 | 符号外,还有 +# 号分别表示接受以空格分隔、和以逗号分隔的属性,感兴趣的可以自行尝试。

使用 length 类型作用于一些长度变化

掌握了上述的技巧,我们就可以利用 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;}
}
复制代码

使用 Houdini 自定义变量改造,化腐朽为神奇:

@property --offset {syntax: '';inherits: false;initial-value: 0;
}
div {text-underline-offset: var(--offset, 1px);text-decoration: underline;transition: --offset 400ms, text-decoration-color 400ms;&:hover {--offset: 10px;color: orange;text-decoration-color: orange;}
}
复制代码

可以得到丝滑的过渡效果:

实战一下,使用 CSS @property 配合 background 实现屏保动画

嗯,因为 CSS @property 的存在,让以前需要非常多 CSS 代码的工作,一下子变得简单了起来。

我们尝试利用 CSS @property 配合 background,简单的实现一个屏保动画。

我们利用 background 可以简单的得到这样一个图形,代码如下:

html, body {width: 100%;height: 100%;
}
body {background-image:radial-gradient(circle at 86% 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%),radial-gradient(circle at 15% 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%),radial-gradient(circle at 75% 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;initial-value: 0deg;
}body {background-image: radial-gradient(circle at var(--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%),radial-gradient(circle at var(--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%),radial-gradient(circle at var(--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));animation: move 30s infinite alternate linear;
}@keyframes move {100% {--perA: 85%;--perB: 49%;--perC: 45%;--perD: 39%;--perE: 70%;--angle: 360deg;}
}
复制代码

效果如下(因为 Gif 上传大小限制,加快了速率,截取了其中一部分,简单做个示意):

相关内容

热门资讯

埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...