您的位置:  首页 > 技术 > 前端 > 正文

一起了解一下css新特性@property

2021-09-14 15:00 https://my.oschina.net/u/5367319/blog/5261045 老刀唠叨 次阅读 条评论

一、概念

@property是一个新增的CSS @规则(CSS at-rule),它是CSS Houdini API的一部分, 它允许开发者显式地定义css自定义属性,并允许进行属性类型检查、设定默认值以及定义该自定义属性是否可以被继承。@property可以直接在样式表中注册自定义属性,无需运行任何JS代码;同时也配备相应的JS语法注册自定义属性。@property自定义属性,是CSS变量(CSS variables)声明变量的升级版本,比CSS变量更加规范和严谨。

下面我们一起详细了解一下@property。在此之前,简单了解一下CSS Houdini。了解了CSS Houdini,有助于我们理解和掌握css发展方向和设计思路。

二、关于CSS Houdini

CSS Houdini是一组底层API,它们公开了CSS引擎的各个部分,从而使开发人员能够通过加入浏览器渲染引擎的样式和布局过程来扩展CSS; 使开发人员可以直接访问CSS 对象模型 (CSSOM),使开发人员可以编写浏览器可以解析为CSS的代码,从而创建新的CSS功能,而无需等待它们在浏览器中本地实现。

CSS Houdini API主要包括以下几部分:

  • CSS Parser API:更直接地暴露出 CSS 解析器的 API,能够把任意 CSS 类语言解析成为一种中间类型

  • CSS Properties and Values API:定义了一个用来注册新的 CSS 属性的 API。通过该 API 注册的属性可以以定义其类型、继承行为以及初始值

  • CSS Typed OM(CSSOM):该 API 将 CSSOM 字符串转化为有类型意义的 JavaScript。CSSOM 值以类型化处理的 JavaScript 对象的形式暴露出来,以使其表现可以被控制

  • CSS Layout API:作为一个被设计来提升 CSS 扩展性的 API,该 API 能够让开发者去书写他们自己的布局算法,比如 masonry 或者 line snapping

  • CSS Painting API:作为一个被设计来提升 CSS 扩展性的 API,该 API 允许开发者通过 paint() 方法书写 JavaScript 函数,以控制绘制元素的背景、边框或者内容区域

  • Worklets: 该 API 允许脚本独立于 JavaScript 执行环境,运行在渲染流程的各个阶段。Worklets 在概念上很接近于 Web Workers ,它由渲染引擎调用,并扩展了渲染引擎

  • CSS Animation API:该API让我们能够基于用户输入驱动关键动画效果

CSS Houdini API的发展和完善,将大幅度提高,css的访问速度、可编程性、可扩展性、以及可控性。有关CSS Houdini只介绍这么多,主要目的是明确@property是CSS Properties and Values API的重要组成部分。

三、@property 语法

1. 标准语法

标准语法由下面三部分组成

  • @property关键字
  • 自定义属性名称(custom-property-name),需--前缀。例如, --primary-color
  • 声明字段(declaration-list)
@property <custom-property-name> {

  <declaration-list>

}

2. 声明字段

声明字段包括syntax、inherits 和 initial-value

  • syntax:类型string。定义自定义属性的类型。例如,number,color,percentage等
  • inherits:类型boolean。定义自定义属性是否允许继承
  • initial-value:类型符合syntax定义的类型,定义初始值
  • syntaxinherits 描述符是必需的,其中任何一项缺失, 整条规则都将失效并且会被忽略
  • initial-value 描述符仅在syntax描述符为通用syntax定义时是可选的,否则也是必需的

完整声明示例 以往,CSS变量(CSS variables)声明变量示例

:root {

  --primary-color:green;

}



.box {

    background-color: var(--primary-color);

}

现在,使用@property声明变量示例

@property --primary-color {

  syntax: '<color>';

  inherits: false;

  initial-value: green;

}



:root{

    --primary-color: blue;

}



.box {

    background-color: var(--primary-color);

}

3. syntax可用有效字段

注册自定义属性时,可以使用CSS值和单位规范中的许多受支持的语法

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

4. 声明复合属性值

syntax支持复合属性值,例如,font-family: Arial, Verdana, Geneva, sans-serif 和 border:1px solid #ccc,属性值是逗号或者空格分隔的值列表。针对这种场景,syntax提供了语法声明符号+、#、|

  • 符号(+),用于声明接受以空格分隔的值列表 例如:"<length>+"
@property --padding{

    syntax: '<lenth>+';

    inherits: false;

}



.box{

    --padding:0 10px;

    padding: var(--padding);

}

  • 符号(#),用于声明接受以逗号分隔的值列表 例如:"<url>#"
@property --img-url{

    syntax: '<url>#';

    inherits: false;

}



.box{

    --img-url:url(img01.png),url(img02.png);

    background-image: var(--img-url);

}

  • 符号(|),用于声明不同类型的值 例如:"<length> | <length>+ | auto"
@property --padding{

    syntax: '<length> | <lenth>+ | auto';

    inherits: false;

}



.box{

    --padding:10px auto;

    padding: var(--padding);

}

5. @property的JS语法

CSS.registerProperty方法用于注册css自定义属性。registerProperty用法跟@property大致相同,同样包括name、syntax、inherits和initialValue,只是把注册自定义属性,转移到JS上下文中执行。

JS中注册自定义属性

window.CSS.registerProperty({

    name: '--primary-color',

    syntax: '<color>',

    inherits: false,

    initialValue: 'green',

})

CSS中使用自定义属性

.box{

    background-color:var(--primary-color);

    color:white;

}

四、@property应用与实践

1. @property声明自定义属性,更加规范:

  • 可以添加值类型检测,不合法的属性值会被忽略。 有别于CSS变量,@property声明的自定义属性,类型检测不合法的值会被忽略,不影响继续使用继承自外部容器的值;而CSS变量中不合法的属性值,会覆盖继承自外部容器的值,导致自定义变量失效。
@property --bg-color{

   syntax: '<color>+';

   inherits: false;

   initial-value: green;

}



.box{

    --bg-color:20px;

    background-color:var(--bg-color);

}

box最终呈现的背景是green,20px不属于<color>有效值,被忽略; 对比看一下CSS变量,20px不属于有效值,但覆盖了green,导致背景设置失败

:root{--bg1-color:green;}



.box1{

    --bg1-color:20px;

    background-color:var(--bg1-color);

}

查看对比示例

  • 可以设置是否允许属性值继承外部容器的值
@property --custom-color{

    syntax: '<color>+';

    inherits: false;

    initial-value: green;

}



@property --font-color{

    syntax: '<color>+';

    inherits: true;

    initial-value: white;

}



:root{

    --font-color:yellow;

    --custom-color:blue;

}



.box{

    color:var(--font-color);

    background-color:var(--custom-color);

}

box最终呈现的背景是green,字体是yellow。因为我们禁止--custom-color继承外部容器的值;允许--font-color继承外部容器的值。查看效果

2.@property属性支持transition动画

@property声明的自定义属性支持transition动画。不要小看这个小小的转变,就仿佛给我们开了一扇通向css动画世界的大门。只要你的想象力足够强大,就可以创造出很多令人惊奇的css动画。

以往,用CSS变量定义背景渐变,背景无渐变动画效果

:root{

    --start-color1:red;

    --end-color1:black;

}



.child{

    background-image:linear-gradient(

    to bottom,

    var(--start-color1),

    var(--end-color1)

  );

}



.child:hover{

    --start-color1:green;

}

查看示例 -- child:nth-child(1)

现在,用@property定义背景渐变,背景有动画渐变效果

@property --start-color{

    syntax:'<color>';

    inherits:false;

    initial-value:orange;

}



@property --end-color{

    syntax:'<color>';

    inherits:false;

    initial-value:black;

}



.child{

  background-image:linear-gradient(

    to bottom,

    var(--start-color),

    var(--end-color)

 );

}



.child:hover{

    --start-color: blue;

}

查看示例 -- child:nth-child(2)

进而,可以把渐变动画拓展到【color的渐变位置】

@property --color-pos{

    syntax:'<length>|<length-percentage>|<percentage>';

    inherits:false;

    initial-value:90%;

}



.child{

  background-image:linear-gradient(

    to bottom,

    #f05b72 0,

    black var(--color-pos),

    #f05b72 100%

  );

}



.child:hover{

  --color-pos:10%;

}

查看示例 -- child:nth-child(3)

再进一步,还可以把动画拓展到颜色通道,比如hsl

@keyframes huechange {

  to {--color-hue:360}

}

.child{

  background-color:hsl(var(--color-hue), 80%, 50%);

}

.child:hover{

  animation:huechange 2s infinite linear;

}

查看示例 -- child:nth-child(4)

脑洞大开一下,可以变成一道彩虹

@keyframes huechange {

  to {--color-hue:360}

}

.child{

  display:flex;

}

.child .rainbow{

  flex:1;

  background-color: hsl(var(--color-hue), 80%, 50%);

  animation:huechange 2s calc(var(--index, 0) * -0.2s) infinite linear;

}

查看示例 – child:nth-child(5)

五、参考

https://developer.mozilla.org/zh-CN/docs/Web/CSS/@property

https://developer.mozilla.org/en-US/docs/Web/API/CSS/RegisterProperty

https://developer.mozilla.org/zh-CN/docs/Web/Guide/Houdini

https://segmentfault.com/a/1190000039826626?utm_source=sf-similar-article

https://css-tricks.com/exploring-property-and-its-animating-powers/

https://www.w3cplus.com/css/css-at-property.html

https://houdini.glitch.me/custom-properties

  • 0
    感动
  • 0
    路过
  • 0
    高兴
  • 0
    难过
  • 0
    搞笑
  • 0
    无聊
  • 0
    愤怒
  • 0
    同情
热度排行
友情链接