漸層邊框繞著卡片或按鈕流動,是定價方案、「推薦」標籤與主要按鈕常用的強調方式。CSS 的 border-image 不支援 border-radius,所以實務上都是用背景或偽元素疊出來。這篇整理三種做法,每一種都附可以直接貼上的 CSS,最後比較取捨。範例以 Tailwind CSS v4.3 專案為準,CSS 本身不依賴 Tailwind。
瀏覽器支援資料查核日期:2026-10-14。
做法一:旋轉 conic-gradient 圖層
外層容器留 2px 內距並裁切溢出,在後面放一塊比容器大的正方形,填上 conic-gradient 後用 transform: rotate() 旋轉。內層內容蓋在上面,露出來的 2px 就是邊框。
.spin-border {
position: relative;
overflow: hidden;
border-radius: 12px;
padding: 2px;
}
.spin-border::before {
content: "";
position: absolute;
left: 50%;
top: 50%;
width: 200%;
aspect-ratio: 1;
transform: translate(-50%, -50%);
background: conic-gradient(from 0deg, transparent 0 70%, #6366f1, #ec4899);
animation: spin-border 4s linear infinite;
}
.spin-border > * {
position: relative;
border-radius: 10px;
background: #09090b;
}
@keyframes spin-border {
from {
transform: translate(-50%, -50%) rotate(0deg);
}
to {
transform: translate(-50%, -50%) rotate(360deg);
}
}
@media (prefers-reduced-motion: reduce) {
.spin-border::before {
animation: none;
}
}同樣的結構用 Tailwind utility 寫:
<div className="relative overflow-hidden rounded-xl p-[2px]">
<div
aria-hidden="true"
className="pointer-events-none absolute left-1/2 top-1/2 aspect-square w-[200%] -translate-x-1/2 -translate-y-1/2 animate-[spin_4s_linear_infinite] bg-[conic-gradient(from_0deg,transparent_0_70%,#6366f1,#ec4899)] motion-reduce:animate-none"
/>
<div className="relative rounded-[calc(var(--radius-xl)-2px)] bg-zinc-950 px-6 py-4 text-zinc-100">
新版本已部署到正式環境
</div>
</div>Tailwind v4 的 -translate-x-1/2 寫的是獨立的 translate 屬性,animate-spin 的 keyframes 寫的是 transform,兩者不會互相覆蓋,所以可以直接沿用內建的 spin。
取捨: 動畫的是 transform,瀏覽器通常能交給合成層處理,成本最低。缺點是內層一定要有不透明背景,而且旋轉的正方形必須大到能覆蓋容器的對角線。上面的 w-[200%] 適用於寬大於高的元素,直立的長卡片要改用高度計算,否則旋轉到某些角度時邊角會露白。conic-gradient 的支援從 Chrome 69、Firefox 83、Safari 12.1 開始(caniuse),這個做法不需要任何新特性。
做法二:用 @property 動畫漸層角度
不旋轉元素,改成旋轉漸層本身。CSS 變數預設不能被插值,用 @property 註冊成 <angle> 型別後,瀏覽器就能在 keyframes 裡逐幀計算角度。
@property --border-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.angle-border {
border: 2px solid transparent;
border-radius: 12px;
background:
linear-gradient(var(--card-bg, #09090b), var(--card-bg, #09090b)) padding-box,
conic-gradient(from var(--border-angle), #6366f1, #ec4899, #f59e0b, #6366f1) border-box;
animation: border-angle 4s linear infinite;
}
@keyframes border-angle {
to {
--border-angle: 360deg;
}
}
@media (prefers-reduced-motion: reduce) {
.angle-border {
animation: none;
}
}兩層背景分別裁在 padding-box 與 border-box:上層純色填滿內距區,下層漸層只從透明邊框露出來。結構只需要一個元素,不需要偽元素或額外的 div。
在 Tailwind v4 專案裡,@property 與 @keyframes 直接寫在全域 CSS 頂層即可;想讓它能搭配 hover:、md: 等前綴使用,可以把 .angle-border 的內容改寫成 @utility angle-border { ... }。
取捨: 每一幀都要重新繪製背景,成本比做法一高,同一頁放很多個時要留意。內層同樣必須是不透明的純色。好處是邊框寬度與圓角就是元素自己的 border 與 border-radius,不會有露白問題。
瀏覽器支援: @property 在 MDN 標示為 Baseline 2024,從 2024 年 7 月起三大引擎都支援:Chrome 與 Edge 85、Safari 16.4、Firefox 128。caniuse 在 2026-10-14 顯示全球支援率約 96.13%(caniuse)。不支援的瀏覽器會把未註冊的變數當成離散值,0deg 與 360deg 看起來一樣,結果是一圈靜止的漸層邊框,版面不會壞掉。
做法三:用 mask 挖空中央
前兩種做法都要求內層有不透明背景。如果卡片是半透明玻璃效果,或底下有背景圖要透出來,就需要把漸層的中央真正挖掉。做法是在偽元素上疊兩層遮罩:一層只覆蓋 content-box,一層覆蓋整個元素,再用 exclude 合成,剩下的就只有 padding 那一圈。
@property --border-angle {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
.mask-border {
position: relative;
border-radius: 12px;
}
.mask-border::before {
content: "";
position: absolute;
inset: 0;
padding: 2px;
border-radius: inherit;
background: conic-gradient(from var(--border-angle), #6366f1, #ec4899, #f59e0b, #6366f1);
-webkit-mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
-webkit-mask-composite: xor;
mask:
linear-gradient(#000 0 0) content-box,
linear-gradient(#000 0 0);
mask-composite: exclude;
animation: border-angle 4s linear infinite;
pointer-events: none;
}
@keyframes border-angle {
to {
--border-angle: 360deg;
}
}
@media (prefers-reduced-motion: reduce) {
.mask-border::before {
animation: none;
}
}宣告順序有意義:mask 簡寫會把 mask-composite 重設為預設值,所以 mask-composite: exclude 必須寫在 mask 之後。前面的 -webkit- 兩行給只認得舊語法的瀏覽器,舊語法的 xor 對應標準的 exclude。
取捨: 中央完全透明,任何背景都能透出來,這是三種做法裡唯一能做到的。成本與做法二相同,也是每幀重繪。邊框寬度由偽元素的 padding 決定。動畫同樣依賴 @property,不支援時退化成靜止邊框。MDN 標示 mask-composite 從 2023 年 12 月起各大瀏覽器皆可用(MDN)。
三種做法比較
| 旋轉圖層 | @property 角度 | mask 挖空 | |
|---|---|---|---|
| 內層背景 | 必須不透明 | 必須不透明 | 可以透明 |
| 動畫屬性 | transform | 註冊的 CSS 變數 | 註冊的 CSS 變數 |
| 每幀成本 | 低,通常在合成層 | 重繪背景 | 重繪偽元素 |
| 需要的 DOM | 外層、旋轉層、內層 | 一個元素 | 一個元素加偽元素 |
| 舊瀏覽器 | 只需 conic-gradient | 退化成靜止漸層邊框 | 退化成靜止漸層邊框 |
有一點三種做法都一樣:conic-gradient 是以中心點掃角度,在長方形上,亮點經過長邊中段時慢、經過轉角時快。如果需要光點沿著周長等速移動,要換成 offset-path 讓一個元素沿著圓角矩形路徑走,這也是下面 Border Beam 的做法。
WebberUI 的邊框與按鈕元件
以下元件都已經處理好 prefers-reduced-motion(透過 motion/react 的 useReducedMotion),用 WebberUI CLI 安裝後原始碼放進你的專案:
- Border Beam:一道光束沿容器邊框巡遊。用
offset-path: rect(... round ...)貼齊圓角,配合mask-composite只在邊框區顯示。免費。 - Moving Border Button:一顆光點沿按鈕圓角邊框繞行,同樣以
offset-path定位。免費。 - Neon Gradient Card:旋轉 conic 漸層邊框加外暈。以逐幀更新漸層角度驅動,而不是旋轉元素,避免做法一的邊角露白。免費。
- Shimmer Button:光沿按鈕周邊流動,帶內襯高光與 hover 立體反饋。免費。
- Rainbow Button:彩虹漸層流動的按鈕,有實心與外框兩種樣式。免費。
- Electric Border:用 SVG
feTurbulence噪點位移扭曲描邊,做出抖動的電流邊框。免費。
把這個效果裝進你的專案
在專案資料夾執行指令,CLI 會加入原始碼與依賴套件,再依下方使用範例引用元件。
npx webberui@latest add border-beamnpx webberui@latest add https://webberui.com/r/border-beam.json更多可以看 卡片與網格 與 按鈕與切換 兩個分類。如果漸層邊框要放在無限捲動的區塊裡,可以參考 Tailwind 無限跑馬燈。