自订属性值 ( @property )
CSS 的 @property 可以让用户“自订属性值”的 At 规则,使用方式跟“CSS 变数”非常类似,可以当作是一种“新型态的 CSS 变数”,定义属性值之后,就能在任何地方使用这个属性值,这篇教学会介绍 CSS 的 @property 自订属性,最后还会利用 @property 制作渐层色动画。
快速导览:
教学影片
搭配教学影片一起阅读,效果会更好!欢迎大家订阅 STEAM 教育学习网的 Youtube 频道。
认识 @property
@property 是一个新的 CSS 语法,可以透过类型、默认值与继承行为,定义并建立一个自订属性 ( 类似新型态的 CSS 变数 ),由于浏览器能够解析这种自订属性的类型,因此广泛应用于进阶的动画效果,透过 @property 让浏览器正确计算出动画过渡的过程,产生平滑的补间动画 ( 单纯 CSS 变数会将属性值全部当作字串处理 )。
下方列出 @property 和 CSS 变数的简单差异:
| 项目 | 自订属性 @property |
CSS 变数 |
|---|---|---|
| 语法 | @property --name { ... } |
--name: value; |
| 用途 | 自订可重复使用的属性类型与行为 | 定义可重复使用的变数值 |
| 型别支援 | 支援 | 不支援 ( 全部当作字串处理 ) |
| 继承性 | 默认会继承 | 默认会继承 |
| 初始值设定 | 透过 initial-value 赋值 |
在变数中直接赋值 |
| 支援补间动画 | 支援 | 不支援 |
| 安全性与型别验证 | 有型别验证与安全性检查 | 没有型别或错误检查 |
| 浏览器支援 | 较新,仅部分支援 | 广泛支援 |
@property 自订属性值
CSS 自订属性值需要使用 @property 规则进行定义,包含定义名称、句法、继承和属性值,撰写语法如下:
@property --property-name {
syntax: "<color>";
inherits: false;
initial-value: #c0ffee;
}
语法中包含了下列几个属性:
--property-name属性名称
- 使用“两个破折号
--”开头,后方连接“名称”。- 使用“英文字母大小写、数字、破折号和底线符号”,且开头需为英文。
- 名称区分大小写,例如
--apple和--Apple会被视为两个不同的属性。
syntax句法:该属性的型别,只能接受什么数值 ( 详细参考 MDN syntax ):
句法名称 说明 - 句法名称 说明 <angle>角度 - <url>网址 <color>颜色 - <custom-ident>自订标志 <image>图片 - <integer>整数 <length>长度 - <length-percentage>长度百分比 <number>数字 - <percentage>百分比 <resolution>分辨率 - <string>字串 <time>时间 - <transform-function>转换函数 <transform-list>转换清单 - - -
inherits继承:数值为 true 或 false ( 小写 ),如果子元素也有使用同样的自订属性,则会取代子元素的自订属性。
initial-value默认值。
下方的范例将会订一个名为 --oxxo 的属性值,这个属性值是颜色性质,有继承特性,默认值为红色。
@property --oxxo {
syntax: "<color>";
inherits: true;
initial-value: red;
}
使用自订属性值
自订属性之后,只在需要在特定的样式属性里里,使用“var()”函数读取自订的属性值,就会自动将自订属性值带入到样式属性中,作法和变数几乎一模一样。下方范例使用两组自订属性,分别是 --apple 和 --banana,由于 --banana 设定为不会继承,当父元素的自订属性变更属性值时,子元素仍然会保持原本的属性值。
<!-- HTML 程式碼 -->
<h3 class="a">hello <span>apple ( 子元素維持父元素顏色 )<span></h3>
<h3 class="b">hello <span>banana ( 子元素一直保持藍色 )<span></h3>
<!-- CSS 程式碼 -->
<style>
/* 自訂屬性值 --apple */
@property --apple {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
/* 自訂屬性值 --banana */
@property --banana {
syntax: "<color>";
inherits: false;
initial-value: blue;
}
.a {color: var(--apple);} /* 父元素使用自訂屬性值 */
.b {color: var(--banana);} /* 父元素使用自訂屬性值 */
.a span {color: var(--apple);} /* 子元素使用自訂屬性值 */
.b span {color: var(--banana);} /* 子元素使用自訂屬性值 */
h3 {
--apple: red; /* 修改父元素屬性值 */
--banana: red; /* 修改父元素屬性值 */
}
h3:hover {
--apple: green; /* 修改父元素屬性值 */
--banana: green; /* 修改父元素屬性值 */
}
</style>
全域、区域自订属性值
“全域自订属性值”表示“所有元素都能使用的自订属性值”,如果要宣告全域自订属性值,通常会将自订属性值写在 :root 里,或写在 html 或 body 元素里,而“区域自订属性值”表示“某个元素里才能使用的自订属性值”,由于定义在指定元素内,不属于这个元素的子元素 ( 兄弟元素或父元素 ) 就无法使用。
下方范例会使用 :root 使用全域自订属性,在 h2 和 h3 里使用区域自订属性。
<!-- HTML 程式碼 -->
<h2 class="a">hello <span>apple ( 子元素藍色 )<span></h2>
<h3 class="b">hello <span>banana ( 子元素綠色 )<span></h3>
<!-- CSS 程式碼 -->
<style>
@property --apple {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
@property --banana {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
/* 全域、區域自訂屬性值 */
:root {--apple: red;}
h2 {--banana: blue;}
h3 {--banana: green;}
.a {color: var(--apple);}
.b {color: var(--apple);}
.a span {color: var(--banana);}
.b span {color: var(--banana);}
</style>
HTML 行内 CSS 自订属性值
CSS 的自订属性值除了写在 CSS 的文件里,也可以写在 HTML 标签行内,写在行内的属性值因为最靠近要套用的元素,所以基本上一定会覆盖之前的自订属性值 ( 权重最大 ),下方的范例执行后,就会按照行内定义的自订属性值,将文字变成绿色。
<!-- HTML 程式碼 -->
<h3 class="a">hello
<span style="--banana: blue;">apple ( 子元素藍色 )<span>
</h3>
<h3 class="b">hello
<span>banana ( 子元素綠色 )<span>
</h3>
<!-- CSS 程式碼 -->
<style>
@property --apple {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
@property --banana {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
/* 雖然使用了自訂屬性值,但因為行內自訂屬性值最接近套用的元素,所以會以行內為主 */
h3, h3 span {
--apple: red;
--banana: green;
}
.a {color: var(--apple);}
.b {color: var(--apple);}
.a span {color: var(--banana);}
.b span {color: var(--banana);}
</style>
搭配 CSS media Queries
CSS 的自订属性值也可以搭配 media Queries,在不同 media 显示尺寸之下,一次性的设定各种属性值,避免不断重复输入,下方的范例执行后,当网页宽度小于 400px,会呈现父元素红色子元素绿色的样貌,当宽度大于 400px 就会全部变成蓝色。
<!-- HTML 程式碼 -->
<h3 class="a">hello <span>apple ( 瀏覽寬度大於 400 全藍 )<span></h3>
<h3 class="b">hello <span>banana ( 瀏覽寬度大於 400 全藍 )<span></h3>
<!-- CSS 程式碼 -->
<style>
@property --apple {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
@property --banana {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
@media (max-width:400px){
:root{
--apple: red;
--banana: green;
}
}
.a {color: var(--apple);}
.b {color: var(--apple);}
.a span {color: var(--banana);}
.b span {color: var(--banana);}
</style>
使用 JavaScript 操控
如果运用 JavaScript 将写入元素行内属性的方法,就能利用行内的 CSS 自订属性值控制样式,写入方法有下面几种:
window.CSS.registerProperty:替整个网页注册某个属性。元素.style.getPropertyValue:读取某个属性。元素.style.setProperty:设定某个属性。元素.style.cssText:覆写整个 style 属性。元素.setAttribute:覆写整个 style 属性。
举例来说,假设已经在 :root 设定变数数值,仍然可以使用 JavaScript 在元素里添加行内变数,下方的范例执行后,会透过 JavaScript 注册一个名为 --oxxo 的自订属性值,这时就能在 CSS 中读取并使用这个属性值,接着透过 JavaScript 设定特定元素的属性值,就能产生不同颜色的效果。
<!-- HTML 程式碼 -->
<h3 class="a">hello <span>apple<span></h3>
<h3 class="b">hello <span>banana<span></h3>
<!-- CSS 程式碼 -->
<style>
@property --apple {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
@property --banana {
syntax: "<color>";
inherits: true;
initial-value: blue;
}
:root{
--apple: red;
--banana: green;
}
h3 {
background: var(--oxxo);
}
.a {color: var(--apple);}
.b {color: var(--apple);}
.a span {color: var(--banana);}
.b span {color: var(--banana);}
</style>
<!-- JS 程式碼 -->
<script>
window.CSS.registerProperty({
name: "--oxxo",
syntax: "<color>",
inherits: false,
initialValue: "#ccc",
});
const apple = document.querySelector('.a');
apple.style.setProperty('--apple','#900');
apple.style.setProperty('--banana','yellow');
const banana = document.querySelector('.b');
banana.style.setProperty('--apple','black');
banana.style.setProperty('--banana','white');
</script>
使用 @property 制作渐层色动画
渐层色本身无法使用动画效果,但透过 @property 的辅助,也可以实现渐层色动画效果,下方范例会建立三个自订属性值 --c1、--c2 和 --p,透过这三个属性值建立渐层色背景,当鼠标移动到元素上方时改变属性值,就能实现渐层色动画效果。
- 注意,使用
transition需要额外针对自订属性撰写对应的属性值。- 参考:CSS 渐层色、转场 transition
<!-- HTML 程式碼 -->
<h1>oxxo</h1>
<!-- CSS 程式碼 -->
<style>
/* 顏色自訂屬性 */
@property --c1 {
syntax: "<color>";
inherits: true;
initial-value: red;
}
/* 顏色自訂屬性 */
@property --c2 {
syntax: "<color>";
inherits: true;
initial-value: yellow;
}
/* 長度百分比自訂屬性 */
@property --p {
syntax: "<length-percentage>";
inherits: true;
initial-value: 0%;
}
h1 {
width: 200px;
height: 200px;
border: 1px solid #000;
color: red;
text-align: center;
font-size: 50px;
line-height: 200px;
transition: all .5s,
--c1 .5s,
--c2 .5s,
--p .5s; /* 轉場效果需要額外針對屬性撰寫 */
background: linear-gradient(var(--c1) 0%,
var(--c1) var(--p),
var(--c2) var(--p),
var(--c2) 100%);
}
h1:hover{
color: blue;
--c1: cyan; /* 改變屬性值 */
--c2: green; /* 改變屬性值 */
--p: 100%; /* 改變屬性值 */
}
</style>
小结
CSS 自订属性值和 CSS 变数在用法上大同小异,都可以让 CSS 的文件更为弹性好管理,如果自己网页中有许多重复的属性值,不妨可透过 CSS 自订属性值改善程序码架构,如此也更能提高网页执行的效率。
微信扫码关注
抖音扫码关注