HTML5
CSS3

親要素からはみ出した子要素は、右側だけがスクロール表示される

More than 5 years have passed since last update.

ネガティブマージン(margin に負の値)や position: absolute; を指定した要素が、親要素からはみ出した場合に、横スクロールが奇妙な現われ方をしたので調べてみた。

まずは簡略化したコードを用意。

<div id="wrap">

<div class="left">左ブロック</div>
<div class="right">右ブロック</div>
</div>

#wrap {

margin: 0 auto;
width: 300px;
}
#wrap .left {
margin-left: -100px;
}
#wrap .right {
margin-right: -100px;
}

#wrapの横幅は300pxなので、ブラウザのウインドウ幅が300px未満になったときに横スクロールが発生する。ところで、#wrapには子要素のブロック要素が二つあり、それぞれ左右に100pxだけ、親要素からはみ出ている状態にある。

この場合、ウインドウ幅を小さくしていくと、どのように表示されるだろうか。


はみ出した部分はスクロール幅に含まれるのか

結論からいうと、右側だけ含まれる。

文章だけでは分かりにくいので画像をどうぞ。


ウインドウ幅が広いとき

スクリーンショット 2013-11-18 6.45.32.png


ウインドウ幅を狭くしたとき

スクリーンショット 2013-11-18 6.55.50.png

画面下部に横スクロールが出ている。

スクロールバーは左端に達しているので、赤いブロックの左にはみ出た部分は見えなくなっている。

一方で、右には若干スクロールさせる余地が残っており、青いブロックの右にはみ出した部分は表示される。

横幅の小さい端末で閲覧した時に、左右アンバランス(左側に寄っているよう)に配置されて見えてしまう。

このとき、window, document, 親要素の幅を取ってみた。

console.log( $(window).width(), $(document).width(), $("#wrap").width());

// 400, 450, 300


ウインドウ幅を親要素の幅と同じにしたとき

スクリーンショット 2013-11-18 18.32.41.png

右側にはみ出た青い部分は全部見えるが、左側にはみ出た赤い部分は全く見えなくなる。

同じく、window, document, 親要素の幅を取ってみた。

console.log( $(window).width(), $(document).width(), $("#wrap").width());

// 300, 400, 300

なぜか右側にはみ出た長さ分だけ、documentは親要素より大きくなっていて、

左側にはみ出た分は無視され(documentの幅に含まれない)るため、横スクロールで右側だけ見える。


対処策

親要素のさらに外側をブロック要素で囲み、左右にはみ出た分も含めた幅をwidthに指定する。

<div id="outer">

<div id="wrap">
<div class="left">左ブロック</div>
<div class="right">右ブロック</div>
</div>
</div>

#outer {

margin: 0 auto;
width: 500px;
}

はみ出る長さを後で変えるかもしれない、というときは、

この要素の幅も変更しなければいけないので、やや気持ち悪い。


仕様か

以下のブラウザで同じ挙動を確認。(いずれもOS X)

- Google Chrome

- Safari

- Firefox

一見奇妙な挙動なので戸惑うが、主要ブラウザで同じところを見ると仕様なのだろうと思われる。

推測に過ぎないが、テキストが長くて親要素を突き出してしまうケースを想定して、

右側にはみ出た分だけはdocumentの幅に含めるようにしたのではないだろうか。

(右から左へ記述する言語を無視していることになるが)

W3Cの文書までは確認できていない。