
CSS clip-path 常見陷阱:陰影、插值、版面與 Safari 相容性
CSS clip-path 可以改變元素的可見形狀,但不會同時改變所有與方框有關的行為。陰影被裁走、圖示周圍仍有空位,未必是瀏覽器出錯。本文先說明裁剪、插值及版面尺寸的規則,再把 WebKit 曾出現的 SVG 參照問題獨立處理,方便逐項排查。
日文原文發布: 2026-04-17
先了解 clip-path 的基本用法
clip-path 可把元素裁成多邊形、圓形、橢圓形,或其他支援的路徑形狀。
.hexagon {
clip-path: polygon(
25% 0%, 75% 0%, 100% 50%,
75% 100%, 25% 100%, 0% 50%
);
}主要瀏覽器已廣泛支援基本裁剪功能,但不同語法的支援程度仍須分開確認。舊版 Safari 曾需要 -webkit-clip-path 前綴;如要支援這些版本,可把相容宣告放在前面,標準宣告放在後面。請查閱相容性資料,並在實際需要支援的裝置及版本測試。
.hexagon {
-webkit-clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}WebKit 的過往問題:SVG 參照與堆疊上下文
WebKit Bug 233553 記錄了一個特定個案:在 <img> 使用 SVG 參照 clip-path: url(#shape),再加入 transform 等會建立堆疊上下文(stacking context)的宣告,圖片可能完全消失。該個案的 SVG 使用 clipPathUnits="objectBoundingBox"。
修正已於 2024 年 11 月 5 日合併至 WebKit,問題狀態為 RESOLVED FIXED。合併日期本身不足以確定哪個 Safari 正式版本最先包含修正。因此,不應把它描述成現行 Safari 普遍存在的未解決問題,也不能由此推論所有 polygon() 與 transform 的組合都有問題。
/* 歷史個案的 CSS 片段;須另外提供圖片及 SVG #shape 定義。 */
.masked-image {
clip-path: url(#shape);
transform: translate3d(0, 0, 0);
}排查時,請在目標 Safari 版本依次測試只有 SVG 參照、只有建立堆疊上下文的宣告,以及兩者同時存在的情況。若仍能重現問題,可移除不必要的合成相關宣告;如果基本形狀能表達同一輪廓,也可考慮 polygon(),然後在目標裝置驗證。不要把促使合成的宣告當成通用修正,因為它可能再次構成上述個案的觸發條件。
要保留外陰影:外層加濾鏡,內層做裁剪
超出裁剪範圍的 box-shadow 也會被裁走,這是規格定義的行為,並非 Safari 特有問題。在不透明元素上直接加入一般外陰影,不會自動得到沿新輪廓向外延伸的陰影。
/* 裁剪範圍以外的陰影不會顯示。 */
.badge {
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
box-shadow: 0 4px 12px rgba(0,0,0,.2);
}CSS Masking 定義的處理次序是先套用濾鏡,再做裁剪。因此,即使改用 filter: drop-shadow(),只要放在同一元素,陰影仍會受到裁剪。做法是把濾鏡放到外層容器,讓子元素負責 clip-path。以下範例前半是 HTML,由 .badge-shadow 開始則是 CSS,應分別放到對應位置。
<div class="badge-shadow">
<div class="badge-shape">徽章</div>
</div>
.badge-shadow {
display: inline-block;
filter: drop-shadow(0 4px 12px rgba(0,0,0,.25));
}
.badge-shape {
width: 160px;
height: 100px;
display: grid;
place-items: center;
background: #2563eb;
color: white;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}外層容器本身應保持透明背景,讓子元素的形狀成為陰影的輪廓。若更外層的祖先元素設有 overflow: hidden,陰影仍可能被裁走。濾鏡的繪製負擔與使用數量及面積有關,大量使用時應在目標裝置量度。
polygon() 插值:頂點數、填充規則及參照框要一致
起點與終點的多邊形頂點數不同,就不能對座標作連續插值。CSS 關鍵影格動畫及 Web Animations 可作離散切換;一般 CSS transition 預設不會為離散變化啟動過渡效果。以兩個關鍵影格及線性進度為例,離散切換發生在區間中點;預設 transition 則可直接套用新值,不能一概說成到最後才跳轉。
/* 無法連續插值:由 4 個頂點變成 6 個。 */
.el { clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%); }
.el:hover { clip-path: polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%); }要連續變形,先把兩端的頂點數對齊。把同一座標重複列出,可令額外的頂點在起始狀態與另一頂點重疊。
/* 起點及終點均有 6 個頂點。 */
.el {
clip-path: polygon(0 0, 100% 0, 100% 0, 100% 100%, 0 100%, 0 100%);
}
.el:hover {
clip-path: polygon(25% 0, 75% 0, 100% 50%, 75% 100%, 25% 100%, 0 50%);
}CSS Shapes 對這種多邊形插值亦要求相同的參照框(reference box)及填充規則(fill-rule)。上例兩端均使用預設的 border-box 及 nonzero。只有 hover 形狀宣告並不會產生動畫;如要加入過渡效果,還須設定例如 transition: clip-path 250ms linear。亦應尊重用戶減少動態效果的偏好,例如在該設定下停用過渡效果。
父元素的 overflow 與子元素的裁剪要分開查
父元素的 overflow: hidden 與子元素的 clip-path 是兩項不同的裁剪限制,可見範圍會同時受兩者約束。若只看子元素的形狀,容易把父元素造成的裁剪誤當成 clip-path 出錯。
可先暫時把父元素的 overflow 改為 visible,檢查子元素單獨裁剪的結果,再恢復所需的父元素尺寸及 overflow 設定。未確認裁剪邊界前,不應隨意加入 position 或 isolation 作為修正。
.parent {
position: relative;
overflow: hidden;
}
.child {
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}裁剪不會縮小版面所用的方框
clip-path 改變繪製結果,不會改變元素本身的幾何尺寸,也不會改變固有尺寸(intrinsic size)的計算。即使元素位於 Grid 或 Flexbox 內,被隱藏的部分仍屬於版面計算所用的方框,所以視覺上細小的圖示,周圍仍可能佔用空間。
請按需要設定 width 及 height。當某一方向的尺寸為 auto,aspect-ratio 可協助推算該方向的尺寸,但比例本身不會指定實際大小。父層限制及 Flex 項目的縮小行為也須一併檢查。
.icon {
width: 32px;
height: 32px;
clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}建議的排查次序
- 目標是 Safari,就在 Safari 檢查。在 Chrome 運作正常,並不足以證明 Safari 也有相同結果。
- 先停止動畫及過渡效果,再獨立移除 transform。
transform: none不會停止clip-path的動畫。可利用開發者工具暫停動態效果,再逐項排除宣告。 - 暫時使用 clip-path: none。先查看原本的版面方框及位置,然後恢復裁剪形狀。
- 把語法支援與繪製正確性分開驗證。polygon、path 及 SVG 參照不是同一項相容性測試。
CSS.supports()可檢查宣告是否受支援,但不能證明繪製沒有錯誤。
重點回顧
- 需要支援舊 Safari 時,把前綴宣告放在標準宣告之前。
- WebKit Bug 233553 是已修正的過往個案;仍應在目標版本分開驗證 SVG 參照及堆疊上下文的條件。
- 要讓外陰影沿形狀延伸,外層容器套用濾鏡,子元素套用裁剪。
- 多邊形連續插值需要相同的頂點數、填充規則及參照框。
- 父元素的 overflow 與子元素的 clip-path 應逐項排查。
- 裁剪不會縮小版面方框;請設定所需尺寸,並檢查父層限制。
參考資料及來源
- W3C: CSS Box Sizing Module Level 4 ↗
- W3C: CSS Transitions Module Level 2 ↗
- W3C: Web Animations ↗
- MDN Web Docs: clip-path CSS property - CSS ↗(英文)
- W3C: CSS Masking Module Level 1 ↗
- W3C: CSS Shapes Module Level 1 ↗
- bugs.webkit.org: 233553 – Combining CSS clip-path with any property that creates a new stacking context makes img element disappear ↗
編輯說明
本文使用 AI 協助編輯,並在發布前由編輯核對。內容仍可能包含事實、理解或時效上的錯誤;作出重要決定前,請查閱所列的一手資料或官方文件。

