CSS clip-path のブラウザ差 — Safari で崩れるケースと実践的な対策
GDESIGN
デザイン(更新: 2026-08-22)6 分で読める

CSS clip-path のブラウザ差 — Safari で崩れるケースと実践的な対策

CSS clip-path は、要素を任意の形に切り抜ける便利なプロパティです。本記事では、仕様で決まる影・補間・レイアウトの挙動と、WebKitで条件付きの報告があるSVG clipPath参照の問題を分け、再現条件を限定して解説します。

#CSS#clip-path#Safari#ブラウザ差分

clip-path の基本おさらい

clip-path は、要素を多角形・円・楕円・SVGパス等の形状で切り抜きます。

.hexagon {
  clip-path: polygon(
    25% 0%, 75% 0%, 100% 50%,
    75% 100%, 25% 100%, 0% 50%
  );
}

clip-path は現在の主要ブラウザで広く利用できます。Safari は長らく -webkit-clip-path プレフィックスを必要としていた歴史があるため、古いSafari系まで対象にする場合は互換宣言を先に置き、標準宣言を後に置きます。必要なバージョンはMDNの互換表と実機で確認してください。

.hexagon {
  -webkit-clip-path: polygon(/* ... */);
          clip-path: polygon(/* ... */);
}

WebKitで報告されたSVG clipPath参照とstacking contextの問題

WebKit Bug 233553では、<img>にSVGのclip-path: url(#shape)を指定し、さらにtransform等でstacking contextを作ると画像が消える事例が報告されています。これは特定のSVG参照と合成条件の報告であり、polygon()とtransformの全組み合わせが不安定だという根拠ではありません。

/* WebKitで報告された条件の概略 */
.masked-image {
  clip-path: url(#shape);
  transform: translate3d(0, 0, 0); /* stacking contextを作る条件の例 */
}

切り分け: 対象SafariでSVG参照だけ、stacking contextを作る指定だけ、両方の順に確認します。問題が再現する場合は、不要な合成指定を外すか、同じ輪郭を表現できる用途ではpolygon()等のbasic shapeも候補にし、対象端末で結果を確認してください。合成を促す指定を一律に追加する対策は、この既知条件を強める可能性があるため避けます。

崩れケース2: box-shadow が clip-path で切られてしまう

これはSafari固有ではなく仕様通りの挙動です。clip-path領域の外側へ出たbox-shadowはクリップされるため、不透明な要素へ通常の外側box-shadowを指定しても、切り抜いた輪郭に沿う外影にはなりません。

/* 影が消える */
.badge {
  clip-path: polygon(/* 六角形 */);
  box-shadow: 0 4px 12px rgba(0,0,0,.2);  /* 見えない */
}

対策: 親ラッパーにfilter: drop-shadow()を指定する

CSS Maskingの描画順ではフィルターの後にクリッピングされます。そのため、同じ要素へdrop-shadowを指定しても影はclip-pathで切られます。親要素へフィルター、子要素へclip-pathを分けます。

<div class="badge-shadow">
  <div class="badge-shape">Badge</div>
</div>

.badge-shadow {
  filter: drop-shadow(0 4px 12px rgba(0,0,0,.25));
}
.badge-shape {
  clip-path: polygon(/* 六角形 */);
}

フィルターの利用量や対象面積で描画負荷は変わるため、大量に使うページでは対象端末で計測してください。

崩れケース3: polygon() のアニメーションで頂点数が違うと崩れる

clip-pathのアニメーションで、開始状態と終了状態で polygon の頂点数が異なると、ブラウザは補間できず、カクついたり最終状態に瞬間スナップしたりします。

/* NG: 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%); }

対策: 開始・終了で同じ頂点数にする。変化させたくない頂点は同じ座標に2つ重ねて配置する方法もあります。

/* OK: 両方 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仕様では、頂点数とfill-ruleが一致するpolygon()同士だけに補間が定義されています。異なる頂点数を滑らかに変形できる前提にせず、同数へ揃えてください。

確認点4: 親のoverflowとclip-pathが重なる場合

親要素の overflow: hidden と子要素の clip-path は別々のクリップ領域です。見える範囲は両方の制約を受けるため、子の形状だけを見ているとclip-pathが崩れたように見えることがあります。

切り分け: まず親のoverflowを一時的にvisibleへ戻し、子のclip-path単独の結果を確認します。次に必要な親の寸法とoverflowを戻してください。positionやisolationを根拠なく足すのではなく、各クリップ領域を個別に確認します。

.parent {
  position: relative;
  overflow: hidden;
}
.child {
  clip-path: polygon(/* ... */);
}

崩れケース5: clip-path と CSS Grid/Flex の intrinsic size

Grid/Flex内の要素にclip-pathを当てると、intrinsic size(要素の自然サイズ)の計算に clip-path は影響しません。つまりクリップされた"見えない部分"もレイアウト計算上は存在します。

視覚的に小さく見えるアイコンが、実際は周囲に余白を作ってしまう現象です。

対策: width/height を明示するか、aspect-ratio で縦横比を固定すると予測可能になります。

.icon {
  width: 32px;
  height: 32px;
  aspect-ratio: 1 / 1;
  clip-path: polygon(/* ... */);
}

デバッグのコツ

  1. Safari Web Inspector で表示 — Chrome DevTools で動くものが Safari で動かない場合、Safari で直接見るのが最速
  2. transform: none; でアニメーションを切って確認 — 静的な形状は正しいか? transformとの合成が原因か切り分ける
  3. clip-path: none; でレイアウトを確認 — クリップなしで要素がどこにあるか確認してから戻す
  4. CanIUse で機能単位の対応状況を確認clip-path: path()(SVGパス)などは対応が遅れているケースあり

まとめ

  • 古いSafari系も対象なら-webkit-clip-pathを標準宣言より先に置く
  • WebKitの既知報告はSVG clipPath参照とstacking contextの条件を分けて再現する
  • 影は親ラッパーのfilter: drop-shadow()、clip-pathは子要素へ分ける
  • polygonアニメーションは開始と終了で頂点数を揃える
  • 親のoverflowと子のclip-pathを個別に切り分ける
  • 本質的にレイアウト計算は"クリップ前のサイズ"で行われるため、width/height/aspect-ratioで明示する

参考文献・ソース

記事作成に関する注記

本記事は AI(大規模言語モデル)を編集補助として活用して作成しています。 公開前に編集者が内容を確認していますが、事実誤認・仕様の解釈ミス・最新情報との齟齬が含まれる可能性があります。 重要な判断を行う際は、本文中の一次ソースや公式ドキュメントを必ずご自身でご確認ください。 誤りにお気づきの場合は、お問い合わせフォームよりご連絡いただけると助かります。

🔧 関連ツール

📚 関連記事