こんにちは。
CSSで子要素が親要素の領域を超えた場合の制御方法としてoverflow
プロパティがありますが、overflow-x
、overflow-y
という形で水平・垂直方向で別々に指定できます。しかしその両方を同時に指定すると直感と異なる挙動になったため紹介します。
こんにちは。
CSSで子要素が親要素の領域を超えた場合の制御方法としてoverflow
プロパティがありますが、overflow-x
、overflow-y
という形で水平・垂直方向で別々に指定できます。しかしその両方を同時に指定すると直感と異なる挙動になったため紹介します。
overflow
プロパティは、指定した要素の子要素が領域内に収まらない場合にどういった表示・動作をするかを指定するプロパティです。以下の値を取ることができます。
visible
hidden
clip
scroll
auto
デフォルトはvisible
で、よく使うのはhidden
やscroll
かと思います。hidden
とclip
の違い等はここでは説明しません。
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
になっているなど)。とはいえ仕様書を読めばすぐ分かることなので、慣れていきたいところです。
それではまた。