@property

Baseline 2024
新推出

自 ⁨2024 年 7 月⁩起,此功能可在最新的裝置和瀏覽器版本上使用。此功能可能無法在較舊的裝置或瀏覽器上使用。

@property CSS @ 規則CSS Houdini API 的一部分。它允許開發者顯式地定義 CSS 自定義屬性,從而可以進行屬性型別檢查、設定預設值,以及定義自定義屬性是否可以繼承值。

@property 規則表示直接在樣式表中註冊一個自定義屬性,而無需執行任何 JavaScript。有效的 @property 規則會產生一個已註冊的自定義屬性,這類似於使用等效引數呼叫 registerProperty()

語法

css
@property --rotation {
  syntax: "<angle>";
  inherits: false;
  initial-value: 45deg;
}

自定義屬性名是一個 <dashed-ident>,以 -- 開頭,後跟一個有效的、使用者定義的識別符號。它區分大小寫。

描述符

syntax

一個描述已註冊自定義屬性允許的值型別的字串。可以是一個數據型別名稱(如 <color><length><number> 等),可以帶有乘數(+#)和組合符(|),或者是一個自定義識別符號。更多詳情請參閱 syntax 描述符頁面。

inherits

一個布林值,控制由 @property 指定的自定義屬性註冊是否預設繼承。

initial-value

一個為屬性設定初始值的值。

描述

@property 規則必須滿足以下條件才有效

  • @property 規則必須同時包含 syntaxinherits 描述符。如果缺少任何一個,整個 @property 規則都將無效並被忽略。
  • 如果 syntax 描述符的值是通用語法定義(即 syntax: "*"),則 initial-value 描述符是可選的。如果 initial-value 描述符是必需的但被省略了,則整個 @property 規則都將無效並被忽略。
  • 如果 syntax 描述符的值不是通用語法定義,那麼 initial-value 描述符必須是一個計算無關的值。這意味著該值可以被轉換為計算值而無需依賴其他值,除了那些獨立於 CSS 的“全域性”定義。例如,10px 是計算無關的——它在轉換為計算值時不會改變。2in 也是有效的,因為 1in 總是等於 96px。然而,3em 是無效的,因為 em 的值依賴於父元素的 font-size
  • 未知的描述符是無效的並且會被忽略,但不會使 @property 規則失效。

正式語法

@property = 
@property <custom-property-name> { <declaration-list> }

示例

使用 @property 註冊和使用自定義屬性

在這個例子中,我們定義了兩個自定義屬性,--item-size--item-color,我們將用它們來定義下面三個專案的尺寸(寬度和高度)和背景顏色。

html
<div class="container">
  <div class="item one">Item one</div>
  <div class="item two">Item two</div>
  <div class="item three">Item three</div>
</div>

以下程式碼使用 CSS @property @ 規則定義一個名為 --item-size 的自定義屬性。該屬性設定初始值為 40%,並將有效值限制為僅 <percentage> 型別的值。這意味著,當用作專案尺寸的值時,其尺寸將始終相對於其父元素的尺寸。該屬性是可繼承的。

css
@property --item-size {
  syntax: "<percentage>";
  inherits: true;
  initial-value: 40%;
}

我們使用 JavaScript 而不是 CSS 來定義第二個自定義屬性 --item-color。JavaScript 的 registerProperty() 方法等同於 @property @ 規則。該屬性被定義為初始值為 aqua,只接受 <color> 型別的值,並且不可繼承。

js
window.CSS.registerProperty({
  name: "--item-color",
  syntax: "<color>",
  inherits: false,
  initialValue: "aqua",
});

我們使用這兩個自定義屬性來設定專案的樣式

css
.container {
  display: flex;
  height: 200px;
  border: 1px dashed black;

  /* set custom property values on parent */
  --item-size: 20%;
  --item-color: orange;
}

/* use custom properties to set item size and background color */
.item {
  width: var(--item-size);
  height: var(--item-size);
  background-color: var(--item-color);
}

/* set custom property values on element itself */
.two {
  --item-size: initial;
  --item-color: inherit;
}

.three {
  /* invalid values */
  --item-size: 1000px;
  --item-color: xyz;
}

兩個自定義屬性 --item-size: 20%--item-color: orange; 設定在父元素 container 上,覆蓋了這些自定義屬性定義時設定的 40%aqua 預設值。尺寸被設定為可繼承;顏色則不是。

對於第一個專案,沒有設定這些自定義屬性。--item-size 是可繼承的,所以使用了其父元素 container 上設定的 20% 值。另一方面,--item-color 屬性是不可繼承的,所以父元素上設定的 orange 值不會被考慮。而是使用了預設的初始值 aqua

對於第二個專案,為兩個自定義屬性都設定了 CSS 全域性關鍵字,這些關鍵字對所有值型別都有效,因此無論 syntax 描述符的值是什麼都是有效的。--item-size 被設定為 initial,並使用在 @property 宣告中設定的 initial-value: 40%;initial 值意味著使用該屬性的 initialValue 值。--item-color 被設定為 inherit,明確地從其父元素繼承了 orange 值,儘管該自定義屬性被設定為不可繼承。這就是為什麼第二個專案是橙色的。

對於第三個專案,--item-size 的值被設定為 1000px。雖然 1000px 是一個 <length> 值,但 @property 宣告要求該值是 <percentage>,因此該宣告無效並被忽略,這意味著使用了父元素上設定的可繼承的 20% 值。xyz 值也是無效的。由於 registerProperty()--item-color 設定為不可繼承,因此使用的是預設的初始值 aqua,而不是父元素的 orange 值。

為自定義屬性值新增動畫

在這個例子中,我們使用 @property 定義了一個名為 --progress 的自定義屬性:它接受 <percentage> 值,並且初始值為 25%。我們使用 --progress 來定義 linear-gradient() 中顏色斷點的位置值,指定綠色停止和黑色開始的位置。然後,我們在 2.5 秒內將 --progress 的值動畫化到 100%,從而產生進度條動畫的效果。

html
<div class="bar"></div>
css
@property --progress {
  syntax: "<percentage>";
  inherits: false;
  initial-value: 25%;
}

.bar {
  display: inline-block;
  --progress: 25%;
  width: 100%;
  height: 5px;
  background: linear-gradient(
    to right,
    #00d230 var(--progress),
    black var(--progress)
  );
  animation: progressAnimation 2.5s ease infinite;
}

@keyframes progressAnimation {
  to {
    --progress: 100%;
  }
}

規範

規範
CSS 屬性和值 API Level 1
# at-property-rule

瀏覽器相容性

另見