✂️

【CSS】Safari 16.0でフルサポートされたoverflow: clipが便利

2022/11/25に公開
2

overflow: clipの概要

overflow: clipはChrome・Edgeでは90から[1]、Safariでは16.0から[2]フルサポートされた比較的新しい値です。

"overflow: clip" | Can I use

overflow: clipの特徴には
① コンテンツを要素のパディングボックスに合わせて切り取る
② プログラム的なスクロールも含め、全てのスクロールを禁止する
overflow-xまたはoverflow-yを使用して1つの軸にクリッピングを適用することができる
があります。[3][4]

①はoverflow: hiddenと同じですが、②、③の特徴はhiddenとは異なり、このことによってhiddenではできなかったことを簡単にできるようになりました。

本記事では、clipによってでできるようになったこと2つを紹介します。

1. position: stickyの祖先要素に使える

position: stickyで固定したい要素の祖先要素にoverflow: hidden(※)が適用されていると、position: stickyがうまく効かないことがあります。

特に多いのはbody {overflow-x: hidden}したいけど、bodyの子孫要素にposition: stickyを使いたい場合ではないでしょうか。
このようなときにoverflow-x: hiddenの代わりにoverflow-x: clipを使うと、position: stickyを意図通りに適用することができます。

overflow-x: hiddenのみ、またはoverflow-y: hiddenのみの場合も含みます。文章の読みやすさのために省略してoverflow: hiddenと書いていきます。

祖先要素にoverflow: hiddenするとstickyが効かなくなる理由

position: stickyが適用された要素は、文書の通常のフローに従って配置され、さらに、直近のスクロールの仕組みを持つ祖先要素に対してtop,right,bottom,leftの値で設定された位置で固定配置されます。

このスクロールの仕組みを持つ祖先要素overflow: autoまたはoverflow: scrollの要素だけなら、想像通りの振る舞いになると思います。

しかし、overflow: hiddenもスクロールの仕組みを持つ要素とされているのが混乱する原因です。

hidden
...内容はプログラム的に (例えば、 offsetLeft のようなプロパティの値を設定する方法などで) スクロールすることができますので、要素はスクロールコンテナーになります。
overflow - CSS | MDN


以下でstickyがうまくいく例とoverflow: hiddenによってうまくいかない例を見ていきましょう。

要素の親子関係は以下のようになっています。

.container  // .container__innerの親
  └ .container__inner  // .stickyBoxの親
      └ .stickyBox

うまくいく例
.stickyBoxoverflow-y: scrollが適用された.containerにtopの位置で張り付いています。.stickyBoxの親要素の.container__inneroverflow: visible(デフォルト値)です。

うまくいかない例
.stickyBoxの親要素.container__inneroverflow-x: hiddenすると、.stickyBoxはこれに貼り付いてしまい、stickyが効いていないように見えます。

position: stickyの祖先要素にoverflow-x: clipしてみた

前述の特徴②にあるように、overflow: clipプログラム的なスクロールも含め、全てのスクロールを禁止するので、「はみ出した部分を切り取りたいだけなのに、意図せずstickyの貼り付く対象になってしまう」のを防ぐことができます。


先ほどのうまくいかない例.container__inneroverflow-x: clipを適用してみましょう。
.stickyBoxは親要素の.container__innerではなく祖先要素の.containerに貼り付いて、意図した振る舞いになりました。

2. 要素外にはみ出した部分をx/yどちらかの方向だけ切り取ることができる

overflow: hiddenでは、はみ出したコンテンツをx/yどちらかの軸方向のみで切り取ることできませんでした。

例えば、x方向ははみ出した部分を切り取り、y方向ははみ出した部分をそのまま表示したい場合、
overflow-x: hidden; overflow-y: visible;
としても、y方向のはみ出た部分は表示されません。

理由は、overflow-xまたはoverflow-yの一方にhidden/scroll/autoが設定されているとき、もう一方に設定されたvisibleautoになってしまうからです。

一括指定の次の各プロパティとして
overflow-x: 指定通り、ただし overflow-x と overflow-y のどちらかが visible でも clip でもない場合は、 visible/clip はそれぞれ auto/hidden と計算される
overflow-y: 指定通り、ただし overflow-x と overflow-y のどちらかが visible でも clip でもない場合は、 visible/clip はそれぞれ auto/hidden と計算される
overflow - CSS | MDN

overflow-x: clipまたはoverflow-y: clipはもう一方のoverflowに干渉しないので、一方の軸方向ではみ出た部分を切り取り、もう一方の軸方向では表示することができます。

脚注
  1. New in Chrome 90 #Prevent overflow with overflow: clip - Chrome Developers ↩︎

  2. Release Notes - Safari Technology Preview - Safari - Apple Developer ↩︎

  3. overflow - CSS | MDN ↩︎

  4. https://developer.chrome.com/blog/new-in-chrome-90/#overflow-clip ↩︎

Discussion

HTMLGOHTMLGO

例えば、x方向ははみ出した部分を切り取り、y方向ははみ出した部分をそのまま表示したい場合、overflow-x: hidden; overflow-y: visible;としても、y方向のはみ出た部分は表示されません。

これのせいでどれだけ苦しめられたか。。
とてもいい記事ありがとうございます!