原文: HTML vs Body: How to Set Width and Height for Full Page Size (Dave Gray)

翻訳・翻案: Hitomi Kawahara

CSS は難しいですが、自由度も高いです。そして、この高い自由度のおかげで、たとえ行き当たりばったりでもスタイルを適用することができます。

ページは一見問題なく読み込まれます。「クラッシュ」もしません。

ではページ全体の幅と高さを設定したい場合、HTML 要素にどのような設定をすればいいか分かりますか。body 要素についてはどうでしょう。

上手くいくことを願いながらただ当てずっぽうにスタイルを適用していませんか。

もしそうであっても、あなたは一人じゃありません。

これらの質問に対する答えは直感的ではないのですから。

私自身、どのプロパティをどの要素に適用すべきかを正確に把握せずに、両方の要素にスタイルを適用していたという罪深い過去があります。🤦‍♂️

次の例のように、CSS プロパティが HTML と body の両方の要素に適用されていることは珍しくありません。

html, body {
     min-height: 100%;
}

それって問題なの?

はい、かなり問題です。

上のスタイル定義は以下のような問題を引き起こします。

両方の要素の min-height (最小の高さ) を 100% に設定しても、body 要素はページ全体を埋めるようになりません。これは思っていた動作と異なるかと思います。結果として表示されたスタイルの値を開発ツールで確認してみれば、body 要素の高さがゼロになっていることが分かるでしょう。

一方で、HTML 要素はブラウザーの表示領域と同じ高さになっています。

次の Chrome Dev Tools のスクリーンショットを見てください。

empty_body-3
body 要素には、上部のバーで示された初期値 8px のマージンがあります。 高さの値はゼロです。

なぜこんなことが起こるの?

パーセンテージをサイズの値として使用する場合、その要素はパーセンテージの基準として親要素を参照します。

HTML 要素は、目に見える表示領域の高さを高さ値として持つビューポートを参照します。しかし、上の例では HTML 要素の min-height を設定しているだけで、height プロパティの値は設定していません。

したがって、body 要素には、100% が何に等しいかの基準として参照する親の height 値がないことになります。

そして、問題は目に見えないかも

もし、ページを埋め尽くすほどのコンテンツがあった場合、この問題には気付かないかもしれません。

そして、より気付きにくくなる原因として、両方あるいは片方の要素に背景色を設定した場合、ビューポートはその色で埋め尽くされます。これによって、body 要素がビューポートと同じ高さを持つと錯覚してしまうのです。

それは間違いで、高さはゼロのままです。

先ほどの画像は次の CSS で表示されたものです。

html, body {
    min-height: 100%;
}
body { background-color: dodgerblue; }

逆継承?

奇妙な現象ではありますが、もし HTML 要素の背景色を個別に設定しない場合、HTML 要素には body 要素の背景色が適用されます。

では、レスポンシブなフルページの理想的な高さ設定は?

何年もの間、答えは次の通りでした。

html {
    height: 100%;
}
body {
    min-height: 100%;
}

これにより HTML 要素は親となるビューポートを参照し、ビューポートの高さの 100% に等しい height の値を持つことができます。

HTML 要素に height 値が設定されたことで、body 要素に割り当てられた min-height は、body 要素の最小の高さを HTML 要素の高さと同じにします。

この設定はまた、コンテンツがページの見えている部分より大きい場合に、あわせて body の高さを大きくすることもできます。

唯一の欠点は、HTML 要素は見えているビューポートの高さを超えて大きくならないことです。ただし、body 要素が HTML 要素を超えて大きくなることは問題ないと考えられてきました。

最新の解決策はもっと簡潔です

body { min-height: 100vh; }

この例では、単位 vh (viewport height) を使用することで、body がビューポートの全高に基づいて高さの最小値を設定できるようにしています。

先ほど述べた背景色と同じように、HTML 要素に height 値を設定しない場合、body 要素に与えられた height 値と等しい値が採用されます。

したがって、この解決策であれば以前の解決策の欠点であった HTML 要素のオーバーフローが回避され、両方の要素がコンテンツと共に大きくなります!

単位 vh の使用は、過去には一部のモバイル端末で異常をきたすこともありましたが、現在では Chrome と Safari ではビューポート単位は正常に動作するようです

ページの高さによっては水平スクロールバーが表示されることがあります

えっ、どういうこと?

「ページ幅」じゃなくて?

いいえ、違います。

別の奇妙な現象として、ページの高さがブラウザーの水平スクロールバーをアクティブにする場合があります。

ページのコンテンツがビューポートの高さを超えると、右側の垂直スクロールバーがアクティブになります。これによって、同時に水平スクロールバーが表示される可能性があります。

どうやって修正するの?

ページ幅設定が原因であることを知っておくと安心かもしれません。

この問題は HTML 要素や body 要素だけでなく、要素を 100vw (viewport width) 単位に設定することに起因します。

ビューポート単位は垂直スクロールバーが占める約 10px の幅を考慮していません。

したがって、垂直スクロールバーがアクティブになると水平スクロールバーも表示されることがあるのです。

ページをフル幅に設定する方法

設定しないというのも一つの方法です。

HTML 要素と body 要素に幅を設定しない場合のデフォルトは画面全体のサイズになります。width の値を auto 以外に設定するときには、初めに CSS をリセットするようにしましょう。

デフォルトで、body 要素の全サイドのマージンが 8px に設定されていることを覚えていますか。

CSS リセットにより、これが削除されます。マージンを削除する前に幅を 100% に設定すると body 要素のオーバーフローを引き起こします。私がよく使う CSS リセットは次のコードです。

* { 
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

好みの幅に設定する方法

必ずしも幅を設定する必要はありませんが、通常、私は設定するようにしています。

単なる癖かもしれません。

body 要素の幅を 100% に設定すると、ページ全体の幅になります。これは基本的に、幅の値を設定せずにデフォルトを許可することと同じです。

body 要素を小さなコンテナとして使用し、HTML 要素でページを埋めたい場合は、body に幅の最大値を設定することもできます。

例えば次のように設定できます。

html { background-color: #000; } 
body {
    min-height: 100vh;
    max-width: 400px;
    background-color: papayawhip; 
    margin: 0 auto;
}

結論

HTML 要素に height 値がない場合、body 要素の height や min-height を 100% に設定しても (コンテンツを追加する前は) 高さはゼロになります。

一方、HTML 要素に width 値がない場合は、body 要素の width を 100% に設定すると幅はフルページの幅になります。

これは直感に反するため、混乱するかもしれません。

レスポンシブなフルページの高さを実現するには、body 要素の min-height を 100vh に設定しましょう。

ページ幅を設定する場合、水平スクロールバーが意図せず表示されることを避けるため、100vw よりも 100% を選択しましょう。

私の YouTube チャンネルのチュートリアルでは、全画面サイズかつコンテンツと共に拡大する HTML ページ作成のために、CSS の高さと幅をどのように設定すればよいかを実際に再現しながら紹介しています。

CSS の幅と高さを設定する他の方法を知っていますか?

‌ぜひ教えてください!