「heightの指定で100%と100vhの違いがわかっていない」
「height: 100%;にしているのになぜかレイアウトが崩れることがある」
「親子関係になっている要素では親と子のどちらに高さを指定すれば良いか悩むことがある」
本日はそんな方に向けてheightの指定のやり方を解説していきます。
昔の自分が勘違いしていた2つの間違い例をもとにheightの挙動を確認していきましょう。
また動画もあるので必要に応じて活用してください。
CSSでheight: 100%;とどうなるのか?
初学者向けの学習教材やYoutube動画でHTML、CSSを学習していると「height: 100%;」という指定をよく見かけると思います。
初学者のうちはコピペするのが精一杯だと思いますが、少しずつコーディングに慣れてきたら実際の意味を理解しておかないと実務でハマります。
結論、height: 100%;は「親の要素の高さと同じにする」という意味になります。
以下のようなHTMLを想定します。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="container">
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認する
</div>
<hr />
</body>
</html>
現状だと上図のようになっています。
要素がどこまでの範囲を占めるのか分かりやすくするためにCSSで背景色をつけておきましょう。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
background: yellow;
}
これでどこまでがheightの高さになるのかがパッと見てわかるようになりましたね。
現状は文字の最終行までが高さになっているようです。
それではheight: 100%;を追加してみましょう。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
background: yellow;
/* ここを追加 */
height: 100%;
}
特に見た目は変わっていませんね、と言うのもcontainerの親要素はbodyタグになるわけですがbodyタグに高さを指定していないからです。
そこでbodyタグに高さを指定してみます。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
/* ここを追加 */
height: 500px;
}
.container {
background: yellow;
height: 100%;
}
先ほどheight: 100%;の意味は「親要素と同じ高さにする」と言いました。
containerの親であるbodyの高さが500pxになったので、containerも500pxの高さになり文字の最終行よりも下の方にまで黄色網掛けが広がりました。
「100%」という単語だけ見ると「画面いっぱい」と解釈する方もいるかもしれませんが、ご覧頂いたように「画面いっぱい」という意味ではありません。
あくまで親要素の高さによって変動します。
ちなみに画面いっぱいに高さを広げたい場合は「100vh」とすればOKです。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
height: 500px;
}
.container {
background: yellow;
/* ここを修正 */
height: 100vh;
}
親要素で高さを500pxにしていましたが、画面いっぱいまで黄色網掛けが広がりましたね。
「100vh」という指定もよく使うので違いを理解しておきましょう。
CSSでheight: 100%;を使うときのミス①
例題を変えて以下のようなHTMLを作ってみます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="wrapper">
<div class="text1">
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
</div>
<div class="text2">
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
</div>
</div>
</body>
</html>
もう一度height: 100%;の件に戻るのですが、例えば親要素にoverflow: hidden;が設定されている場合は注意です。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
height: 300px;
overflow: hidden;
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
}
.text2 {
border: 2px solid #333;
}
この状態からtext1に対してheight: 100%;で高さを指定してみます。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
height: 300px;
overflow: hidden;
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
/* ここを追加 */
height: 100%;
}
.text2 {
border: 2px solid #333;
}
text1の親要素にあたるwrapperはもともと高さ300pxでしたので、text1にheight: 100px;を追加するとtext1の高さも300pxになります。
ここまでは冒頭のお話と同じなのですが、text2が画面から消えてしまいました。
親要素であるwrapperにoverflow: hidden;が設定されていることが原因で、overflow: hidden;は「はみ出た要素を非表示する」という効果があります。
状況を整理すると以下のような手順です。
①親要素のwrapperの高さは300px
②子要素のtext1にheight: 100%;を追加したのでtext1の高さも300pxになる
③親要素のwrapperの高さはtext1で埋まったので、はみ出たtext2は非表示になる
一番手っ取り早い解決法はwrapperからoverflow: hidden;を削除することですが、他の事情でoverflow: hidden;を残さないといけない場合があります。
その際には親要素では高さは指定せず、子要素のみで高さを指定することが必要です。
CSSを以下のように修正します。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
overflow: hidden;
/* height: 300px;を削除 */
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
/* ここを修正 */
height: 300px;
}
.text2 {
border: 2px solid #333;
}
これでtext1の高さを300pxまで広げつつ、全体が表示されるようになりました。
今回のように別のプロパティがぶつかり合うことで予定にないレイアウト変更が起きるミスには気をつけましょう。
CSSでheight: 100%;を使うときのミス②
height: 100%;でありがちなミスをもう一つ紹介します。
HTMLは先ほどと同じものを使います。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="./style.css" />
<script src="./script.js" defer></script>
</head>
<body>
<div class="wrapper">
<div class="text1">
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
</div>
<div class="text2">
この文章はダミーです。文字の大きさ、量、字間、行間等を確認するために入れています。
</div>
</div>
</body>
</html>
CSSについて親要素のwrapperの高さをmin-height: 300px;で指定したとします。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
min-height: 300px;
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
}
.text2 {
border: 2px solid #333;
}
min-height: 300px;とすることで「高さは300px以上」という意味になります。
今回も子要素であるtext1に対してheight: 100%;を指定してみます。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
min-height: 300px;
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
/* ここを追加 */
height: 100%;
}
.text2 {
border: 2px solid #333;
}
見た目は変わっていないのですが検証ツールを見てみます。
親要素であるwrapperの高さは300pxなのですが、子要素のtext1は高さが変わって無いことがわかります。
昔の自分はheght: 100%;としているのだからtext1も高さも増えると思っていました。
しかしmin-heightはあくまで「〇〇以上」という意味で、具体的な高さの値は決まっていませんのでheight: 100%;としても高さの値を決められないのです。
そのためtext1の高さは変わって無い状態になっているわけです。
ちなみにこちらの例も先ほどと同じで子要素に具体的な高さを指定すれば解決できます。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
min-height: 300px;
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
/* ここを修正 */
height: 300px;
}
.text2 {
border: 2px solid #333;
}
text1には100%ではなく300pxと決めうちで値を指定したことで上手くいきました。
また別の解決法としてflexボックスにすることでも解決できます。
CSSを以下のように修正します。
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
width: 300px;
min-height: 300px;
/* ここを追加 */
display: flex;
flex-direction: column;
}
.text1 {
border: 2px solid #333;
margin-bottom: 16px;
/* ここを修正 */
flex-grow: 1;
}
.text2 {
border: 2px solid #333;
}
親要素であるwrapperにてflexプロパティで縦関係の並びにしています。
とはいえ元から縦関係の並びだったので見た目は変わりません。
親要素であるwrapperにflexプロパティを追加したことで、子要素であるtext1にflex-growを使うことができます。
flex-growは本来は複数の要素で「余ったスペースを2:1で分配する」といった具合に、余ったスペースを埋める比率を設定するものです。
この特性を利用してtext1にのみflex-grow: 1;とすることで、「余ったスペースはtext1に全て分配する」という意味になります。
結果的にtext1は文字の幅を超えて高さを広げることができます。
こんな感じでheight: 100%;は親要素のプロパティによって意図しない表示になることがあるので皆さんも注意してください。
また今回の記事を作成するにあたり以下の本を参考にしましたので良ければどうぞ。