Safari や iOS 上のブラウザで border-radius で子要素をマスクできない問題

CSS

Safari で HTML を閲覧した際に、親要素に overflow: hiddenborder-radius を設定してあるのに子要素が border-radius の範囲をはみ出して表示されてしまう問題についてです。

追記: 親要素に overflow: hidden を設定している前提の説明が抜けてしまっていたのでタイトルと本文を修正しました(コメントいただいた方ありがとうございました)。

問題

子要素に角丸スタイルを適用するために親要素で overflow: hiddenborder-radius を設定しても、子要素が border-radius の範囲外でも表示されてしまいます。 デスクトップ版の Safari や iOS 上の Chrome 等で発生します。

たとえば次のように <img><div> で囲って overflow: hiddenborder-radius を設定すると現象を再現することができます。

HTML:

<div class="parent">
  <img src="avatar.jpg" width="100" height="100" />
</div>

CSS:

.parent {
  overflow: hidden;
  border-radius: 50%;
}

(当然のことながら)適用したい要素そのものに border-radius を設定した場合は意図したとおりに表示されるので、問題は親要素に overflow: hiddenborder-radius を設定したときにのみ発生します。

私は以下のブラウザ・バージョンで現象を再現できました。

  • macOS Safari: 15.4 (17613.1.17.1.13)
  • iOS Chrome: 100.0.4896.85
  • iOS Brave: 1.37 (22.4.6.8)

原因

早速結論ですが、どうやら Safari (正確には WebKit )のバグ(?)が原因のようです。 WebKit Bugzilla の Bug 140535 で「 non-stacking context でのみ発生する」と言われています。

検証のために、 stacking context を生成するような CSS プロパティを追加すると現象が解消します。

対処方法

上述のとおり non-stacking context でのみ発生するので、意図的に stacking context を生成すれば回避できます。 具体的には、見栄えに影響を与えずに stacking context を生成するために以下のような方法があります:

方法 A) isolation: isolate をセットする

.parent {
  isolation: isolate;
}

方法 B) positionz-index をセットする

.parent {
  position: relative;
  z-index: 0;
}

方法 C) transform をセットする

.parent {
  transform: translateZ(0);
}

「 stacking context を生成する」という本来の意味合いから言うと、最も直接的なのはおそらく方法 A) の isolation: isolate になるかと思います。 他の方法を使いたい理由が特に無ければ A) を選んでおくとよいのかなと思います。

stacking context を生成する方法は他にもいろいろあるようなので、興味のある方は MDN のページなどを参照してみてください:

参考

Safari (WebKit) 関連:

Chrome (Chromium) 関連:

stacking context 関連:


アバター
後藤隼人 ( ごとうはやと )

Python や PHP を使ってソフトウェア開発やウェブ制作をしています。詳しくはこちら