這個 CSS 特性感覺像 JavaScript:但它是 100% 原生的
這些年我一直在和 CSS 打交道,反復打磨樣式表,只為追求“干凈又靈動”的設計平衡。
你是否也有同感?一遍遍寫重復的規則,為了一個小邏輯去繞 JavaScript,擔心設計系統越用越亂。
今天我們來看看一個簡單卻強力的 CSS 特性:它不僅能讓樣式表更清爽,還能高度復用。
一起上手。
寫出干凈、可復用的 CSS
最近留意到 Chrome 139 帶來的新能力——@function 規則。真心講,既“酷”又“好用”。
這不只是又一個 CSS 語法點,而是一種更“聰明”的寫法:讓復用與邏輯封裝成為日常,風格貼近 2025 年的現代前端。
接下來我們用它來簡化設計系統:從流式排版到主題切換,你可以把示例代碼直接落地到項目里。
@function 是什么?
@function 允許你定義自定義 CSS 函數,把可復用的樣式邏輯封裝起來。你可以把它想成 CSS 里的“迷你 JavaScript 函數”:純粹、聲明式、由瀏覽器原生支持。
為什么這對你很重要?
因為它能減少重復代碼,讓樣式在不依賴預處理器或腳本的情況下更具動態性。
先看個直觀示例:
@function --dashed-border(--color: red) {
result: 2px dashed var(--color);
}這段代碼創建了一個可復用的“虛線邊框”函數。更妙的是:你還能給參數設置默認值——上面默認色就是 red。
用法如下:
div {
border: --dashed-border(blue); /* 2px dashed blue */
}簡潔、直接、可復用。干凈吧?
實用場景 1:優雅求“負”的工具
有時我們需要負值(比如外邊距或定位),但 calc() 連用起來很凌亂。
自定義 @function 就能把它封成一行、處處可用:
/* 返回某個值的相反數 */
@function --negate(--value) {
result: calc(-1 * var(--value));
}
.navigation {
margin: --negate(30px);
}任何值一鍵“取負”,布局更靈活。告別滿屏 calc()。是不是順手多了?
實用場景 2:不費力的透明度處理
給顏色做透明變化(比如 hover 或 disabled 態),過去常常意味著重復規則或拉上 JS。
現在,@function 把這套邏輯集中到一個地方:
/* 返回半透明的顏色值 */
@function --opacity(--opacity, --color: #007bff) {
result: rgb(from var(--color) r g b / var(--opacity));
}
button {
background: --opacity(0.8);
}
button:hover {
background: --opacity(1);
}
button:disabled {
background: --opacity(0.3, gray);
}再配合主題或狀態相關的自定義屬性,你就能寫出無需額外類名的動態按鈕樣式。并且這里也給顏色參數留了默認值。
實用場景 3:順滑可控的流式排版
響應式設計里,流式排版很關鍵;但反復寫 clamp(),真心費勁。
用 @function 把它變成一句話:
@function --fluid-type(--font-min, --font-max, --type: 'header') {
--scalar: if(style(--type: 'header'): 4vw;
style(--type: 'copy'): 0.5vw);
result: clamp(var(--font-min), var(--scalar) + var(--font-min), var(--font-max));
}
h1 {
font-size: --fluid-type(24px, 36px);
}
p {
font-size: --fluid-type(16px, 24px, 'copy');
}字體會隨視口平滑縮放,并可根據標題/正文字體分別設置縮放強度。
沒函數之前手寫?那體驗,別提了 ??。
實用場景 4:自適應邊界的條件圓角
當元素貼近視口邊緣時,讓圓角“收起來”,能避免難看的貼邊效果;但為此寫媒體查詢就有點小題大做。
@function 的寫法更干凈:
/* 當元素距離屏幕邊緣在一定閾值內(默認 4px,可傳第二參)時,按條件收縮圓角 */
@function --conditional-radius(--radius, --edge-dist: 4px) {
result: clamp(0px, ((100vw - var(--edge-dist)) - 100%) * 1e5, var(--radius));
}
/* 用法 */
.box {
/* 1rem 圓角,默認 4px 邊緣距離 */
border-radius: --conditional-radius(1rem);
}
.box-2 {
/* 1rem 圓角,緊貼邊緣(0px 距離) */
border-radius: --conditional-radius(1rem, 0px);
}當元素觸到視口邊緣時,圓角自動收斂,版面更干凈。
無需媒體查詢。這就是我偏愛的 CSS 風格。
實用場景 5:把明暗主題拓展到“任何屬性”
light-dark() 對顏色很好用,但邊框、字重、尺寸這些怎么辦?
自定義 @function 可以把主題邏輯擴展到任意屬性:
/* 若用戶的顏色偏好為淺色,取第一個值;若為深色,取第二個值 */
@function --light-dark(--light, --dark) {
result: if(
style(--scheme: dark): var(--dark);
else: var(--light)
);
}
:root {
--root-scheme: light;
--scheme: light;
@media (prefers-color-scheme: dark) {
--root-scheme: dark;
--scheme: dark;
}
}
@scope ([data-scheme]) {
:scope {
--scheme-from-attr: attr(data-scheme type());
--scheme: if(
style(--scheme-from-attr: system): var(--root-scheme);
else: var(--scheme-from-attr)
);
color-scheme: var(--scheme); /* 讓原生 light-dark() 生效 */
}
}用法示例:
[data-scheme] {
color: light-dark(#333, #e4e4e4);
background-color: light-dark(aliceblue, #333);
border: 4px --light-dark(dashed, dotted) currentcolor;
font-weight: --light-dark(500, 300);
font-size: --light-dark(16px, 18px);
}<div class="stylable-thing" data-scheme="light">
…
</div>實用場景 6:側欄網格的響應式函數
我們再寫一個側欄布局的小工具:
/* 小屏下側欄占 1fr;>=640px 時側欄固定寬度,其余空間給主內容 */
@function --layout-sidebar(--sidebar-width: 20ch) {
result: 1fr;
@media (width > 640px) {
result: var(--sidebar-width) auto;
}
}
.layout {
display: grid;
/* 使用默認 20ch 的側欄寬度 */
grid-template-columns: --layout-sidebar();
}這個函數能把側欄/主內容的響應式切換一步到位:小屏單列,大屏固定側欄 + 自適應主區域。
加餐:給函數也做“類型檢查”
就像 @property 可以為自定義屬性約束類型一樣,CSS @function 也能限制參數與返回值的類型。結合內聯條件表達式,還能做更安全的動態計算。
示例如下:
@function --custom-spacing(--a <length>) { /* ... */ } /* 例:10px */
@function --custom-background(--b <color>) { /* ... */ } /* 例:hsl(50%, 30% 50%) */
@function --custom-margin(--c <length>+) { /* ... */ } /* 例:10px 2rem 20px */
@function --wideness(--d type(<number> | <percentage>)) { /* ... */ }我們甚至可以為返回值聲明類型:
@function --progression(--current, --total) returns <percentage> {
result: calc(var(--current) / var(--total) * 100%);
}為什么說它“像未來”?
以往這類邏輯常靠 Sass 或 JavaScript 處理;而現在,@function 把它原生落在 CSS 層。
意義不止是“寫得更少”,更是讓樣式具備智能適配能力。
同時,這也順應了 React 19 對渲染優化的趨勢:樣式更精簡,應用更迅速。
但要注意什么?
Chrome 139 畢竟是前沿版本,瀏覽器支持度暫時有限。這里沒有可用的 polyfill,但你可以用特性檢測或回退策略來兼容舊環境。
.browser-support {
margin: 2rem auto;
width: max-content;
@supports (color: --function(value)) {
display: none;
}
}這樣就能在嘗試新特性的同時,保證線上安全。




























