CSSのoverflowで、角丸の親から画像がはみ出すのを防ぐ方法
親の要素に border-radius を付けて角を丸くしても、中に入れた画像の角は四角いまま、丸みの外にはみ出して表示されます。親に overflow: hidden か overflow: clip を付けると、画像は親の丸みに沿って切り取られます。記事一覧やブログのカード、商品のサムネイル付きのカードなど、上半分に写真を置いた角丸の枠を作るときの直し方です。ふつうのカードなら、どちらの値でも見た目は同じです。違いが出るのは、カードの高さを決めているとき、片方の向きだけに書いたとき、角の外にバッジを出したいときです。
検証環境は Ubuntu 24.04、Node.js 22.23.4、Playwright 1.63.0、ヘッドレスの Chromium 153 です。検証用のページを Playwright で開き、画面を撮った画像の色と、getComputedStyle() などの値を読みました。カードの画像には、検証のために描いた SVG を使っています。Firefox と Safari、スマートフォンの実機は試していません。
親に border-radius を付けただけでは、子の画像は切れない
幅 240px のカードに、角の半径 16px の border-radius を付けました。中には幅いっぱいの画像と、本文の段落を入れています。
<div class="card">
<img src="photo.jpg" alt="">
<p>カードの本文</p>
</div>
.card {
width: 240px;
border-radius: 16px;
background: #ffe9a8;
overflow: hidden; /* または clip */
}
.card img {
display: block;
width: 100%;
height: auto;
}
下の画像は、overflow を付けないカード、hidden を付けたカード、clip を付けたカードを上から並べたものです。右側には、それぞれの左上の角を拡大して並べました。

overflow を付けないカードでは、本文の背景の色は下の角で丸くなりますが、画像の角は四角いままでした。左上の角から斜めに 2px 入った点を調べると、画像の青でした。hidden と clip のカードでは、同じ点がページの背景の白になり、7px 入った点から画像の青になりました。角を切り取る形は、2つの値で同じでした。
CSS Backgrounds and Borders の仕様では、overflow が visible 以外の値のとき、はみ出しを切り取る線は、丸みの付いたパディングの外側の線(padding edge)になると決められています。border-radius は、背景や枠線の形を丸くするだけです。中の要素を丸く切り取らせるには、overflow が必要です。
カード自身に付けた box-shadow は、overflow では消えません。box-shadow: 0 0 0 6px でカードの外に線の影を描いたところ、hidden でも clip でも、カードの外側 3px の点に影の色が出ていました。overflow が切り取るのは、カードの中身だけです。
枠線を付けたカードは、枠線の内側の丸みで切れる
カードに 6px の border を付けると、画像は枠線の外側の丸みではなく、枠線の内側の線で切り取られます。
検証環境では、hidden でも clip でも、左上の角から斜めに 2px の点はページの背景の白、7px の点は枠線の色、10px の点で画像の色になりました。画像が枠線の上に重なることはありませんでした。
2つの値で結果が変わる場面
高さを決めたカードでは、hidden の中身がフォーカスで動く
MDN の overflow のページによると、hidden の要素は、中身がはみ出したときにスクロールバーのないスクロールコンテナーになり、タブ移動などでスクロールします。clip の要素はスクロールコンテナーになりません。
カードの中身が多くて枠に収まらないときに、この違いが出ます。グリッドで高さをそろえたカードのように、高さを 200px に決め、本文の最後の「続きを読む」リンクが枠の下にはみ出すカードで試しました。ページを開いて Tab キーを1回押し、リンクにフォーカスを移した結果です。
overflow: hidden |
overflow: clip |
|
|---|---|---|
カードの scrollTop |
36 | 0 |
| 画像の上端 | カードの上端より 36px 上へずれた | 動かなかった |
| フォーカスしたリンク | カードの中に見えた | カードの外(見えない位置)のまま |
hidden のカードは、リンクが見える位置まで中身がスクロールし、画像の上の 36px が隠れました。clip のカードは中身が動きませんが、フォーカスしたリンクは見えないままです。どちらの値でも、フォーカスできる要素を枠の外にはみ出させないのが確実です。スクロールとフォーカスの違いは、「CSSのoverflowで、clipとhiddenをどう使い分けるか」の記事でも詳しく確かめています。
片方の向きだけに書くと、clip では角が丸くならない
overflow-x か overflow-y の片方だけに書いたときは、結果が変わります。検証環境で、計算値と、左上の角から斜めに 2px の点の色を調べました。
| 指定 | 計算値(x / y) | 角の点 |
|---|---|---|
overflow-x: hidden |
hidden / auto |
背景の白(丸く切れた) |
overflow-x: clip |
clip / visible |
画像の青(切れなかった) |
overflow-y: clip |
visible / clip |
画像の青(切れなかった) |
overflow: clip visible |
clip / visible |
画像の青(切れなかった) |
overflow-x: hidden だけを書くと、もう片方の overflow-y は auto になりました。両方の向きが visible 以外になるので、角は丸く切れます。ただし、カードはスクロールコンテナーになります。clip を片方だけに書いた場合は、もう片方が visible のままで、角は丸くなりませんでした。
CSS Overflow Module Level 3 の仕様にも、片方の向きが clip で、もう片方が visible のときは、切り取る範囲を丸くしないと書かれています。角の丸みで切りたいときは、overflow: clip のように両方の向きに指定します。
角の外にバッジを出したいなら、overflow-clip-margin より包む要素を分ける
カードの右上に、件数などを示す丸いバッジを、角から 10px はみ出させて置いてみました。overflow: hidden や clip を付けたカードの中に置くと、バッジのはみ出した部分も切り取られます。バッジの色の画素を数えると、何も切り取らないときの 406 画素のうち、見えたのは 83 画素でした。
clip には、切り取る線を外へ広げる overflow-clip-margin があります。overflow: clip に overflow-clip-margin: 12px を足すと、バッジは 406 画素のうち 353 画素まで見えるようになりました。ところが、今度は画像の角が丸く切れなくなりました。左上と左下の角から 2px の点が、どちらも画像の青でした。

切り取る線が 12px 外へ広がると、角の丸みも一緒に外へ移ります。仕様では、広げた線の角の形は、同じ距離だけ広げた box-shadow と同じになると決められています。画像はカードの内側にあるので、外へ移った丸みには掛かりません。バッジの右上が少し欠けたのも、広げた線の角が丸いためです。なお、overflow-clip-margin は hidden には効かず、hidden に同じ指定を足しても、バッジは 83 画素のままでした。
角の外にバッジを出したいときは、切り取る要素とバッジを分けるほうが確実です。画像だけを包む要素に border-radius と overflow: clip を付け、バッジはその外側の要素に置きます。
<div class="card">
<div class="card-media">
<img src="photo.jpg" alt="">
</div>
<span class="badge">3</span>
</div>
.card {
position: relative; /* バッジの位置の基準 */
width: 240px;
}
.card-media {
border-radius: 16px;
overflow: clip;
}
.badge {
position: absolute;
top: -10px;
right: -10px;
width: 24px;
height: 24px;
border-radius: 50%;
}
この書き方では、バッジは 406 画素すべてが見え、画像の左上の角から 2px の点も背景の白でした。
overflow を使わずに、画像に角丸を付ける方法もある
画像がカードのいちばん上にあるだけなら、親の overflow を使わず、画像に上の2つの角だけの border-radius を付けても同じ見た目になります。
.card img {
border-radius: 16px 16px 0 0; /* 左上・右上だけを丸くする */
}
検証環境では、カードの overflow は visible のままで、画像の左上の角から斜めに 2px の点と、右上の角の近く(右端から 3px、上端から 2px)の点は背景の白でした。画像の下の角は四角いままでした。カードの角の半径を変えたときは、画像の値も一緒に変える必要があります。中身に画像以外の要素がはみ出すことがあるなら、親に overflow を付けるほうが、まとめて切り取れます。
対応しているブラウザー
@mdn/browser-compat-data 8.1.9 の互換性データでは、overflow: clip は Chrome と Edge が 90、Firefox が 81、Safari(macOS・iOS)が 16 から対応しています。overflow-clip-margin は、Chrome と Edge では両方の向きが clip のときだけ効く一部対応で、Safari は対応していないとされています。





