✂️

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

2022/11/25に公開約3,600字

overflow: clipの概要

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

"overflow: clip" | Can I use

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

①は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

ログインするとコメントできます