@function

可用性有限

此特性不是基線特性,因為它在一些最廣泛使用的瀏覽器中不起作用。

實驗性: 這是一項實驗性技術
在生產中使用此技術之前,請仔細檢查瀏覽器相容性表格

@function CSS @ 規則用於定義 CSS 自定義函式。一旦定義,自定義函式就可以在任何屬性值中使用 <dashed-function> 語法(例如,--my-function(30px, 3))來呼叫。

語法

css
@function --function-name(<function-parameter>#?) [returns <css-type>]? {
  <declaration-rule-list>
}

<function-parameter> = --param-name <css-type>? [ : <default-value> ]?

@function 語法的不同部分如下:

--function-name

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

<function-parameter>#? 可選

零個或多個函式引數定義。多個引數定義之間用逗號分隔。每個引數包含:

--param-name

用於標識引數的 CSS 自定義屬性名稱,是一個以 -- 開頭,後跟一個有效的、使用者定義的識別符號的 <dashed-ident>。它區分大小寫。函式引數可以被認為是作用域限於函式體的區域性自定義屬性。

<css-type> 可選

一個 CSS 資料型別或一個 type() 函式,用於定義引數可接受的資料型別。如果未指定,任何資料型別都對該引數有效(與指定 type(*) 相同)。

<default-value> 可選

一個 CSS 值,指定當呼叫函式時如果未指定引數,則分配給該引數的預設值。如果指定了 <css-type>,此值必須對其有效。預設值與引數定義的其他部分用冒號(:)分隔。

[returns <css-type>]? 可選

一個 CSS 資料型別或一個 type() 函式,前面有關鍵字 returns,用於定義引數可接受的返回型別。如果未指定,任何資料型別都對該引數有效(與指定 returns type(*) 相同),但請注意,如果返回型別與 result 描述符產生的型別不匹配,函式將無效。

<declaration-rule-list>

一個或多個 CSS 宣告或 @ 規則,用於定義函式的主體,其中包含其邏輯。包含的宣告可以包括:

  • CSS 自定義屬性,其作用域限於函式體。
  • result 描述符,可以直接在 @function @ 規則內,或在巢狀的 @ 規則內。

描述符

result

一個有效的屬性值,定義了 CSS 自定義函式返回的結果。值中包含的表示式會被求值,然後返回結果。

描述

CSS 自定義函式允許你定義可重用的邏輯片段,這些邏輯片段將根據它們接受的輸入引數以及函式體內定義的邏輯返回不同的值。

一個典型的 CSS 函式如下所示:

css
@function --transparent(--color, --alpha) {
  result: oklch(from var(--color) l c h / var(--alpha));
}

該函式的名稱為 --transparent,並接受兩個自定義屬性作為引數,--color--alpha,它們可以在函式體內區域性使用。函式體包含一行,即一個 result 描述符,它定義了函式返回的值。result 描述符的值使用 CSS 相對顏色語法將輸入的 --color 值轉換為一個 oklch() 顏色,其 alpha 通道值由輸入的 --alpha 值指定。

然後你可以在任何需要生成現有顏色半透明版本的地方呼叫此函式,例如:

css
section {
  --base-color: #faa6ff;
  background-color: --transparent(var(--base-color), 0.8);
}

該函式透過使用 <dashed-function> 語法來呼叫,即函式名後跟括號。所需的引數值在括號內指定。

備註: 如果多個 CSS 函式被賦予相同的名稱,則在更強的級聯層(@layer中的函式獲勝。如果它們都在同一層中,則原始碼順序中最後定義的函式獲勝。

指定資料型別

可以為函式引數和返回型別指定資料型別。例如:

css
@function --transparent(--color <color>, --alpha <number>) returns <color> {
  result: oklch(from var(--color) l c h / var(--alpha));
}

現在,只有當輸入引數分別為 <color><number>,並且 result 是一個 <color> 時,該函式才會產生有效值。否則,例如:

css
section {
  --base-color: #faa6ff;
  background-color: --transparent(var(--base-color), 50%);
}

那麼該值將在計算值時變得無效(因為指定的 --alpha 引數是一個 <percentage> 而不是預期的 <number>),並且 background-color 最終將被設定為 transparent

你可以使用 type() 函式並以 | 符號作為分隔符來指定多個可接受的資料型別,例如:

css
@function --transparent(--color <color>, --alpha type(<number> | <percentage>))
  returns <color> {
  result: oklch(from var(--color) l c h / var(--alpha));
}

經過此調整後,--transparent(var(--base-color), 50%) 函式呼叫現在是有效的。

指定預設值

你還可以在引數定義的末尾,用冒號指定引數的預設值。例如:

css
@function --transparent(--color <color>, --alpha <number>: 0.8) returns <color> {
  result: oklch(from var(--color) l c h / var(--alpha));
}

--alpha 引數的預設值現在是 0.8。如果你想使用這個值,可以在呼叫函式時省略第二個引數:

css
section {
  --base-color: #faa6ff;
  background-color: --transparent(var(--base-color));
}

備註: 如果一個無效的值作為函式引數傳入,並且該引數定義中指定了預設值,那麼無效值將被忽略,而使用預設值。

將包含逗號的值作為引數傳遞

在下一個示例中,--max-plus-x() 函式期望傳入一個以逗號分隔的長度列表和一個單一長度作為引數。它使用 CSS max() 函式來確定長度列表中的最大值,然後將其與單一長度相加,並返回結果。

css
@function --max-plus-x(--list <length>#, --x <length>) {
  result: calc(max(var(--list)) + var(--x));
}

第一個引數需要是一個逗號分隔的列表,這可能被誤解為三個獨立的引數。要解決這個問題,你可以在將值傳入函式呼叫時用花括號將其包裹起來:

css
div {
  width: --max-plus-x({1px, 7px, 2px}, 3px); /* 10px */
}

在函式中包含自定義屬性

正如我們已經看到的,函式引數被定義為自定義屬性,然後在函式體內可用。

你還可以在函式體內指定自定義屬性,它們將作為區域性作用域的常量。在下面的示例中,我們定義了一個名為 --anim-1s() 的函式,它返回一個 animation 簡寫值,其中持續時間和緩動值始終相同,只有動畫名稱和次數是可變的。

css
@function --anim-1s(--animation, --count) {
  --duration: 1s;
  --easing: linear;
  result: var(--animation) var(--duration) var(--count) var(--easing);
}

這種用法允許你為動畫編寫更簡單、更具表現力的語法,前提是你知道你總是希望持續時間和緩動函式是相同的:

css
animation: --anim-1s(bounce, 2);

還值得注意的是,你可以在一個自定義函式內部呼叫另一個自定義函式。在這種情況下,一個自定義函式可以訪問呼叫棧中更上層函式的區域性變數和函式引數。在這裡,外部函式的引數和區域性自定義屬性在內部函式的作用域內將是可用的:

css
@function --outer(--outer-arg) {
  --outer-local: 2;
  result: --inner();
}

@function --inner() returns <number> {
  result: calc(var(--outer-arg) + var(--outer-local));
}

div {
  z-index: --outer(1); /* 3 */
}

此外,在呼叫自定義函式的同一元素上定義的自定義屬性對該函式也是可用的:

css
@function --double-z() returns <number> {
  result: calc(var(--z) * 2);
}

div {
  --z: 3;
  z-index: --double-z(); /* 6 */
}

當一個同名的自定義屬性在多個地方定義時,函式引數會覆蓋在同一元素上定義的自定義屬性,而在函式體內定義的區域性自定義屬性會覆蓋兩者。在下面的示例中,--add-a-b-c() 函式使用了來自 div 規則的自定義屬性 --a、來自函式引數的屬性 --b,以及區域性自定義屬性 --c

css
@function --add-a-b-c(--b, --c) {
  --c: 300;
  result: calc(var(--a) + var(--b) + var(--c));
}

div {
  --a: 1;
  --b: 2;
  --c: 3;
  z-index: --add-a-b-c(20, 30); /* 321 */
}

包含複雜邏輯

你可以使用 @media @ 規則和 if() 函式等結構在函式中包含更復雜的邏輯。例如,下一個函式接受兩個引數,一個用於窄屏佈局,一個用於寬屏佈局。它預設返回後者,但當視口寬度小於 700px 時(透過媒體查詢檢測),它返回前者。

css
@function --narrow-wide(--narrow, --wide) {
  result: var(--wide);
  @media (width < 700px) {
    result: var(--narrow);
  }
}

你可以包含多個 result 描述符來表達不同邏輯結果的不同返回值。

備註: CSS 函式在衝突解決方面的行為與 CSS 的其餘部分相同——原始碼順序中最後的獲勝。因此,在上面的函式中,resultvar(--wide),除非媒體查詢測試返回 true,在這種情況下它被 var(--narrow) 覆蓋。

CSS 函式中沒有像 JavaScript 函式那樣的提前返回。在上面的函式中,如果媒體查詢寫在前面,在單個 result 行之前,那麼 result 將始終是 var(--wide),因為它會在媒體查詢測試返回 true 的情況下覆蓋 var(--narrow)

我們可以重寫這個 CSS 自定義函式來改用 if() 函式:

css
@function --narrow-wide(--narrow, --wide) {
  result: if(media(width < 700px): var(--narrow) ; else: var(--wide));
}

正式語法

@function = 
@function <function-token> <function-parameter>#? ) [ returns <css-type> ]? { <declaration-rule-list> }

<function-parameter> =
<custom-property-name> <css-type>? [ : <default-value> ]?

<css-type> =
<syntax-component> |
<type()>

<default-value> =
<declaration-value>

<syntax-component> =
<syntax-single-component> <syntax-multiplier>? |
'<' transform-list '>'

<type()> =
type( <string> )

<syntax-single-component> =
'<' <syntax-type-name> '>' |
<ident>

<syntax-multiplier> =
'#' |
'+'

<syntax-type-name> =
angle |
color |
custom-ident |
image |
integer |
length |
length-percentage |
number |
percentage |
resolution |
string |
time |
url |
transform-function

示例

更多示例,請參閱我們的使用 CSS 自定義函式指南。

@function 基本用法

此示例展示了一個將傳入值加倍的基本函式。

HTML

標記包含一個帶有某些文字內容的 <p> 元素:

html
<p>Some content</p>

CSS

在我們的樣式中,我們首先定義 CSS 自定義函式。該函式名為 --double,並接受一個任何型別的單個引數,我們稱之為 --value。在函式體內,我們包含一個 result 描述符,它使用 calc() 函式將傳入的引數加倍:

css
@function --double(--value) {
  result: calc(var(--value) * 2);
}

接下來,我們定義一個值為 10px--base-spacing 自定義屬性。我們將該屬性賦給 border-radius 值,但隨後使用 --double() 自定義函式將其加倍用於 padding 值。

css
p {
  --base-spacing: 10px;
  border-radius: var(--base-spacing);
  padding: --double(var(--base-spacing));
  width: 50%;
  background-color: wheat;
}

結果

規範

規範
CSS 函式與混入模組
# function-rule

瀏覽器相容性

另見