🤷♂️ 這是一個實驗性技術,正如你所見,它兼容性目前糟糕!可是 Chrome 的發展是在不斷支持它的,接下來了解一下它。 javascript
@ property CSS at-rule 是 CSS Houdini api 的一部分,它容許開發人員顯式定義 CSS 自定義屬性,容許屬性類型檢查,設置默認值,並定義屬性是否能夠繼承值。css
該規則直接在樣式表中表示自定義屬性的註冊,無需運行任何 JS。有效的規則會生成一個已註冊的自定義屬性,就好像使用等效的 parameters.@property@property 調用了 CSS.registerProperty 同樣html
Houdini 是一組底層 api,它公開了 CSS 引擎的部份內容,使開發人員可以經過鉤入瀏覽器渲染引擎的樣式和佈局過程來擴展 CSS。Houdini 是一組 api,可讓開發者直接訪問 CSS 對象模型(CSSOM) ,使開發者可以編寫瀏覽器能夠解析爲 CSS 的代碼,從而建立新的 CSS 特性,而無需等待這些特性在瀏覽器中自行實現。java
@property --propery-name { syntax: '<color>'; inherits: false; initial-value: #c0ffee; }
一個有效的規則表示自定義屬性註冊,屬性名稱是規則的 prelude.@property 中的序列化。api
@property 規則須要語法(syntax)和繼承描述符(inheritsdescriptor); 若是缺乏其中一個,則整個規則無效,必須忽略。只有在語法是通用語法定義的狀況下,初始值描述符纔是可選的,不然就須要描述符; 若是缺乏初始值描述符,則整個規則無效,必須忽略它。瀏覽器
未知的描述符無效並被忽略,可是不要使 rule.@property 無效。app
注意:應該在選擇器塊外面聲明ide
若是您仍然不是很明白,接下來咱們建立一個自定義屬性 --my-color:佈局
@property --my-color { syntax: '<color>'; inherits: false; initial-value: #c0ffee; }
若是使用 Javascript 實現,等價於:flex
window.CSS.registerProperty({ name: '--my-color', syntax: '<color>', inherits: false, initialValue: '#c0ffee', });
若是您常常使用 css 的 transition 屬性,試着回想一下,是否是遇到過這種狀況:在給某個屬性添加 transition 時,卻沒有生效。看下面這段 css 代碼:
.el { background: linear-gradient(white, black); /* this transition won't work */ transition: 1s; } .el:hover { background: linear-gradient(red, black); }
你可能認爲這個漸變中的白色會隨着過渡漸變爲紅色,但事實並不是如此,這種過渡是不可能的。若是咱們過去須要使用一些小技巧實現它,好比用新的漸變顏色在僞元素中褪色,或者用比元素漸變動寬的背景位置來僞造它。
可是如今咱們能夠這樣作了:
@property --gradient-start { syntax: "<color>"; initial-value: white; inherits: false; } .el { --gradient-start: white; background: linear-gradient(var(--gradient-start), black); transition: --gradient-start 1s; } .el:hover { --gradient-start: red; }
由於咱們告訴 CSS 這個自定義屬性是一個 <color>
,因此它能夠被處理或者動畫化。以前的顏色值是沒法被動畫化的。
這裏有個有趣的示例:
實現思路很簡單,使用 CSS3 border-image 屬性設置邊框顏色爲漸變色,而後使用 animation 改變漸變方向。代碼大概這樣子:
<div class="wrapper"> <div class="box"> <p>圓錐形漸變</p> </div> <div class="box"> <p>徑向漸變</p> </div> </div>
:root { --angle: 90deg; --gradX: 100%; --gradY: 50%; --d: 2500ms; --c1: rgba(168, 239, 255, 1); --c2: rgba(66, 106, 116, 0.1); } .box { border-image: conic-gradient(from var(--angle), var(--c2), var(--c1) 0.1turn, var(--c1) 0.15turn, var(--c2) 0.25turn) 30; animation: borderRotate var(--d) linear infinite forwards; } .box:nth-child(2) { border-image: radial-gradient(ellipse at var(--gradX) var(--gradY), var(--c1), var(--c1) 10%, var(--c2) 40%) 30; animation: borderRadial var(--d) linear infinite forwards; } @keyframes borderRotate { 100% { --angle: 420deg; } } @keyframes borderRadial { 20% { --gradX: 100%; --gradY: 50%; } 40% { --gradX: 100%; --gradY: 100%; } 60% { --gradX: 50%; --gradY: 100%; } 80% { --gradX: 0%; --gradY: 50%; } 100% { --gradX: 50%; --gradY: 0%; } }
此時,你會發現 border 上的漸變並不會由於設置了 animation 就動起來,這時候 @property 就排上用場了。
咱們在 css 中先使用 @property 聲明這幾個須要變化的屬性。
@property --angle { syntax: '<angle>'; initial-value: 90deg; inherits: true; } @property --gradX { syntax: '<percentage>'; initial-value: 50%; inherits: true; } @property --gradY { syntax: '<percentage>'; initial-value: 0%; inherits: true; }
此時 border 才真正的「動起來」了。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { box-sizing: border-box; } @property --angle { syntax: '<angle>'; initial-value: 90deg; inherits: true; } @property --gradX { syntax: '<percentage>'; initial-value: 50%; inherits: true; } @property --gradY { syntax: '<percentage>'; initial-value: 0%; inherits: true; } body { font-family: Raleway, sans-serif; text-align: center; margin: 0; padding: 1rem; background-color: rgba(10, 12, 18, 1); color: white; min-height: 100vh; display: flex; flex-wrap: wrap; align-items: center; justify-content: center; } p { margin: 0; } :root { --angle: 90deg; --gradX: 100%; --gradY: 50%; --d: 2500ms; --c1: rgba(168, 239, 255, 1); --c2: rgba(66, 106, 116, 0.1); } .wrapper { min-width: min(40rem, 100%); } .box { font-size: 3vw; margin: max(1rem, 3vw); border: 0.35rem solid; padding: 3vw; border-image: conic-gradient(from var(--angle), var(--c2), var(--c1) 0.1turn, var(--c1) 0.15turn, var(--c2) 0.25turn) 30; animation: borderRotate var(--d) linear infinite forwards; } .box:nth-child(2) { border-image: radial-gradient(ellipse at var(--gradX) var(--gradY), var(--c1), var(--c1) 10%, var(--c2) 40%) 30; animation: borderRadial var(--d) linear infinite forwards; } @keyframes borderRotate { 100% { --angle: 420deg; } } @keyframes borderRadial { 20% { --gradX: 100%; --gradY: 50%; } 40% { --gradX: 100%; --gradY: 100%; } 60% { --gradX: 50%; --gradY: 100%; } 80% { --gradX: 0%; --gradY: 50%; } 100% { --gradX: 50%; --gradY: 0%; } } </style> </head> <body> <div class="wrapper"> <div class="box"> <p>圓錐形漸變</p> </div> <div class="box"> <p>徑向漸變</p> </div> </div> </body> </html>