【CSS】clip-pathの使い方:図形の切り抜きと影・枠線の付け方

css-clip-path

clip-pathは、要素を任意の図形に切り抜き、Webデザインの表現の幅を広げるCSSプロパティです。

本記事では、基本図形の作り方から複雑なSVGパスの活用、影や枠線の付け方、ホバーアニメーションやレスポンシブ対応まで解説します。

また、CSSに関するカテゴリーページから学びたい内容を決めたい人は、以下のCSSページをご確認ください。

目次

clip-pathとは:図形を作る使い方

Webデザインにおいて、画像を斜めに切り取ったり、複雑な多角形を作ったりする際に欠かせないのがclip-pathプロパティです。

clip-pathプロパティを一言で表すと、「要素を好きな形にくり抜く(切り取る)ハサミ」のような機能です。

clip-pathとは:図形を作る使い方
  • circleellipseで円や楕円に切り抜く
  • polygonで多角形や吹き出しを作る
  • insetで四角形に切り抜く

circle・ellipseで円や楕円に切り抜く

プロフィール画像やサムネイルを丸く切り抜く際、正円や楕円が活躍します。

また、少し工夫するだけで半円を作ることも可能です。

単に要素を丸く見せるだけなら、処理が軽いborder-radiusを使うのが基本です。

しかし、ホバー時に波紋のように円が広がって画像が出現するといったアニメーションを実装したい場合は、border-radiusでは不可能なため、clip-path: circle()を使って円の半径をアニメーションさせるのがよいです。

⭕️ circle を使った正円と半円の切り抜き

正円
circle(50% at 50% 50%)

半円(下半分)
circle(50% at 50% 100%)

/* 💡 正円:半径50%の円を、要素のド真ん中(X50% Y50%)に配置 */
.circle {
  clip-path: circle(50% at 50% 50%);
}

/* ⭕️ 半円を作りたい時は、円の中心点をズラす */
/* 💡 半径50%の円を、下端の中央(X50% Y100%)に配置すると綺麗な半円になる */
.half-circle {
  clip-path: circle(50% at 50% 100%);
}
HTMLコード表示
<div class="cp-sec-wrapper">
  
  <p class="cp-caption">⭕️ circle を使った正円と半円の切り抜き</p>

  <div class="cp-demo-area">
    
    <div class="cp-box">
      <p class="cp-label">正円<br><small>circle(50% at 50% 50%)</small></p>
      <div class="cp-shape is-circle"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label">半円(下半分)<br><small>circle(50% at 50% 100%)</small></p>
      <div class="cp-shape is-half-circle"></div>
    </div>

  </div>

  <div class="cp-code">
    /* 💡 正円:半径50%の円を、要素のド真ん中(X50% Y50%)に配置 */<br>
    <span class="hl-blue">.circle</span> {<br>
      <span class="hl-red">clip-path: circle(50% at 50% 50%);</span><br>
    }<br><br>

    /* ⭕️ 半円を作りたい時は、円の中心点をズラす */<br>
    <span class="hl-comment">/* 💡 半径50%の円を、下端の中央(X50% Y100%)に配置すると綺麗な半円になる */</span><br>
    <span class="hl-blue">.half-circle</span> {<br>
      <span class="hl-red">clip-path: circle(50% at 50% 100%);</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-sec-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.cp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.cp-demo-area {
  display: flex;
  gap: 40px;
  justify-content: center;
  align-items: flex-end;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  line-height: 1.4;
}

.cp-shape {
  width: 100px;
  height: 100px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

/* 💡 正円 */
.is-circle {
  clip-path: circle(50% at 50% 50%);
}

/* 💡 半円(下半分だけ見せる) */
.is-half-circle {
  /* 高さを半分に見せるため、あらかじめベースを調整 */
  height: 50px;
  /* 横幅の50%の半径で、中心を下端(bottom)に持ってくる */
  clip-path: circle(50% at 50% 100%);
}

.cp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

単に要素を角丸にするためなら、border-radiusプロパティの使い方として「【CSS】角丸を作るborder-radiusの使い方:一部指定やボタン実装」を一読ください。

polygonで多角形や吹き出しを作る

clip-pathの中で自由度が高くかつよく使われるのがpolygonです。

カンマ区切りで複数の頂点の座標(X Y)を指定することで、三角形や六角形、さらには複雑な吹き出しまであらゆる直線的な図形を作成できます。

多角形を使う際の2つの条件があります。

  1. 絶対に手書きせず、ジェネレーター(Clippyなど)を使うこと。
  2. 座標はpxではなく、%(パーセント)で指定すること。
    %で指定しておけば、要素の縦横比が変わっても、図形が伸縮して形を保ってくれます。

⭕️ polygon を使った多角形(パーセント指定でレスポンシブ対応)

三角形
3つの頂点

六角形
6つの頂点

吹き出し
7つの頂点

/* 💡 頂点上(50% 0)、右下(100% 100%)、左下(0 100%)を結ぶ三角形 */
.triangle {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}

/* 💡 六角形(ハニカム構造) */
.hexagon {
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
}

/* ⭕️ 吹き出しのしっぽもpolygonでサクッと作れる */
.speech-bubble {
  clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
}
HTMLコード表示
<div class="cp-sec-wrapper">
  
  <p class="cp-caption">⭕️ polygon を使った多角形(パーセント指定でレスポンシブ対応)</p>

  <div class="cp-demo-area" style="gap: 20px;">
    
    <div class="cp-box">
      <p class="cp-label">三角形<br><small>3つの頂点</small></p>
      <div class="cp-shape is-triangle"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label">六角形<br><small>6つの頂点</small></p>
      <div class="cp-shape is-hexagon"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label">吹き出し<br><small>7つの頂点</small></p>
      <div class="cp-shape is-speech"></div>
    </div>

  </div>

  <div class="cp-code">
    /* 💡 頂点上(50% 0)、右下(100% 100%)、左下(0 100%)を結ぶ三角形 */<br>
    <span class="hl-blue">.triangle</span> {<br>
      <span class="hl-red">clip-path: polygon(50% 0%, 0% 100%, 100% 100%);</span><br>
    }<br><br>

    /* 💡 六角形(ハニカム構造) */<br>
    <span class="hl-blue">.hexagon</span> {<br>
      <span class="hl-red">clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);</span><br>
    }<br><br>

    /* ⭕️ 吹き出しのしっぽもpolygonでサクッと作れる */<br>
    <span class="hl-blue">.speech-bubble</span> {<br>
      <span class="hl-red">clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);</span><br>
    }
  </div>

</div>
CSSコード表示
/* 💡 多角形ベース */
.is-triangle {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
  background: linear-gradient(135deg, #f6d365 0%, #fda085 100%);
}

/* 💡 六角形 */
.is-hexagon {
  clip-path: polygon(25% 0%, 75% 0%, 100% 50%, 75% 100%, 25% 100%, 0% 50%);
  background: linear-gradient(135deg, #84fab0 0%, #8fd3f4 100%);
}

/* 💡 吹き出し */
.is-speech {
  /* 上半分が四角、下部にしっぽ(左から50%の位置) */
  clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
  background: linear-gradient(135deg, #fbc2eb 0%, #a6c1ee 100%);
}

insetで四角形に切り抜く

insetは、要素の上下左右の端から「どれくらい内側に向かって切り落とすか(オフセット)」を指定して、四角形に切り抜く機能です。

inset(上 右 下 左)の順で指定します。

insetの隠れた機能がroundキーワードです。

clip-path: inset(10px round 20px);と記述することで、「内側に切り抜きつつ、切り抜いた四角形に角丸をつける」ことができます。

画像ギャラリーのエフェクトなどで重宝するテクニックです。

⭕️ inset を使った写真のトリミングと、便利な角丸(round)指定

元の画像
切り抜きなし

風景画像

insetでトリミング
上下左右を20%削る

風景画像

切り抜き + 角丸
inset(20% round 15px)

風景画像
/* 💡 上・右・下・左の端から、それぞれ画像の20%ずつ内側を切り抜く */
.trim-img {
  clip-path: inset(20% 20% 20% 20%);
}

/* ⭕️ round を使えば、切り抜いた形にそのまま角丸をつけられる */
.trim-img-rounded {
  clip-path: inset(20% round 15px); /* 💡 15pxの角丸 */
}
HTMLコード表示
<div class="cp-sec-wrapper">
  
  <p class="cp-caption">⭕️ inset を使った写真のトリミングと、便利な角丸(round)指定</p>

  <div class="cp-demo-area">
    
    <div class="cp-box">
      <p class="cp-label">元の画像<br><small>切り抜きなし</small></p>
      <img src="https://picsum.photos/id/1015/400/400" alt="風景画像" class="cp-img is-original">
    </div>

    <div class="cp-box">
      <p class="cp-label">insetでトリミング<br><small>上下左右を20%削る</small></p>
      <img src="https://picsum.photos/id/1015/400/400" alt="風景画像" class="cp-img is-inset">
    </div>

    <div class="cp-box">
      <p class="cp-label" style="color:#0d6efd;">切り抜き + 角丸<br><small>inset(20% round 15px)</small></p>
      <img src="https://picsum.photos/id/1015/400/400" alt="風景画像" class="cp-img is-inset-round">
    </div>

  </div>

  <div class="cp-code">
    /* 💡 上・右・下・左の端から、それぞれ画像の20%ずつ内側を切り抜く */<br>
    <span class="hl-blue">.trim-img</span> {<br>
      <span class="hl-red">clip-path: inset(20% 20% 20% 20%);</span><br>
    }<br><br>

    /* ⭕️ round を使えば、切り抜いた形にそのまま角丸をつけられる */<br>
    <span class="hl-blue">.trim-img-rounded</span> {<br>
      <span class="hl-red">clip-path: inset(20% round 15px);</span> /* 💡 15pxの角丸 */<br>
    }
  </div>

</div>
CSSコード表示
.cp-sec-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.cp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.cp-demo-area {
  display: flex;
  gap: 30px;
  justify-content: center;
  align-items: flex-end;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  line-height: 1.4;
}

/* 💡 画像のベーススタイル */
.cp-img {
  width: 120px;
  height: 120px;
  /* 画像が歪まないようにカバーさせる */
  object-fit: cover; 
  /* 余計な背景や枠線を消す */
  background-color: transparent;
  border-radius: 0;
  box-shadow: 0 4px 10px rgba(0,0,0,0.1);
}

/* 💡 オリジナル(切り抜きなし) */
.is-original {
  clip-path: none;
}

/* 💡 周囲を20%切り落とす */
.is-inset {
  clip-path: inset(20% 20% 20% 20%);
}

/* ⭕️ 20%切り落としつつ、角を丸くする */
.is-inset-round {
  clip-path: inset(20% 20% 20% 20% round 15px);
}

/* コードブロック装飾 */
.cp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

複雑な図形!曲線・波線・SVGパスを使った切り抜き

Webデザインのトレンドにおいて、直線の多角形だけでなく、有機的な曲線や波線あるいはアイコンのような複雑なシルエットで要素を切り抜く表現が増えています。

こうした複雑なクリッピングを実現するには、CSSに直接SVGのパスデータを記述する関数、HTML上に配置したSVG要素をIDで呼び出すテクニックが必要になります。

ここでは、実務で曲線やオリジナル図形の切り抜き手法を解説します。

曲線・波線・SVGパスを使った切り抜き
  • path()を使って曲線やハート型・チェックマークを作る
  • 外部のSVGファイルを参照する

path()を使って曲線やハート型・チェックマークを作る

clip-pathには、SVGのパスデータ(d属性の値)を直接引数として渡せるpath()という関数が存在します。

これを利用すれば、曲線やベジェ曲線を駆使した波線、さらにはハート型やチェックマークといった事実上図形でもCSS1行で描画することが可能になります。

実務において、path()で指定した複雑な図形をレスポンシブに追従させるには、要素自体にaspect-ratioを指定して縦横比を固定するか、JavaScriptを使って画面幅に合わせてパスのスケールを再計算するなどの工夫が必要です。

もしくは、拡縮させたい場合は後述するurl()とSVGのobjectBoundingBoxを使う手法に切り替えるのがよいです。

⭕️ path() を使えば、どんな複雑な曲線や図形でも切り抜ける

ハート型
path() 指定

チェックマーク
path() 指定

波線(Wave)
path() 指定

/* 💡 ハート型:ベジェ曲線(CやA)を含むSVGパスをそのまま記述する */
.heart-shape {
  clip-path: path(‘M50,30 C30,0 0,20 0,50 C0,80 50,100 50,100 C50,100 100,80 100,50 C100,20 70,0 50,30 Z’);
}

/* ⭕️ path()は固定サイズ(px)になるため、要素のサイズ自体をパスに合わせる */
.wave-shape {
  width: 150px;
  height: 100px;
  clip-path: path(‘M0,0 L150,0 L150,70 Q112.5,100 75,70 T0,70 Z’);
}
HTMLコード表示
<div class="cp-path-wrapper">
  
  <p class="cp-caption">⭕️ path() を使えば、どんな複雑な曲線や図形でも切り抜ける</p>

  <div class="cp-demo-area">
    
    <div class="cp-box">
      <p class="cp-label">ハート型<br><small>path() 指定</small></p>
      <div class="cp-shape-path is-heart"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label">チェックマーク<br><small>path() 指定</small></p>
      <div class="cp-shape-path is-check"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label">波線(Wave)<br><small>path() 指定</small></p>
      <div class="cp-shape-path is-wave" style="width: 150px; height: 100px;"></div>
    </div>

  </div>

  <div class="cp-code">
    /* 💡 ハート型:ベジェ曲線(CやA)を含むSVGパスをそのまま記述する */<br>
    <span class="hl-blue">.heart-shape</span> {<br>
      <span class="hl-red">clip-path: path('M50,30 C30,0 0,20 0,50 C0,80 50,100 50,100 C50,100 100,80 100,50 C100,20 70,0 50,30 Z');</span><br>
    }<br><br>

    /* ⭕️ path()は固定サイズ(px)になるため、要素のサイズ自体をパスに合わせる */<br>
    <span class="hl-blue">.wave-shape</span> {<br>
      <span class="hl-green">width: 150px;</span><br>
      <span class="hl-green">height: 100px;</span><br>
      <span class="hl-red">clip-path: path('M0,0 L150,0 L150,70 Q112.5,100 75,70 T0,70 Z');</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-path-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.cp-demo-area {
  display: flex;
  gap: 30px;
  justify-content: center;
  align-items: flex-end;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-shape-path {
  width: 100px;
  height: 100px;
  background: linear-gradient(135deg, #ff9a9e 0%, #fecfef 99%, #fecfef 100%);
}

/* 💡 ハート型のパス */
.is-heart {
  clip-path: path('M50,30 C30,0 0,20 0,50 C0,80 50,100 50,100 C50,100 100,80 100,50 C100,20 70,0 50,30 Z');
  background: linear-gradient(135deg, #ff0844 0%, #ffb199 100%);
}

/* 💡 チェックマークのパス */
.is-check {
  clip-path: path('M20,50 L40,70 L80,30 L70,20 L40,50 L30,40 Z');
  background: linear-gradient(135deg, #0ba360 0%, #3cba92 100%);
}

/* 💡 波線(Wave)のパス ※幅150px想定 */
.is-wave {
  width: 150px;
  clip-path: path('M0,0 L150,0 L150,70 Q112.5,100 75,70 T0,70 Z');
  background: linear-gradient(135deg, #89f7fe 0%, #66a6ff 100%);
}

外部のSVGファイルを参照する

複雑な図形やレスポンシブに対応させたい場合は、HTML上に<svg><clipPath>タグを配置し、CSS側からclip-path: url(#ID名)で参照します。

この手法の利点は、文字の形(テキスト)で画像を切り抜くようなCSS単体では不可能なグラフィック表現ができることです。

SVGは外部ファイル化せず、HTML内に直接インラインで記述します。

レスポンシブで要素の幅に合わせて図形を伸縮させたい場合は、<clipPath clipPathUnits="objectBoundingBox"> を指定し、パスの座標を01.0の比率に変換して記述します。

⭕️ url(#id) を使えば、レスポンシブ対応や「文字の形での切り抜き」が可能

OCEAN

レスポンシブな波線
幅が伸びても綺麗に変形する

テキストクリップ
画像が文字の形で切り抜かれる

海
/* 💡 HTML内に配置したSVGのID(#responsive-wave)を参照する */
.responsive-box {
  width: 100%;
  clip-path: url(#responsive-wave);
}

/* ⭕️ 画像に対して「SVGテキストのID」を参照すれば、文字型に切り抜ける */
.image-text {
  clip-path: url(#text-clip);
}
HTMLコード表示
<div class="cp-svg-wrapper">
  
  <p class="cp-caption">⭕️ url(#id) を使えば、レスポンシブ対応や「文字の形での切り抜き」が可能</p>

  <div class="cp-demo-area" style="flex-direction: column; gap: 40px;">
    
    <svg width="0" height="0" style="position: absolute; pointer-events: none;">
      <defs>
        <clipPath id="responsive-wave" clipPathUnits="objectBoundingBox">
          <path d="M0,0 L1,0 L1,0.7 C0.75,1 0.25,1 0,0.7 Z" />
        </clipPath>
        
        <clipPath id="text-clip">
          <text x="200" y="105" text-anchor="middle" style="font-size: 100px; font-weight: 900; font-family: 'Arial', sans-serif; letter-spacing: 5px;">OCEAN</text>
        </clipPath>
      </defs>
    </svg>

    <div class="cp-box" style="width: 100%;">
      <p class="cp-label">レスポンシブな波線<br><small>幅が伸びても綺麗に変形する</small></p>
      <div class="cp-shape-svg is-svg-wave"></div>
    </div>

    <div class="cp-box" style="width: 100%;">
      <p class="cp-label">テキストクリップ<br><small>画像が文字の形で切り抜かれる</small></p>
      <img src="https://picsum.photos/id/1015/600/300" alt="海" class="cp-shape-svg is-svg-text">
    </div>

  </div>

  <div class="cp-code">
    /* 💡 HTML内に配置したSVGのID(#responsive-wave)を参照する */<br>
    <span class="hl-blue">.responsive-box</span> {<br>
      <span class="hl-green">width: 100%;</span><br>
      <span class="hl-red">clip-path: url(#responsive-wave);</span><br>
    }<br><br>

    /* ⭕️ 画像に対して「SVGテキストのID」を参照すれば、文字型に切り抜ける */<br>
    <span class="hl-blue">.image-text</span> {<br>
      <span class="hl-red">clip-path: url(#text-clip);</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-svg-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
  position: relative;
}

.cp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.cp-demo-area {
  display: flex;
  align-items: center;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  line-height: 1.4;
}

/* 💡 波線のスタイル */
.is-svg-wave {
  width: 100%;
  height: 120px;
  background: linear-gradient(135deg, #00c6ff 0%, #0072ff 100%);
  clip-path: url(#responsive-wave);
}

/* 💡 テキストクリップのスタイル */
.is-svg-text {
  /* ⭕️ 文字を大きくした分、切り抜かれる画像本体も大きくする */
  /* SVGの x="200" と中央が合うように、横幅を 400px に固定 */
  width: 400px;
  height: 140px;
  object-fit: cover;
  clip-path: url(#text-clip);
  display: block;
  margin: 0 auto;
}

/* コードブロック装飾 */
.cp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }

切り抜いた要素に影や枠線をつける

clip-pathの基本をマスターし、実務のプロジェクトで使い始めると、直面する大きな壁があります。

「切り抜いた図形に影をつけたい」「切り抜いた形に沿って枠線を引きたい」「多角形の角を少しだけ丸くしたい」という、デザイン上の追加要望です。

実は、clip-pathには仕様上、これらの装飾が適用できないという厄介な特徴があります。

切り抜いた要素に影や枠線をつける
  • 影にはfilter: drop-shadowを使う
  • 切り抜いた形に合わせて枠線をつける
  • 多角形の角を丸くする

影にはfilter: drop-shadowを使う

clip-pathで切り抜いた要素に対して、CSS標準の影付けプロパティであるbox-shadowを指定しても、影は表示されません。

切り抜いた形に沿った影を落としたい場合は「影をつけるための親要素」を作り、filter: drop-shadow()を適用するのがよいです。

ブラウザは「子要素の切り抜かれた最終的なシルエット」を親要素側で検知し、シルエットに対して影を落としてくれます。

⭕️ 影(shadow)は、要素自身ではなく「親要素」に drop-shadow をかける

❌ box-shadow
(影も一緒に切り取られる)

⭕️ drop-shadow
(親要素にかけるのが正解)

/* ❌ 切り抜かれた要素自身に影をつけると見えなくなる */
.hexagon-wrong {
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  box-shadow: 0 10px 15px rgba(0,0,0,0.5); /* 💡 一切表示されない */
}

/* ⭕️ 影用の親div(ラッパー)を作り、そこに drop-shadow をかける */
.hexagon-wrapper {
  filter: drop-shadow(0 10px 10px rgba(0,0,0,0.4));
}
.hexagon-inner {
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
}
HTMLコード表示
<div class="cp-sec-wrapper">
  
  <p class="cp-caption">⭕️ 影(shadow)は、要素自身ではなく「親要素」に drop-shadow をかける</p>

  <div class="cp-demo-area">
    
    <div class="cp-box">
      <p class="cp-label">❌ box-shadow<br><small>(影も一緒に切り取られる)</small></p>
      <div class="cp-shape-shadow is-wrong"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label" style="color:#0d6efd;">⭕️ drop-shadow<br><small>(親要素にかけるのが正解)</small></p>
      <div class="cp-shadow-wrapper">
        <div class="cp-shape-shadow is-correct"></div>
      </div>
    </div>

  </div>

  <div class="cp-code">
    /* ❌ 切り抜かれた要素自身に影をつけると見えなくなる */<br>
    <span class="hl-blue">.hexagon-wrong</span> {<br>
      <span class="hl-green">clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);</span><br>
      <span class="hl-red">box-shadow: 0 10px 15px rgba(0,0,0,0.5);</span> /* 💡 一切表示されない */<br>
    }<br><br>

    /* ⭕️ 影用の親div(ラッパー)を作り、そこに drop-shadow をかける */<br>
    <span class="hl-blue">.hexagon-wrapper</span> {<br>
      <span class="hl-red">filter: drop-shadow(0 10px 10px rgba(0,0,0,0.4));</span><br>
    }<br>
    <span class="hl-blue">.hexagon-inner</span> {<br>
      <span class="hl-green">clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-sec-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.cp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.cp-demo-area {
  display: flex;
  gap: 50px;
  justify-content: center;
  align-items: flex-end;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  line-height: 1.4;
}

/* ベースの六角形 */
.cp-shape-shadow {
  width: 100px;
  height: 100px;
  background: linear-gradient(135deg, #f6d365 0%, #fda085 100%);
}

/* ❌ 失敗パターン */
.is-wrong {
  clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
  box-shadow: 0 20px 20px rgba(0,0,0,1); /* わざと濃くしても見えない */
}

/* ⭕️ 成功パターン(親ラッパー) */
.cp-shadow-wrapper {
  /* 親要素にdrop-shadowをかける */
  filter: drop-shadow(0 10px 10px rgba(0,0,0,0.4));
}

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

/* コードブロック装飾 */
.cp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }

box-shadowプロパティの使い方を詳しく知りたい人は「【CSS】box-shadowの使い方:おしゃれな影のコピペ集と浮遊感の作り方」を一読ください。

切り抜いた形に合わせて枠線をつける

多角形などの複雑な図形に切り抜いた後、枠線をつけたいという要望も多いです。

枠線を実現するのは、「同じclip-pathを持った親要素と子要素を重ね、親要素にpaddingで枠線の太さを作る」手法です。

親要素の背景色が枠線の色になり、子要素の背景色が本体の色になります。

座標を%で指定していれば、paddingによって子要素の幅が変わっても、図形は崩れることなく枠線を描き出します。

⭕️ 親子で同じ図形に切り抜き、親の padding を「枠線の太さ」として利用する

❌ 普通のborder
(外枠の四角につく)

TEXT

⭕️ 二重clip-path
(形に沿った完璧な枠線)

TEXT
/* ❌ 普通のborderは切り抜く前の四角い箱についてしまう */
.polygon-wrong {
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  border: 4px solid #0d6efd;
}

/* ⭕️ 親要素のpaddingを枠線の太さに、背景色を枠線の色にする */
.border-parent {
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  background-color: #0d6efd; /* 💡 これが枠線の色になる */
  padding: 4px; /* 💡 これが枠線の太さになる */
}

/* 💡 子要素も同じ形で切り抜き、本体の色を設定する */
.border-child {
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  background-color: #fff;
  height: 100%;
}
HTMLコード表示
<div class="cp-sec-wrapper">
  
  <p class="cp-caption">⭕️ 親子で同じ図形に切り抜き、親の padding を「枠線の太さ」として利用する</p>

  <div class="cp-demo-area">
    
    <div class="cp-box">
      <p class="cp-label">❌ 普通のborder<br><small>(外枠の四角につく)</small></p>
      <div class="cp-shape-border is-wrong">TEXT</div>
    </div>

    <div class="cp-box">
      <p class="cp-label" style="color:#0d6efd;">⭕️ 二重clip-path<br><small>(形に沿った完璧な枠線)</small></p>
      
      <div class="cp-border-parent">
        <div class="cp-border-child">TEXT</div>
      </div>
    </div>

  </div>

  <div class="cp-code">
    /* ❌ 普通のborderは切り抜く前の四角い箱についてしまう */<br>
    <span class="hl-blue">.polygon-wrong</span> {<br>
      <span class="hl-green">clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);</span><br>
      <span class="hl-red">border: 4px solid #0d6efd;</span><br>
    }<br><br>

    /* ⭕️ 親要素のpaddingを枠線の太さに、背景色を枠線の色にする */<br>
    <span class="hl-blue">.border-parent</span> {<br>
      <span class="hl-green">clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);</span><br>
      <span class="hl-red">background-color: #0d6efd;</span> /* 💡 これが枠線の色になる */<br>
      <span class="hl-red">padding: 4px;</span> /* 💡 これが枠線の太さになる */<br>
    }<br><br>

    /* 💡 子要素も同じ形で切り抜き、本体の色を設定する */<br>
    <span class="hl-blue">.border-child</span> {<br>
      <span class="hl-green">clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);</span><br>
      <span class="hl-green">background-color: #fff;</span><br>
      <span class="hl-green">height: 100%;</span><br>
    }
  </div>

</div>
CSSコード表示
/* ❌ 失敗パターン */
.cp-shape-border.is-wrong {
  width: 100px;
  height: 100px;
  background-color: #fff;
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  border: 4px solid #0d6efd; /* 外枠につくため切り落とされるか四角く見える */
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
}

/* ⭕️ 成功パターン(親要素) */
.cp-border-parent {
  width: 100px;
  height: 100px;
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  background-color: #0d6efd; /* 枠線の色 */
  padding: 4px; /* 枠線の太さ */
}

/* ⭕️ 成功パターン(子要素) */
.cp-border-child {
  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
  background-color: #fff; /* 本体の背景色 */
  height: 100%; /* 親のpadding内をいっぱいに広げる */
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  color: #333;
}

多角形の角を丸くする

多角形の角を丸くするのは、デザイナーから要求されるにもかかわらず、実装者を絶望させる仕様です。

現在のCSSの仕様では、polygon()関数で作られた図形の頂点を直接丸くするプロパティは存在しません。

実務で多角形の角を丸くしたい場合は、polygon()を使うのをやめ、FigmaやIllustratorなどのデザインツールで「角丸の多角形」を作り、そこから書き出したSVGのpath()clip-pathに指定するのが確実な解決策です。

⭕️ polygonの角はCSSでは丸くならない!角丸には必ず path() を使う

❌ polygon + border-radius
(角は鋭いまま)

⭕️ SVG path()
(美しい角丸になる)

/* ❌ polygonで切り抜いた図形にborder-radiusをかけても無意味 */
.triangle-wrong {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
  border-radius: 20px; /* 💡 頂点には全く効かない */
}

/* ⭕️ Figma等で角丸にした図形のSVGパス(ベジェ曲線を含む)を使用する */
.triangle-rounded {
  clip-path: path(‘M45,5 Q50,0 55,5 L95,80 Q100,90 90,90 L10,90 Q0,90 5,80 Z’);
}
HTMLコード表示
<div class="cp-sec-wrapper">
  
  <p class="cp-caption">⭕️ polygonの角はCSSでは丸くならない!角丸には必ず path() を使う</p>

  <div class="cp-demo-area">
    
    <div class="cp-box">
      <p class="cp-label">❌ polygon + border-radius<br><small>(角は鋭いまま)</small></p>
      <div class="cp-shape-round is-wrong"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label" style="color:#0d6efd;">⭕️ SVG path()<br><small>(美しい角丸になる)</small></p>
      <div class="cp-shape-round is-correct"></div>
    </div>

  </div>

  <div class="cp-code">
    /* ❌ polygonで切り抜いた図形にborder-radiusをかけても無意味 */<br>
    <span class="hl-blue">.triangle-wrong</span> {<br>
      <span class="hl-green">clip-path: polygon(50% 0%, 0% 100%, 100% 100%);</span><br>
      <span class="hl-red">border-radius: 20px;</span> /* 💡 頂点には全く効かない */<br>
    }<br><br>

    /* ⭕️ Figma等で角丸にした図形のSVGパス(ベジェ曲線を含む)を使用する */<br>
    <span class="hl-blue">.triangle-rounded</span> {<br>
      <span class="hl-red">clip-path: path('M45,5 Q50,0 55,5 L95,80 Q100,90 90,90 L10,90 Q0,90 5,80 Z');</span><br>
    }
  </div>

</div>
CSSコード表示
/* ベースの図形サイズ */
.cp-shape-round {
  width: 100px;
  height: 100px;
  background: linear-gradient(135deg, #11998e 0%, #38ef7d 100%);
}

/* ❌ polygon と border-radius(効かない) */
.cp-shape-round.is-wrong {
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
  border-radius: 20px;
}

/* ⭕️ SVG path() を使った角丸三角形 */
/* (Q = 2次ベジェ曲線を使って角を滑らかにしているパスデータ) */
.cp-shape-round.is-correct {
  clip-path: path('M45,5 Q50,0 55,5 L95,80 Q100,90 90,90 L10,90 Q0,90 5,80 Z');
}

反転・アニメーション・レスポンシブ対応

「特定の形に穴を開けたい」「ホバーした時に形を滑らかに変えたい」「スマホとPCで形が崩れないようにしたい」といった要件は、CSSの仕様を正しく理解していないとつまずきます。

ここでは、現場で使う解決策を解説します。

反転・アニメーション・レスポンシブ対応
  • 切り抜きの反転とmask-imageとの違い
  • ホバー時の変形などclip-pathのアニメーション
  • calc()%を使って画面幅に合わせてレスポンシブに可変させる

切り抜きの反転とmask-imageとの違い

図形を残すのではなく、「図形の形に穴を開けたい」という要望は実務で多く発生します。

特に、スポットライトのように真ん中だけをくり抜くのが定番です。

要素に「穴を開ける(反転する)」場合、無理にclip-pathを使いません。

代わりに、mask-imageプロパティを使用します。

mask-imageradial-gradient(円形グラデーション)を組み合わせることで、指定した部分だけを透明にし、それ以外を残すという「反転(穴あき)」を1行で実現できます。

⭕️ clip-pathでの「中抜き(反転)」の限界と、mask-imageによる完璧な穴あけ

四角い穴
polygon一筆書き

丸い穴(反転)
mask-imageを使用

/* 💡 clip-pathで四角い穴を開ける(外周を描いてから、内側を描く一筆書き) */
.polygon-hole {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 0%, 20% 20%, 20% 80%, 80% 80%, 80% 20%, 20% 20%);
}

/* ⭕️ 丸く反転(穴あけ)させたい時は mask-image を使う */
.mask-hole {
  /* 💡 中心50pxを透明(transparent)にし、それ以外を黒(可視)にする */
  -webkit-mask-image: radial-gradient(circle at center, transparent 30px, black 31px);
  mask-image: radial-gradient(circle at center, transparent 30px, black 31px);
}
HTMLコード表示
<div class="cp-tech-wrapper">
  
  <p class="cp-caption">⭕️ clip-pathでの「中抜き(反転)」の限界と、mask-imageによる完璧な穴あけ</p>

  <div class="cp-demo-area" style="background: repeating-linear-gradient(45deg, #ccc, #ccc 10px, #eee 10px, #eee 20px);">
    
    <div class="cp-box">
      <p class="cp-label" style="background:#fff; padding:2px 5px;">四角い穴<br><small>polygon一筆書き</small></p>
      <div class="cp-shape-invert is-polygon-hole"></div>
    </div>

    <div class="cp-box">
      <p class="cp-label" style="color:#0d6efd; background:#fff; padding:2px 5px;">丸い穴(反転)<br><small>mask-imageを使用</small></p>
      <div class="cp-shape-invert is-mask-hole"></div>
    </div>

  </div>

  <div class="cp-code">
    /* 💡 clip-pathで四角い穴を開ける(外周を描いてから、内側を描く一筆書き) */<br>
    <span class="hl-blue">.polygon-hole</span> {<br>
      <span class="hl-red">clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 0%, 20% 20%, 20% 80%, 80% 80%, 80% 20%, 20% 20%);</span><br>
    }<br><br>

    /* ⭕️ 丸く反転(穴あけ)させたい時は mask-image を使う */<br>
    <span class="hl-blue">.mask-hole</span> {<br>
      <span class="hl-comment">/* 💡 中心50pxを透明(transparent)にし、それ以外を黒(可視)にする */</span><br>
      <span class="hl-red">-webkit-mask-image: radial-gradient(circle at center, transparent 30px, black 31px);</span><br>
      <span class="hl-red">mask-image: radial-gradient(circle at center, transparent 30px, black 31px);</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-tech-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.cp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.cp-demo-area {
  display: flex;
  gap: 50px;
  justify-content: center;
  align-items: center;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  line-height: 1.4;
  border-radius: 4px;
}

/* ベースの要素(穴がわかりやすいように濃い色) */
.cp-shape-invert {
  width: 120px;
  height: 120px;
  background-color: #343a40;
}

/* 💡 polygonで四角い穴 */
.is-polygon-hole {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%, 0% 0%, 25% 25%, 25% 75%, 75% 75%, 75% 25%, 25% 25%);
}

/* ⭕️ mask-imageで丸い穴(反転) */
.is-mask-hole {
  -webkit-mask-image: radial-gradient(circle at center, transparent 35px, black 36px);
  mask-image: radial-gradient(circle at center, transparent 35px, black 36px);
}

.cp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

ホバー時の変形などclip-pathのアニメーション

clip-pathのアニメーションは、Webサイトにダイナミックな動きを持たせる手法です。

例えば、斜めにカットされた画像をホバーすると四角形に戻る、といった表現はモダンなサイトで頻出します。

clip-path: polygon()をアニメーション(滑らかにモーフィング)させる条件は、「変形前と変形後で、頂点の数(座標の数)を一致させること」です。

例えば、三角形から四角形に変形させたい場合は、四角形を基準(4点)とし、変形前の三角形の座標を「3点」ではなく「2つの点が同じ位置に重なっている4点」として定義します。

これにより、ブラウザが座標の移動を計算できるようになり、滑らかなアニメーションが実現します。

⭕️ アニメーションの鉄則:変形前と変形後で「関数の種類・頂点の数」を一致させる

❌ 頂点数が違う
(ホバーで一瞬で切り替わる)

HOVER

⭕️ 頂点数が同じ
(滑らかに変形する)

HOVER

💡 実務の定番デザイン
(正円の画像をホバーで四角形に戻す)

風景
/* ❌ 3点の三角形から4点の四角形への変形(アニメーションしない) */
.anim-wrong {
  transition: clip-path 0.4s ease;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%); /* 💡 3つの点 */
}
.anim-wrong:hover {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%); /* 💡 4つの点 */
}

/* ⭕️ 四角形(4点)に変形させるなら、初期状態も「4点」で構成する */
.anim-correct {
  transition: clip-path 0.4s ease;
  clip-path: polygon(50% 0%, 50% 0%, 100% 100%, 0% 100%); /* 💡 上が重なった4点 */
}
.anim-correct:hover {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
}

/* 💡 circle()からpolygon()への変形はできない! inset() を使う */
.image-anim {
  transition: clip-path 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
  /* 💡 切り落とし0%で、角丸(round)を50%にして「正円」を作る */
  clip-path: inset(0% round 50%);
}
.image-anim:hover {
  /* 💡 同じinset関数のまま、角丸を0pxにして「四角形」に戻す(滑らかに動く!) */
  clip-path: inset(0% round 0px);
}
HTMLコード表示
<div class="cp-tech-wrapper">
  
  <p class="cp-caption">⭕️ アニメーションの鉄則:変形前と変形後で「関数の種類・頂点の数」を一致させる</p>

  <div class="cp-demo-area" style="flex-wrap: wrap; gap: 30px;">
    
    <div class="cp-box">
      <p class="cp-label">❌ 頂点数が違う<br><small>(ホバーで一瞬で切り替わる)</small></p>
      <div class="cp-shape-anim is-wrong-anim">HOVER</div>
    </div>

    <div class="cp-box">
      <p class="cp-label" style="color:#0d6efd;">⭕️ 頂点数が同じ<br><small>(滑らかに変形する)</small></p>
      <div class="cp-shape-anim is-correct-anim">HOVER</div>
    </div>

    <div class="cp-box" style="width: 100%; max-width: 300px; margin-top: 10px;">
      <p class="cp-label" style="color:#e83e8c;">💡 実務の定番デザイン<br><small>(正円の画像をホバーで四角形に戻す)</small></p>
      <img src="https://picsum.photos/id/1043/400/400" alt="風景" class="cp-shape-anim is-image-anim">
    </div>

  </div>

  <div class="cp-code">
    /* ❌ 3点の三角形から4点の四角形への変形(アニメーションしない) */<br>
    <span class="hl-blue">.anim-wrong</span> {<br>
      <span class="hl-green">transition: clip-path 0.4s ease;</span><br>
      <span class="hl-red">clip-path: polygon(50% 0%, 0% 100%, 100% 100%);</span> /* 💡 3つの点 */<br>
    }<br>
    <span class="hl-blue">.anim-wrong:hover</span> {<br>
      <span class="hl-red">clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);</span> /* 💡 4つの点 */<br>
    }<br><br>

    /* ⭕️ 四角形(4点)に変形させるなら、初期状態も「4点」で構成する */<br>
    <span class="hl-blue">.anim-correct</span> {<br>
      <span class="hl-green">transition: clip-path 0.4s ease;</span><br>
      <span class="hl-red">clip-path: polygon(50% 0%, 50% 0%, 100% 100%, 0% 100%);</span> /* 💡 上が重なった4点 */<br>
    }<br>
    <span class="hl-blue">.anim-correct:hover</span> {<br>
      <span class="hl-red">clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);</span><br>
    }<br><br>

    /* 💡 circle()からpolygon()への変形はできない! inset() を使う */<br>
    <span class="hl-blue">.image-anim</span> {<br>
      <span class="hl-green">transition: clip-path 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);</span><br>
      <span class="hl-comment">/* 💡 切り落とし0%で、角丸(round)を50%にして「正円」を作る */</span><br>
      <span class="hl-red">clip-path: inset(0% round 50%);</span><br>
    }<br>
    <span class="hl-blue">.image-anim:hover</span> {<br>
      <span class="hl-comment">/* 💡 同じinset関数のまま、角丸を0pxにして「四角形」に戻す(滑らかに動く!) */</span><br>
      <span class="hl-red">clip-path: inset(0% round 0px);</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-tech-wrapper {
  background-color: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  border: 1px solid #dee2e6;
}

.cp-caption {
  font-size: 13px;
  font-weight: bold;
  margin-bottom: 20px;
  color: #198754;
  text-align: center;
}

.cp-demo-area {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #e9ecef;
  padding: 40px 20px;
  border-radius: 4px;
  border: 1px dashed #adb5bd;
  margin-bottom: 20px;
}

.cp-box {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.cp-label {
  font-size: 12px;
  font-weight: bold;
  margin-bottom: 15px;
  color: #333;
  text-align: center;
  line-height: 1.4;
}

/* アニメーション用のベース設定 */
.cp-shape-anim {
  width: 120px;
  height: 120px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: bold;
  cursor: pointer;
  /* 滑らかなアニメーション設定 */
  transition: clip-path 0.5s cubic-bezier(0.25, 0.8, 0.25, 1);
}

/* ❌ 失敗:3点から4点へ */
.is-wrong-anim {
  background-color: #fd7e14;
  color: white;
  clip-path: polygon(50% 0%, 0% 100%, 100% 100%); /* 3点 */
}
.is-wrong-anim:hover {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%); /* 4点(パチッと切り替わる) */
}

/* ⭕️ 成功:4点から4点へ */
.is-correct-anim {
  background-color: #20c997;
  color: white;
  clip-path: polygon(50% 0%, 50% 0%, 100% 100%, 0% 100%); /* 上が重なった4点 */
}
.is-correct-anim:hover {
  clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%); /* 綺麗な四角形へ */
}

/* 💡 実務の定番:正円から四角形へのアニメーション */
.is-image-anim {
  /* 綺麗な正方形(1:1)をベースにする */
  width: 200px;
  height: 200px;
  object-fit: cover;
  
  /* 💡 `circle()` ではなく、`inset()` で角を50%丸めて正円を作るのがプロの鉄則 */
  clip-path: inset(0% round 50%);
  
  /* 少しズームアウトさせる動きも入れるとリッチになります */
  transform: scale(1.05);
  transition: clip-path 0.5s cubic-bezier(0.25, 0.8, 0.25, 1), transform 0.5s ease;
}

.is-image-anim:hover {
  /* 💡 同じ `inset()` のまま、角丸を0にして完全な四角形に戻す */
  clip-path: inset(0% round 0px);
  transform: scale(1);
}

/* コードブロック装飾 */
.cp-code {
  background-color: #282c34;
  color: #abb2bf;
  padding: 15px;
  border-radius: 4px;
  font-family: monospace;
  font-size: 13px;
  line-height: 1.6;
  border-left: 4px solid #0d6efd;
}

.hl-blue { color: #61afef; font-weight: bold; }
.hl-red { color: #e06c75; font-weight: bold; }
.hl-green { color: #98c379; font-weight: bold; }
.hl-comment { color: #6c757d; font-style: italic; }

calc()や%を使って画面幅に合わせてレスポンシブに可変させる

スマホからPCまで、画面幅に合わせて図形を伸縮させるレスポンシブ対応は必須です。

基本的には%を使えば解決すると思われがちですが、「特定の角だけを一定のサイズでカットしたい」といった精密なデザインを%だけで組むと問題が発生します。

レスポンシブ対応において「サイズを固定したい部分」と「伸縮させたい部分」が混在している場合は、calc()関数を組み合わせて使うのがよいです。

clip-path: polygon(0 0, 100% 0, 100% calc(100% - 30px), calc(100% - 30px) 100%, 0 100%)のように指定すれば、どれだけ要素の幅が変わっても、カットされる部分は常に「45度の30px」を保つことができます。

なお、切り抜き要素がはみ出す場合のoverflow制御は、親要素側で管理します。

⭕️ レスポンシブ対応! calc() を使って特定の角度・サイズを固定する

❌ %だけで指定
(幅が伸びるとカットの角度が歪む)

横長の画面
縦長の画面

⭕️ calc()でpx固定
(幅が伸びても常に45度で30pxのカット)

横長の画面
縦長の画面
/* ❌ 右下を 20% 削る(要素の縦横比によって角度がグチャグチャに歪む) */
.cut-wrong {
  clip-path: polygon(0 0, 100% 0, 100% 80%, 80% 100%, 0 100%);
}

/* ⭕️ calc() を使い、「100%の位置から 30px 戻った位置」を指定する */
.cut-correct {
  clip-path: polygon(0 0, 100% 0, 100% calc(100% – 30px), calc(100% – 30px) 100%, 0 100%);
}
HTMLコード表示
<div class="cp-tech-wrapper">
  
  <p class="cp-caption">⭕️ レスポンシブ対応! calc() を使って特定の角度・サイズを固定する</p>

  <div class="cp-demo-area" style="flex-direction: column; align-items: stretch;">
    
    <div class="cp-box" style="align-items: flex-start;">
      <p class="cp-label">❌ %だけで指定<br><small>(幅が伸びるとカットの角度が歪む)</small></p>
      <div class="cp-shape-calc is-wrong-calc" style="width: 100%;">横長の画面</div>
      <div class="cp-shape-calc is-wrong-calc" style="width: 40%;">縦長の画面</div>
    </div>

    <hr style="width:100%; border:0; border-top:1px dashed #adb5bd; margin: 10px 0;">

    <div class="cp-box" style="align-items: flex-start;">
      <p class="cp-label" style="color:#0d6efd;">⭕️ calc()でpx固定<br><small>(幅が伸びても常に45度で30pxのカット)</small></p>
      <div class="cp-shape-calc is-correct-calc" style="width: 100%; background-color:#0d6efd;">横長の画面</div>
      <div class="cp-shape-calc is-correct-calc" style="width: 40%; background-color:#0d6efd;">縦長の画面</div>
    </div>

  </div>

  <div class="cp-code">
    /* ❌ 右下を 20% 削る(要素の縦横比によって角度がグチャグチャに歪む) */<br>
    <span class="hl-blue">.cut-wrong</span> {<br>
      <span class="hl-red">clip-path: polygon(0 0, 100% 0, 100% 80%, 80% 100%, 0 100%);</span><br>
    }<br><br>

    /* ⭕️ calc() を使い、「100%の位置から 30px 戻った位置」を指定する */<br>
    <span class="hl-blue">.cut-correct</span> {<br>
      <span class="hl-red">clip-path: polygon(0 0, 100% 0, 100% calc(100% - 30px), calc(100% - 30px) 100%, 0 100%);</span><br>
    }
  </div>

</div>
CSSコード表示
.cp-shape-calc {
  height: 60px;
  background-color: #6c757d;
  color: white;
  display: flex;
  align-items: center;
  padding-left: 20px;
  font-weight: bold;
  margin-bottom: 10px;
  font-size: 14px;
}

/* ❌ 失敗:%による右下カット */
.is-wrong-calc {
  /* 幅に対して20%を削るため、横長だと長く削られ、縦長だと短く削られる(角度が安定しない) */
  clip-path: polygon(0 0, 100% 0, 100% 80%, 80% 100%, 0 100%);
}

/* ⭕️ 成功:calc()による30px固定の右下カット */
.is-correct-calc {
  /* X軸・Y軸ともに、端(100%)からきっちり30px戻った座標を結ぶため、常に45度の面取りになる */
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - 30px), calc(100% - 30px) 100%, 0 100%);
}

まとめ

分かりやすいようにまとめを記載します。

本記事のまとめ
  • clip-pathは要素を特定の図形に切り抜くプロパティである。
  • circle()ellipse()で円形、polygon()で多角形、inset()で四角形に切り抜ける。
  • inset()roundキーワードを付与することで、切り抜きと同時に角丸を指定できる。
  • polygon()の座標指定はpxではなく%を使用し、レスポンシブ時の形状崩れを防ぐ。
  • path()関数を利用すると、ベジェ曲線を含む複雑な図形を描画できるが、基本は絶対値(px)指定となる。
  • HTML内に配置したSVGのIDをurl(#id)で参照することで、文字の形での切り抜きや比率(objectBoundingBox)を用いたレスポンシブなパスの適用が可能になる。
  • clip-pathを適用した要素自身に指定したbox-shadowborderは、図形の外側として切り落とされる。
  • 切り抜いた図形に影をつける場合は、親要素に対してfilter: drop-shadow()を指定する。
  • 切り抜いた図形に枠線をつける場合は、親要素に同じclip-pathと背景色、padding(枠線の太さ)を設定し、子要素を入れ子にする。
  • polygon()で作った多角形の角をCSSのみで丸くすることはできないため、角丸図形にはSVGのpath()を使用する。
  • 図形を反転して穴を開ける表現には、clip-pathではなくmask-imageを使用する。
  • アニメーション(transition)を適用するには、変形前と変形後で「関数の種類」と「頂点の数」を一致させる必要がある。
  • 角の面取りなど、特定のサイズを固定したまま要素全体をレスポンシブ対応させるには、%calc()を組み合わせる。

よくある質問(FAQ)

CSSのclip-pathとは何ですか?

Webサイト上の要素を、円や多角形、波線など好きな図形の形に「切り抜いて表示する」CSSプロパティです。

画像加工ソフトを使わずに、CSSのコードだけで斜めカットのデザインや複雑なシルエットを作り出すことができます。

clip-pathはすべてのブラウザで使えますか?

現在、Chrome、Safari、Edge、Firefoxといった主要なモダンブラウザ(スマホ環境含む)で標準サポートされており、実務でも問題なく使用できます。

Internet Explorer(IE)では動作しませんが、すでにサポートが終了しているため、現代のWeb制作において使用を控える理由にはなりません。

clip-pathで切り抜いた図形に枠線や影がつきません。

clip-pathは「指定した図形以外の部分をすべて見えなくする」仕様のため、要素自身に指定したborderや外側に広がるbox-shadowも一緒に切り落とされます。

影をつけたい場合は、親要素を用意してfilter: drop-shadow()を適用してください。

枠線をつけたい場合は、親要素にも同じclip-pathと背景色を指定し、paddingの数値を使って枠線の太さを表現するのが一般的です。

多角形の角を少しだけ丸くすることはできますか?

残念ながら、CSSの仕様上clip-path: polygon()で作った図形の頂点に対して、border-radiusを効かせて角を丸くすることはできません。

角丸の多角形を作りたい場合は、FigmaやIllustratorなどのデザインツールで角丸の図形を作成し、書き出した SVGパス(path('...'))をclip-pathに適用するのが確実な解決策です。

ホバー時のアニメーションが滑らかに動かず、一瞬で形が切り替わってしまいます。

clip-pathtransition等で滑らかに変形させる条件は、「変形前と変形後で、座標の数を一致させること」です。

例えば、三角形から四角形に変形させたい場合、初期状態の三角形を「3つの点」ではなく「2つの点が重なる4つの点」として定義しておくことで、ブラウザが動きを計算でき、滑らかなアニメーションが実現します。

この記事を書いた人

sugiのアバター sugi Site operator

【経歴】玉川大学工学部卒業→新卒SIer企業入社→2年半後に独立→プログラミングスクール運営/受託案件→フリーランスエンジニア&SEOコンサル→Python特化のコンテンツサイトJob Code&UIコピペサイトCode Stock運営中

目次