Safariでのみborder-radius: 50%;とoverflow: hidden;を外すとスタイルが崩れてしまい、画像を円形にトリミングできない
といった現象に出くわしました。
解決法を探っていると、どうやらposition
プロパティとz-index
プロパティに原因がありそうです。
【Point】Safariでborder-radiusとoverflow: hidden;を適用させるには
- 子要素の
position
プロパティにstatic
以外の値が指定されていないか確認する
【結論】Safariでborder-radiusとoverflow: hidden;を適用させるには
- 子要素の
position
プロパティを解除できない場合
→親要素にz-index: 1;
を指定する - 子要素の
position
プロパティを解除しても問題ない場合
→子要素のposition
プロパティを解除する
【基本コード】Safariでborder-radiusとoverflow: hidden;を適用させるには
HTML
<figure class="icon">
<img src="/img/icon-profile.png" width="96" height="96" loading="lazy" aria-hidden="true" alt="さおさん">
</figure>
SCSS
.icon{
border-radius: 50%;
overflow: hidden;
img{
position: relative;
}
}
こちらのコードをベースに見ていきます。
下記のスパイスカレーの画像部分のコードです。.icon
という親要素の中に画像が入っています。

【解説】Safariでborder-radiusとoverflow: hidden;を適用させるには
まずは子要素にpositionプロパティが指定されているかを確認する
親要素に指定されているborder-radius
とoverflow
プロパティがきかないケースでは、
子要素のposition
プロパティにstatic
以外の値が指定されていることが多いです。
指定されていた場合、
指定の解除の可否によって対処法が変わってきます。
positionプロパティを解除できない場合の対処法
子要素のposition
プロパティを外すとスタイルが崩れてしまうなどの不具合が起こる可能性があります。
そういったケースでは子要素の指定は変更せず、
親要素にz-index: 1;
を指定します。
.icon{
border-radius: 50%;
overflow: hidden;
position: relative;
z-index: 1;
img{
position: relative;
}
}
z-index
プロパティはposition
プロパティにstatic
以外の値を指定しないとONにならないので、
あわせてposition: relative;
も指定します。
positionプロパティを解除しても問題ない場合の対処法
こちらのケースでは、単純に子要素のposition
プロパティを外してあげましょう。
なので下記で問題ありません。
.icon{
border-radius: 50%;
overflow: hidden;
}
これで円形にアイコン画像をトリミングできました。

スタッキングコンテキストとスタックレベルとは?
なぜこのような対処法で解決できるのでしょうか?
この問題の根底には「スタッキングコンテキスト」と「スタックレベル」という概念が存在しています。
- 「スタックレベルってなんなん?」
スタックレベルとは「スタッキングコンテキスト内の要素の重なり順」のことです。
- 「なるほど。んじゃ、スタッキングコンテキストってなんなん?」
スタッキングコンテキストとは「スタックレベルの比較範囲」のことです。
まとめると、
「スタッキングコンテキスト内の要素間でのみ、重なり順が比較される」
ということです。
——————————————–
期末試験を例に説明してみようと思います。
期末試験が終わると成績順が発表されます。
学年全体の順位もあれば、クラスごとのもの出されます。
このクラスごとの順位を算出するときの
- 「クラスという単位」が「スタッキングコンテキスト」
- 「クラス内の成績順」が「スタックレベル」
です。
A組とB組がある場合、それぞれのクラスごとに生徒の点数を比較しますよね。
A組の最下位とB組の最下位の点数を比較して順位をつけたりしませんよね。
「順位はクラス内の生徒の間でのみ比較」します。
これと同じことがWebページ上でもなされています。
要素の重なり順(成績順)は、スタッキングコンテキスト内(クラスの中)でのみ比較されているのです。
——————————————–
なぜ今回の不具合が起こったのかというと、
親要素にスタッキングコンテキストが生成されていないのに、
子要素であるアイコン画像にposition
プロパティが適用されていたからだと考えられます。
スタッキングコンテキストを作成するには、要素にz-index
を指定する必要があります。
しかしposition
プロパティを指定することで、z-index
を指定しなくても、
スタッキングコンテキストのような振る舞いをします。
つまり、通常の要素よりも上に位置するようになります。
(※参考:君は真に理解しているか?z-indexとスタッキングコンテキストの関係)
このことからSafariでは、
子要素がスタッキングコンテキストのような振る舞いをすると
親要素の領域に所属していないと認識されてしまうのかもしれません。
(親要素のスタッキングコンテキストから外れるのかもしれないということです)
なので対処法は下記の二通りになります。
- 親要素にスタッキングコンテキストを生成する
- 子要素に対するスタッキングコンテキストの適用をやめる
スタッキングコンテキストの生成方法
スタッキングコンテキストを生成するのはカンタンです。
スタッキングコンテキストを生成したい要素に、position
プロパティと z-index
プロパティを指定するだけです。
.icon{
border-radius: 50%;
overflow: hidden;
position: relative;
z-index: 1; //これで.icon要素を基準にスタッキングコンテキストが生成されました
}
この指定で、子要素であるアイコン画像が、親要素のスタッキングコンテキストに所属することになりました。
親要素の領域に内包されることでSafariでも円形トリミングに成功しました。
【まとめ】Safariでborder-radiusとoverflow: hidden;を適用させるには
position
プロパティのこととか z-index
プロパティのこととか、
はたまた「スタッキングコンテキスト」や「スタックレベル」いう概念が出てきたりとか。
調査すればするほど奥が深くて難しくて
オーバーヒートしました…
Safariで border-radius
や overflow
プロパティがきいていない時は、
まず下記の方法をお試しください!
- 親要素に
z-index: 1;
を指定する - 子要素の
position
プロパティを解除する
以上です!
少しでもお役に立てたら嬉しいです。
Comments