使用 CSS 自定義函式
CSS 自定義函式使你能夠建立可重用的 CSS 程式碼塊,這些程式碼塊可以接受引數,包含複雜的邏輯(使用 CSS if() 函式和 @media @規則等特性定義),並根據該邏輯返回值。它們的工作方式類似於 CSS 自定義屬性,但提供了更大的靈活性。
在本文中,我們將向你展示如何使用它們,並提供一些實際的例子。
函式基礎
一個基本的 CSS 自定義函式定義如下所示:
@function --half-opacity() {
result: 0.5;
}
在 @function 語法之後,我們為函式定義一個名稱:--half-opacity。這必須是一個 <dashed-ident> 型別——它必須以雙破折號開頭,並且區分大小寫。函式名後緊跟一對圓括號(())和一對花括號({})。
注意:如果多個 CSS 函式被賦予相同的名稱,則在級聯中更強的 @layer 中的函式會獲勝。如果它們都在同一層中,則原始碼中最後定義的函式會獲勝。
花括號內是函式的主體,這裡定義了函式的邏輯。這可以包含多個宣告,包括自定義屬性(其作用域將限於函式主體)、諸如 @media 之類的 @規則,以及 result 描述符。result 描述符的值被計算以確定函式返回的值。
在這裡,我們將 result 設定為值 0.5:--half-opacity() 函式將始終返回 0.5。
為什麼是“result”而不是“return”?
result 描述符在功能上聽起來類似於 JavaScript 函式的 return 語句。然而,CSS 函式中不使用 return。這是因為,與 JavaScript 的 return 語句不同,CSS 函式不會在遇到 result 宣告時立即返回值。
CSS 函式的主體從頭到尾進行計算。如果主體中包含多個 result 宣告,則原始碼中最後一個會覆蓋前面的。
呼叫 CSS 函式
可以使用 <dashed-function> 語法在任何合適的屬性值位置呼叫 CSS 函式,該語法由函式名後跟一對圓括號組成,圓括號內包含要傳遞給函式的引數(如果有)。例如,我們可以像這樣呼叫我們的 --half-opacity() 函式:
h2 {
opacity: --half-opacity();
}
由於此函式始終返回值 0.5,因此前面的宣告等同於 opacity: 0.5。這並不是很有用。你還不如直接使用自定義屬性或字面量值 0.5。
讓我們繼續看看如何使用 CSS 函式。
CSS 函式的特性檢測
CSS 函式在沒有引數時的一個實際用途是特性檢測。在本文我們將要看到的所有示例中,我們定義了一個 --supports() 函式,它看起來像這樣:
@function --supports() {
result: none;
}
然後,你可以定義一個“功能不支援”的橫幅,並將其 display 屬性設定為 --supports():
<p class="support">
⚠️ Your browser doesn't currently support CSS custom functions.
</p>
.support {
/* ... */
display: --supports();
}
在支援自定義函式的瀏覽器中,display 將被設定為 none,支援橫幅將被隱藏。在不支援的瀏覽器中,display: --supports() 宣告將是無效的,因此會被忽略;因此,橫幅將被顯示。
指定函式引數
CSS 函式引數在函式名後的圓括號內指定為逗號分隔的自定義屬性。例如:
@function --transparent(--color, --alpha) {
result: oklch(from var(--color) l c h / var(--alpha));
}
該函式名為 --transparent,並接受兩個自定義屬性作為引數,--color 和 --alpha,它們可以在函式主體內部區域性使用。主體包含一個 result 描述符,它使用 CSS 相對顏色語法將輸入的 --color 值轉換為一個 oklch() 顏色,其 alpha 通道值由輸入的 --alpha 值指定。
然後,你可以在任何想要生成現有顏色半透明版本的地方呼叫此函式。
例如
section {
--base-color: #faa6ff;
background-color: --transparent(var(--base-color), 0.8);
}
指定資料型別
可以為函式引數和返回值指定允許的資料型別。當你不指定這些時,函式將接受任何型別的值。
讓我們修改我們之前的函式以提供資料型別:
@function --transparent(--color type(<color>), --alpha type(<number>)) returns
type(<color>) {
result: oklch(from var(--color) l c h / var(--alpha));
}
每個引數的資料型別在引數名後指定,而 result 的資料型別在左花括號前指定,並以 returns 關鍵字開頭。type() 函式用於指定資料型別。
請注意,在只指定單個數據型別的情況下,可以省略 type() 語法,直接將型別寫成簡寫形式:
@function --transparent(--color <color>, --alpha <number>) returns <color> {
result: oklch(from var(--color) l c h / var(--alpha));
}
現在,只有當輸入引數分別為 <color> 和 <number>,並且 result 是一個 <color> 時,該函式才會產生有效值。否則,例如:
section {
--base-color: #faa6ff;
background-color: --transparent(var(--base-color), 50%);
}
那麼該值將在計算值時變得無效(因為 50% 不是 <number> 而是 <percentage>),background-color 最終將被設定為 transparent。
指定多個允許的型別
你可以使用 | 符號作為分隔符來指定多個可接受的資料型別,例如:
@function --transparent(--color <color>, --alpha type(<number> | <percentage>))
returns <color> {
result: oklch(from var(--color) l c h / var(--alpha));
}
在這種情況下,必須使用完整的 type() 語法。
經過這個調整,--transparent(var(--base-color), 50%) 函式呼叫現在是有效的。
指定預設值
你還可以在引數定義的末尾,用冒號指定引數的預設值。例如:
@function --transparent(--color <color>, --alpha <number>: 0.8) returns <color> {
result: oklch(from var(--color) l c h / var(--alpha));
}
--alpha 引數的預設值現在是 0.8。如果你想使用這個值,可以在呼叫函式時省略第二個引數:
section {
--base-color: #faa6ff;
background-color: --transparent(var(--base-color));
}
注意:如果一個無效的值作為函式引數傳入,並且該引數定義中指定了預設值,那麼無效值將被忽略,而使用預設值。
顏色調整函式示例
你可以在我們的 color-adjust-functions 示例中看到 --transparent() 函式的實際效果(參見原始碼)。
這個例子還包括名為 --lighter() 和 --darker() 的函式,它們的工作方式與 --transparent() 類似,但分別返回顏色的更亮和更暗的變體:
@function --transparent(--color <color>, --alpha <number>: 0.8) returns <color> {
result: oklch(from var(--color) l c h / var(--alpha));
}
@function --lighter(--color <color>, --lightness-adjust <number>: 0.2) returns
<color> {
result: oklch(from var(--color) calc(l + var(--lightness-adjust)) c h);
}
@function --darker(--color <color>, --lightness-adjust <number>: 0.2) returns
<color> {
result: oklch(from var(--color) calc(l - var(--lightness-adjust)) c h);
}
像這樣的函式庫對於基於單一顏色定義顏色方案非常有用:
:root {
--base-color: #faa6ff;
}
section {
background-color: --transparent(var(--base-color));
border: 3px solid --lighter(var(--base-color), 0.1);
color: --darker(var(--base-color), 0.55);
}
包含複雜邏輯
你可以使用諸如 @media @規則和 if() 函式之類的構造在函式中包含更復雜的邏輯。
我們的 responsive-narrow-wide 示例(參見原始碼)展示了一個名為 --narrow-wide() 的函式,它可以為任何屬性提供兩個值選項。一個在視口低於特定斷點時設定,另一個在視口高於該斷點時設定。
--narrow-wide() 函式接受兩個引數,--narrow 和 --wide。返回的 result 是 --wide 屬性,除非視口寬度小於 700px,在這種情況下返回 --narrow。
@function --narrow-wide(--narrow, --wide) {
result: var(--wide);
@media (width < 700px) {
result: var(--narrow);
}
}
該函式可用於在多種上下文中提供響應式的值選項:
body {
display: grid;
grid-template-columns: repeat(--narrow-wide(1, 3), 1fr);
gap: --narrow-wide(0, 20px);
padding: 0 20px;
}
h2 {
font-size: --narrow-wide(2.5rem, 2rem);
}
p {
font-size: --narrow-wide(1.4rem, 1rem);
line-height: 1.5;
}
使用 if() 函式
我們可以使用 if() 函式來重寫 --narrow-wide() 函式:
@function --narrow-wide(--narrow, --wide) {
result: if(media(width < 700px): var(--narrow) ; else: var(--wide));
}
一次編寫複雜語法,然後重用
CSS 函式的一個關鍵用例是定義一次複雜的語法片段,然後能夠透過更簡單的函式呼叫多次重用它。
我們的 gradient-function 示例(參見原始碼)提供了這方面的一個例子。它有一個名為 --shippo-pattern() 的函式,該函式接受長度和顏色引數,並返回一個複雜的 background 值,該值包含多個 radial-gradient() 背景:
@function --shippo-pattern(--size <length>, --tint <color>) {
result:
radial-gradient(closest-side, transparent 98%, rgb(0 0 0 / 0.3) 99%) 0 0 /
var(--size) var(--size),
radial-gradient(closest-side, transparent 98%, rgb(0 0 0 / 0.3) 99%)
calc(var(--size) / 2) calc(var(--size) / 2) / var(--size) var(--size)
var(--tint);
}
定義了這個函式後,我們現在可以建立具有不同色調和圓圈大小的該背景值的變體:
#one {
background: --shippo-pattern(100px, #def);
}
#two {
background: --shippo-pattern(3.5rem, lime);
}
#three {
background: --shippo-pattern(10vw, purple);
}
另見
- CSS 自定義屬性
- CSS 自定義函式與混入模組
- Custom CSS Functions in the Browser 作者:Miriam Suzanne (2025)
- CSS @function + CSS if() 作者:Bramus (2025)
- 5 Useful CSS functions using the new @function rule 作者:Una Kravets (2025)