目的
「ヘッダーの幅をスクロールバーで縮めたくない」。
ヘッダーを固定する方法に position: fixed
を指定するという方法があるが、
このやり方では固定はできても「ヘッダーを除いた要素だけでスクロール」とはニュアンスが違ってしまう。
要は以下のようなものを作りたい、という記事。
結論から
bodyに height: 100%
を指定、
コンテンツ部分を flex-grow: 1
でヘッダー・フッターを差し引いた高さに固定し、
overflow-y: scroll
でコンテンツ部分だけをスクロールさせる。
コメントアウト部分が要点。
* {
margin: 0 0;
padding: 0 0;
}
body {
overflow: hidden;
height: 100%; /* 高さをブラウザ画面と同じにする */
display: flex; /* frex-growのために指定 */
flex-direction: column; /* flexはデフォで横並びになるので縦並びに指定 */
}
.header {
height: 100px;
min-height: 100px;
background-color: blue;
}
.contents {
flex-grow: 1; /* 親要素の高さ(幅)を埋めるようにストレッチさせる */
overflow-y: scroll; /* この要素をスクロールさせる(autoでも可) */
display: flex;
flex-direction: column;
}
.box {
height: 200px;
min-height: 200px;
display: flex;
padding: 20px;
}
.item {
flex-grow: 1;
background-color: gray;
font-size: 5em;
}
.footer {
height: 100px;
min-height: 100px;
background-color: red;
}
<html>
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<div class="header">
<h1>HEADER</h1>
</div>
<div class="contents">
<div class="box">
<div class="item">1</div>
</div>
<div class="box">
<div class="item">2</div>
</div>
<div class="box">
<div class="item">3</div>
</div>
<div class="box">
<div class="item">4</div>
</div>
<div class="box">
<div class="item">5</div>
</div>
</div>
<div class="footer">
<h1>FOOTER</h1>
</div>
</body>
</html>
HTMLの基本的なスクロールの仕組み
デフォルトでの仕様
body内の要素が画面(ブラウザ上の表示画面)の大きさを越えると画面全体のスクロールが有効になる。
それ以外は親要素より子要素が大きくても、親要素から飛び出るだけで、まとめてbodyのスクロールに内包されるのがデフォルトでの仕様。
特定の要素内でスクロールさせるには
親要素より子要素が大きい場合に、親要素内でスクロールさせたい場合は、親要素のstyleに overflow: scroll
を指定する必要がある。
これによって親要素の高さ(幅)の範囲内で子要素をスクロールさせる事ができる。
overflow
は縦方向と横方向別々に指定することも可能で、その場合は overflow-x: hidden
overflow-y: scroll
のように指定する。
また、スクロールバーの幅だけ親要素の表示範囲が狭まるので注意が必要。
スクロールバーのデザインを変更したり非表示にする事もできるが、今回は割愛。
bodyのスクロールを無効にして高さを指定する
body {
overflow: hidden;
height: 100%;
display: flex;
flex-direction: column;
}
-
overflow: hidden
:要素の範囲外に出た部分を非表示にする -
height: 100%
:要素の高さをブラウザ画面の高さに指定 -
display: flex
:子要素のfrex-growのために指定 -
flex-direction: column
:flexはデフォで横並びになるので縦並びにするために指定
これによってbodyのサイズをブラウザ画面全体に指定し、bodyでのスクロールを無効化する事ができる。
今回は body に対して設定しているが、別に body じゃなくても問題無い。
(スマホ横向き表示とかで)ヘッダーやフッターが画面を占有しすぎると、
コンテンツ部分の表示の為の枠が潰れるので注意
→ height の単位を vh にするなどして対策可能
flex-grow: 1; によって要素を引き延ばす
.contents {
flex-grow: 1;
overflow-y: scroll;
display: flex;
flex-direction: column;
}
-
flex-grow: 1
:親要素の幅・高さを埋めるように要素を引き延ばす -
overflow-y: scroll
:縦方向のスクロールバーを表示させる
flex-grow: 1
によって、親要素の高さから、高さの確定している同じ階層の要素の高さの合計を引いた高さに設定される。
例えば、親要素の高さが 720px、同じ階層の要素(header)の高さが 200px、同じ階層の要素(footer)の高さが 100px のとき、
残りの 420px が flex-grow: 1
を設定した要素の高さとして設定される。
flex-grow: 1
を設定している要素が2つ以上存在する場合は、等分になるように設定される。
横方向に並べて同じことをしたい場合
body {
overflow: hidden;
height: 100%;
display: flex;
flex-direction: row;
}
-
flex-direction: row
:column だった部分を row にするだけで横方向への配置になる