【CSS】overflowをxy両方使うときは組み合わせに注意
こんにちは。
CSSで子要素が親要素の領域を超えた場合の制御方法としてoverflowプロパティがありますが、overflow-x、overflow-yという形で水平・垂直方向で別々に指定できます。しかしその両方を同時に指定すると直感と異なる挙動になったため紹介します。
overflowプロパティ
overflowプロパティは、指定した要素の子要素が領域内に収まらない場合にどういった表示・動作をするかを指定するプロパティです。以下の値を取ることができます。
visiblehiddenclipscrollauto
デフォルトはvisibleで、よく使うのはhiddenやscrollかと思います。hiddenとclipの違い等はここでは説明しません。
overflow-x、overflow-yプロパティ
overflowプロパティは実際にはショートハンド(一括指定)プロパティで、水平・横方向のoverflow-xプロパティと垂直・縦方向のoverflow-yプロパティを同時に指定できます。2つの値を並べて書けば1つ目がoverflow-xプロパティに、2つ目がoverflow-yプロパティに指定されます。
両方別々に指定した場合の挙動
本題です。パソコンは横スクロール操作に弱い(やりにくい)ため、縦横自由にスクロールできるようにすることはそこまで多くないと思います。基本的には縦方向のみスクロールできるようにすることが多いと思いますが、稀に縦方向にはスクロールさせつつ横ははみ出して表示したいというようなパターンに遭遇します(幅が決まっている親要素内に置いたモーダル要素をその横に表示するなど)。つまり、以下のような状態です。

この状態で右にはみ出しているボックスはそのままはみ出した状態で、下にはみ出しているボックスははみ出さずスクロールできるようにしたい、という感じです。
そのときに考える指定は、overflow-xはvisible(または指定しない)、overflow-yはscrollという感じになると思います。しかしこの指定をして表示してみると以下のようになります。

縦方向にしかスクロールするよう指定していないにもかかわらず、横方向もスクロールするUIになっています。確かに要素の右端には縦スクロールバーがあるので、はみ出した場合にどう表示するのかという問題が出てきますが、普通に上に重ねて表示してくれてもいいのかなと思ってしまいます(縦スクロールはマウスホイールも使えますし)。
ちなみにscrollではなくhiddenにした場合でも右方向にはみ出すことはありません(この場合縦スクロールバーも無いですがはみ出ません)。

両方指定した場合の仕様
個人的には直感に反する挙動なのですが、これはCSSの仕様に書かれているものなのでブラウザは正しい実装をしているということになります。仕様書を読んでみます。
as specified, except with visible/clip computing to auto/hidden (respectively) if one of overflow-x or overflow-y is neither visible nor clip
つまり、overflow-xとoverflow-yのどちらかにscrollやhiddenを指定している時点で、もう一方はvisibleを指定していても自動的にautoとして扱われるということです。今回の例では、右側は常にはみ出しているため、横スクロールバーが常に表示されてしまうというわけです。
どう解決するか
どうすればはみ出しと縦スクロールを両立できるかですが、同じ要素に両方のプロパティを指定した場合の話なので、もう1段階入れ子にしてoverflow-xとoverflow-yを適用する要素を分けてしまえばいいです。ただそのために要素を増やすくらいならはみ出して表示したい要素はoverflowで制御する要素の外に出してしまって、JavaScript側で位置を指定するでも良い気がします(モーダルのようなUIであれば表示非表示の制御も入ってくると思うので)。
というわけで今回は、overflowプロパティを縦横両方に記述した場合に想定外の表示になってしまう問題について、その仕様を紹介しました。HTMLやCSSは仕様の標準化が進みブラウザ差分は無くなってきていますが、こういった直感に反する仕様もあります(box-sizingプロパティのデフォルトがcontent-boxになっているなど)。とはいえ仕様書を読めばすぐ分かることなので、慣れていきたいところです。
それではまた。