この記事では CSS を学ぶ上で一番苦手意識を感じやすいHTML要素の配置についてまとめていく。
プログラミング学習未経験からでもITエンジニアとしての基礎を身に付けることができるオススメのスクール >> 【DMM WEBCAMP】ブロック要素を横並びにする
この記事のサンプルの基本スタイル
サンプルとして次のような3つの子要素(div.child)を持つ div 要素(div.parent)を作成した。これにスタイルを当てることで配置を変更を確認する。
sample.html
<body>
<div class="parent">
<div class="child no1">child 1</div>
<div class="child no2">child 2</div>
<div class="child no3">child 3</div>
</div>
</body>
style.css
.parent {
width: 400px;
height: 400px;
background-color: gray;
}
.child {
width: 80px;
height: 80px;
text-align: center;
line-height: 80px;
}
.child.no1 {
background-color: lawngreen;
}
.child.no2 {
background-color: lightskyblue;
}
.child.no3 {
background-color: lightcoral;
}
div 要素はブロック要素なので、そのままでは縦(上下)方向に並んでしまう。これを横方向に並ばせたい。
インライン要素にして横並びにする
大雑把に言うと、ブロック要素は縦方向に並び、インライン要素は横方向に並ぶので、div要素もインライン要素に変更してやることで横方向に並ばせることができる。ただ display: inline;
とすると width や height の指定ができないので、「コンテンツが横並びになる」かつ「width , height を指定することができる」という性質を持っている display: inline-block;
を使うのが良いだろう。
style.css
.child {
display: inline-block; /* これを .child に追加する */
}
ただ、この画像を見てもわかるように、子要素の間に想定外のスペースが確保されてしまう。これの正体はソースコード中の改行だ。したがって子要素の間に改行が入らないようにタグの中で改行するか、
<div class="parent">
<div class="child no1">child 1</div
><div class="child no2">child 2</div
><div class="child no3">child 3</div>
</div>
あるいはコメントの中で改行してもよい。
<div class="parent">
<div class="child no1">child 1</div><!--
--><div class="child no2">child 2</div><!--
--><div class="child no3">child 3</div>
</div>
もちろん、そもそも改行しないという方法もとれる。
<div class="parent">
<div class="child no1">child 1</div><div class="child no2">child 2</div><div class="child no3">child 3</div>
</div>
スタイルで解決したいのなら、親要素の div.parent に font-size: 0;
を指定して改行がサイズを持たないようにするという手がある。ただし、子要素にも継承されてしまうので子要素 div.child には改めて font-size
プロパティを指定してあげる必要があることには注意が必要だ。
.parent {
font-size: 0; /* .parent に追加する */
}
.child {
display: inline-block;
font-size: 16px; /* .child に追加する */
}
子要素を親要素の中心に配置する
position プロパティを使った方法を紹介する。
index.html
<body>
<div class="parent">
<div class="child">child</div>
</div>
</body>
style.css
.parent {
width: 600px;
height: 300px;
background-color: gray;
}
.child {
width: 80px;
height: 80px;
text-align: center;
line-height: 80px;
background-color: lawngreen;
}
ここから position プロパティを使って中心に配置するためには、以下のスタイルを追加すれば良い。
.parent {
position: relative; /* 追加 */
}
.child {
position: absolute; /* 追加 */
top: 50%; /* 追加 */
left: 50%; /* 追加 */
transform: translate(-50%, -50%); /* 追加 */
}
top や left プロパティによる位置指定で % を使用すると、基準となる親のボックスの幅や高さに対する割合を指定することになる。そのため、今回であれば div.parent の幅・高さに対して 50% の移動を意味するため、子要素 div.child の左上の角が親要素 div.parent の中心に配置されることになる。
また、transform: translate(-50%, -50%);
は自要素の幅、高さの 50% の移動を意味するため、これにより上記の移動量と合わせて、子要素の中心が親要素の中心に配置されることになる。
フレックスボックスで重ならない要素の配置を制御する
positon プロパティを使った要素の配置は、要素が重なりを持つときに使用することが多い。一方で、重なりを持たない場合の要素の配置にはフレックスボックスを使用するのが便利だ。
次の様な HTML 要素を例に挙げてフレックスボックスの機能を説明する。
index.html
<body>
<div class="parent">
<div class="child no1">child 1</div>
<div class="child no2">child 2</div>
<div class="child no3">child 3</div>
<div class="child no4">child 4</div>
</div>
</body>
style.css
.parent {
margin: 20px auto;
width: 600px;
height: 400px;
background-color: gray;
}
.child {
text-align: center;
}
.child.no1 {
background-color: lawngreen;
width: 70px;
height: 70px;
line-height: 70px;
}
.child.no2 {
background-color: lightskyblue;
width: 80px;
height: 80px;
line-height: 80px;
}
.child.no3 {
background-color: lightcoral;
width: 90px;
height: 90px;
line-height: 90px;
}
.child.no4 {
background-color: lemonchiffon;
width: 100px;
height: 100px;
line-height: 100px;
}
display: flex; でフレックスボックスの機能を使用できるようにする
display: flex;
を親要素(フレックスコンテナーと呼ばれる)に指定すると、その直下の子要素はフレックスボックスで配置を制御できる要素になる(フレックスアイテムと呼ばれる)。
.parent {
display: flex; /* 追加 */
}
この指定により、div.parent 要素の直下の子要素は行(row)に沿って並ぶことになる。
display: flex;
を指定しただけで子要素(フレックスアイテム)がこのように並ぶのは、フレックスボックスで使用する様々なプロパティに対して初期値が適用されるからだ。プロパティの値を初期値から変えることでフレックスアイテムの配置を様々に変更することができる。
フレックスボックスを理解する上で重要なプロパティには以下のようなものがある。
- flex-direction プロパティ
フレックスボックスは主軸とそれに垂直な交差軸で配置を制御するが、このプロパティでは主軸が縦方向/横方向のどちらなのかを決定する(交差軸はそれに垂直な方向となる)。
初期値は row なので、指定しなければ行方向(横方向)にフレックスアイテムは並ぶ。 - justify-content プロパティ
主軸方向に対する子要素(フレックスアイテム)の配置の仕方を指定する。例えば主軸が行方向であれば、行頭に寄せる・中央に寄せる・行末に寄せる… などをこのプロパティで指定できる。
初期値は flex-start なので、指定がなければフレックスアイテムは主軸方向の先頭に寄る。 - align-items プロパティ
交差軸方向に対する子要素(フレックスアイテム)の配置の仕方を指定する。
初期値は stretch なので、指定がなければフレックスアイテムの垂直軸方向のサイズは親要素(フレックスコンテナー)のサイズまで伸縮される(ただしサイズが指定されている時はその値が優先される)。
以下ではこれらのプロパティについてサンプルを交えて紹介する。
flex-direction プロパティで主軸(並ぶ方向)を決定する
フレックスボックスは主軸とそれに垂直な交差軸の2軸を持つことを理解する必要がある。flex-direction プロパティが取ることのできる値は次の4種類とされている。
- row(初期値。横方向)
- row-reverse(横方向で row の逆向き)
- column(縦方向)
- column-reverse(縦方向で column の逆向き)
flex-direction プロパティに指定した値(主軸)に従って、子要素(フレックスアイテム)の並び方が決まることになる。
ここで row と row-reverse はともに横方向を主軸に指定するわけだが、違いはその向きにある。つまり主軸の向きが「右から左」なのか「左から右」なのかの違いだ。row はどちらの向きを表すのだろうか?
答えはどうやら言語によって違うらしい。(参考:MDN)
英語や日本語など左から右に記述する言語では row は左から右となり、アラビア語のような右から左に記述する言語では右から左になるらしい。
.parent {
display: flex;
flex-direction: row; /* 追加 */
}
flex-direction: row;(初期値)
flex-direction: row-reverse;
flex-direction: column;
flex-direction: column-reverse;
justify-content プロパティで主軸方向のアイテムの配置方法を決める
すでに述べたように、主軸の方向は flex-direction プロパティで決定される。justify-content プロパティでは、そこで決めた主軸方向に対する子要素(フレックスアイテム)の配置の仕方を指定することができる。justify-content プロパティに指定できる値はいろいろ用意されているが、以下ではその内のいくつかを取り上げる。
- flex-start(初期値。主軸方向の先頭に寄せる)
- flex-end(主軸方向の末尾に寄せる)
- center(主軸方向の中央に寄せる)
- space-between(主軸方向のアイテム同士のスペースが均等になるように配置する)
- space-around(アイテムの(主軸方向の)前後に同じ幅のスペースを与えて配置する)
- space-evenly(主軸方向の先頭のアイテムの前、末尾のアイテムの後、アイテム間のスペースが均等になるように配置する)
上記の説明で「主軸方向の先頭」「主軸方向の末尾」と述べたが、これは主軸方向が横方向(左から右)であれば、先頭は左端を、末尾は右端を意味している。
.parent {
display: flex;
flex-direction: row; /* 初期値がなので書かなくても良い */
justify-content: flex-start; /* 追加 */
}
justify-content: flex-start;(初期値)
justify-content: flex-end;
justify-content: center;
justify-content: space-between;
justify-content: space-around;
justify-content: space-evenly;
align-items プロパティで交差軸方向のアイテムの配置方法を決める
justify-content プロパティは主軸方向に対してアイテムの配置を決めるためのものであったが、align-items プロパティは主軸に垂直な交差軸方向に対するアイテムの配置を決めるためのプロパティとなっている。次のような値を指定することができる。
- stretch
初期値。親要素(フレックスコンテナー)の交差軸方向のサイズに合わせて子要素(フレックスアイテム)を伸縮する。ただし、子要素に width や height などで交差軸方向の幅が指定されている時はその値が優先される(伸縮しない)。 - center
子要素(フレックスアイテム)は親要素(フレックスコンテナー)の交差軸方向の中央に配置される。 - flex-start
子要素(フレックスアイテム)は親要素(フレックスコンテナー)の交差軸方向の先頭に寄せられる。 - flex-end
子要素(フレックスアイテム)は親要素(フレックスコンテナー)の交差軸方向の末尾に寄せられる。 - baseline
子要素(フレックスアイテム)はベースライン(baseline)が一直線になるように配置される。
stretch;
align-items プロパティの初期値。親要素(フレックスコンテナー)の交差軸方向のサイズに合わせて子要素(フレックスアイテム)を伸縮する。ただし、子要素に width や height などで交差軸方向の幅が指定されている時はその値が優先される(伸縮しない)。
.parent {
display: flex;
align-items: stretch; /* 追加 */
}
.child.no1 {
/* height: 70px; 高さ指定をコメントアウト、あるいは height: auto; を指定する */
}
.child.no3 {
/* height: 90px; 高さ指定をコメントアウト、あるいは height: auto; を指定する */
}
align-items: stretch(初期値)
center / flex-start / flex-end
子要素(フレックスアイテム)は親要素(フレックスコンテナー)の交差軸方向の中央・先頭・末尾に寄せられる。
.parent {
display: flex;
align-items: center; /* 追加 */
}
align-items: center
align-items: flex-start
align-items: flex-end
baseline
子要素(フレックスアイテム)はベースライン(baseline)が一直線になるように配置される。
.parent {
display: flex;
align-items: baseline; /* 追加 */
}
.child.no1 {
font-size: 200%;
}
.child.no3 {
font-size: 300%;
}
align-items: baseline
このように文字が座るラインが一直線になるように配置される。
子要素(フレックスアイテム)の主軸方向のサイズを制御する
親要素(フレックスコンテナー)ではなく、それぞれの子要素(フレックスアイテム)に対して指定し、その主軸方向のサイズを制御するためのプロパティも用意されている。
- flex-basis プロパティ
伸縮前のアイテムのサイズを指定する。 - flex-grow プロパティ
主軸方向に伸ばしてスペースを埋める際のスペースの取得比率。 - flex-shrink プロパティ
主軸方向に縮めてコンテナに収まるようにする際の縮小比率。
flex-basis プロパティ
伸縮させる前のフレックスアイテムの主軸方向のサイズを指定するためのプロパティ。このプロパティを指定しない時は、アイテムの主軸方向のサイズがこのプロパティの値として使用される。
.parent {
display: flex;
}
.child.no1 {
flex-basis: 120px;
}
.child.no4 {
flex-basis: 120px;
width: 60px; /* flex-basis の指定が優先される */
}
flex-grow プロパティ
主軸方向にスペースが存在するときに、アイテムを伸ばしてスペースを埋める際のスペースの分配比率を指定する。初期値は 0 であり、0 の時はそのアイテムは伸ばされない。
.parent {
display: flex;
}
.child.no1 {
flex-grow: 1;
}
.child.no4 {
flex-grow: 2;
}
この例では主軸方向(横方向)に存在するスペースを div.child.no1 と div.child.no4 で 1 : 2 に分配し、それぞれの要素は分配されたスペース分だけ引き伸ばされている。div.child.no2 と div.child.no3 については、flex-grow を指定していないため初期値 0 が適用され、伸ばされない。
flex-shrink プロパティ
親要素(フレックスコンテナー)の主軸方向のサイズに対して、子要素(フレックスアイテム)の主軸方向のサイズの合計が大きくて収まらない場合に、収まらなかったサイズの分配比率を指定する。この比率にしたがってフレックスアイテムが縮小されることになる。flex-shrink の値に 0 を設定すると、そのフレックスアイテムは縮小されなくなるが、初期値は 1 であるため何も指定しなくても基本的にはコンテナに収まるように縮小される。
.parent {
display: flex;
}
.child.no1 {
flex-basis: 200px;
flex-shrink: 0; /* 縮小させない */
}
.child.no2 {
flex-basis: 200px;
flex-shrink: 0; /* 縮小させない */
}
.child.no3 {
flex-basis: 200px;
flex-shrink: 0; /* 縮小させない */
}
.child.no4 {
flex-basis: 200px;
flex-shrink: 0; /* 縮小させない */
}
.parent {
display: flex;
}
.child.no1 {
flex-basis: 200px;
flex-shrink: 1;
}
.child.no2 {
flex-basis: 200px;
flex-shrink: 0; /* 縮小させない */
}
.child.no3 {
flex-basis: 200px;
flex-shrink: 0; /* 縮小させない */
}
.child.no4 {
flex-basis: 200px;
flex-shrink: 2;
}
フレックスコンテナーに収まらないとき複数行に折り返す(flex-wrap)
個々の子要素(フレックスアイテム)に必ず確保したい主軸方向の最小サイズを定めると、画面サイズによっては親要素(フレックスコンテナー)からあふれてしまう場合がある。
あふれてしまう場合はあふれてしまうアイテム以降を交差軸方向に折り返すことができる便利なプロパティが flex-wrap だ。flex-wrap プロパティは次の値を取ることができる。
- nowrap(初期値)
フレックスアイテムがコンテナからあふれてしまう場合でも折り返さない。 - wrap
フレックスアイテムがコンテナからあふれてしまう場合は交差軸方向に折り返す。 - wrap-reverse
wrap と同様に折り返すが、交差軸方向に折り返す向きが逆になる。
.parent {
display: flex;
flex-wrap: nowrap; /* 初期値 */
}
.child.no1 {
flex-basis: 200px;
}
.child.no2 {
flex-basis: 300px;
}
.child.no3 {
flex-basis: 400px;
}
.child.no4 {
flex-basis: 500px;
}
flex-wrap: nowrap;(初期値)
収縮を許可しているため、アイテムはあふれないがサイズが確保できていない
flex-wrap: wrap;
flex-wrap: wrap-reverse;
折り返した時の交差軸方向にとられる間隔は、交差軸方向に生じるスペースを均等に配分しているようだ。