はじめに
CSSによるページレイアウト
Webページのレイアウトを作るとき、要素の位置を操作するCSSはいくつかあります。
代表的なものとしては下記です。
- 通常フロー
- フレックスボックス
- グリッド
- フロート(ほとんど使わない)
- 位置指定(position)
- 表レイアウト(table)
など
通常フロー
CSSが何も適用していない場合、Webページ上の要素はもともとHTMLが持つルールで表示されます。
ブロックレベル要素のコンテンツは、親要素の幅の100%で、高さがコンテンツに準じます。
インライン要素は、コンテンツと同じ幅・高さを持ちます。
視覚的にみると以下のような感じです。
<div class="container">
<div>ブロック要素です。</div>
<span>インライン要素です。</span>
</div>
.container{
height: 200px;
background-color: #ccc;
color: #fff;
}
.container div{
background-color: green;
}
.container span{
background-color: blue;
}
インライン要素のサイズを変更したい場合は、display: block;
を使用してブロックレベル要素に変更する必要があります。
※display: inline-block;
というのもあります。
しかし、これだけでレイアウトを表現するには限界があります。
そこで、displayプロパティに特別な値を指定することで、より複雑なレイアウトを実現することが可能になります。
特別な値の中でも重要なのがdisplay:flex
とdisplay:grid
の2つです。
今回は、display:flex;
についてまとめようと思います。
フレックスボックス
フレックスボックスは、要素を行もしくは列の1次元にレイアウトするための方法です。
1次元とは「行」または「列」のことです。どちらかひとつしか扱うことができません。
フレックスボックスを使うには、display:flex;
をレイアウトしたい親要素に適用します。
こうすることで、その直下の子要素はすべてflex-item
というものになります。
フレックスボックスは、要素を行もしくは列の1次元で扱うと書きましたが、デフォルトでは行として表示される(flex-direction:row;
)ので、横並びになります。
※flex-item
やflex-direction:row;
については後述
<div class="wrapper">
<div>1つめのブロック要素</div>
<div>2つめのブロック要素</div>
<div>3つめのブロック要素</div>
</div>
.wrapper{
display: flex;
}
.wrapper div{
height: 100px;
border-radius: 10px;
border: green 1px solid;
background-color: lightgreen;
}
フレックスボックスの構造
フレックスボックスを理解するには、構造を知ることが欠かせません。
下記が構造図です。
引用 : MDN Web Docs -フレックスボックスhttps://developer.mozilla.org/ja/docs/Learn/CSS/CSS_layout/Flexbox
大事なフレックスボックスの構成要素
-
flex-container:flex-itemを囲む親要素です。
display:flex;
を指定した要素。 - flex-item:flex-containerの直下の子要素です。行か列の1次元でレイアウトされます。
- 主軸(main-axis):flex-itemが配置される方向に走る軸です。
- 主始点(main-start):主軸の始点です。
- 主終点(main-end):主軸の終点です。
- 交差軸(cross-axis):flex-itemが配置される方向に対して垂直に走る軸です。
- 交差始点(cross-start):主軸の始点です。
- 交差終点(cross-end):主軸の終点です。
- main-size:主軸からみたときの、flex-itemの(横)幅です。
フレックスボックスでは上記の構成要素を基準として、CSSプロパティを適用していくことでレイアウトを柔軟に変更することができるのです。
主軸(main-axis)の方向を指定する : flex-direction
flex-direction
というプロパティを使うと、主軸(main-axis)が走る方向を指定できます。
デフォルトだと、row
に設定されているため、行並び(横並び)となります。
列並び(縦並び)にするにはcolumn
を指定します。
<div class="wrapper">
<div>1つめのブロック要素</div>
<div>2つめのブロック要素</div>
<div>3つめのブロック要素</div>
</div>
.wrapper{
display: flex;
flex-direction: column;/*追記*/
}
.wrapper div{
height: 100px;
border-radius: 10px;
border: green 1px solid;
background-color: lightgreen;
}
なお、フレックスボックスは横並びにさせるCSSという認識がある人は、この時点で新しい発見に気づいているとおもいます。
フレックスボックスはデフォルト値が横並びなだけで、決して横並びにさせるためだけのCSSではありません。
あくまで、行か列の1次元におけるレイアウトを表現するためのプロパティなのです。
flex-direction
には、他にもflex-direction: row-reverse;
やflex-direction: column-reverse;
があります。
参考リンクはこちらです。
主軸(main-axis)に沿ったflex-itemの配置方法 : justify-content
flex-direction
で主軸(main-axis)の方向を決めることができたので、次はflex-item
の配置方法を指定します。
flex-item
が主軸上のどこに配置されるかを指定するにはjustify-content
を使います。
デフォルト値はflex-start
となっていて、主軸の始点(main start
)に配置されます。
逆に、主軸の終点(main end
)に配置するにはflex-end
を使います。
.wrapper{
display: flex;
justify-content: flex-end;
}
justify-content
には、他にもjustify-content: space-between;
やjustify-content: space-around;
、justify-content: space-evenly;
などがあります。
参考リンクはこちらです。
交差軸(cross-axis)に沿ったflex-itemの配置方法 : aligin-items
flex-item
が交差軸上のどこに配置されるかを指定するにはaligin-items
を使います。
デフォルト値は、stretch
です。
これは、すべてのflex-items
を親要素の高さに合わせて交差軸の方向に引き伸ばします。
なお、親要素が交差軸方向に固定幅(高さ)を持っていない場合、すべてのflex-item
の高さは、1番高いflex-item
と同じになります。
例えば下記のようなフレックスボックスがあります。
子要素には何も高さを指定していないのに、親の高さ300pxにflex-item
が引き伸ばされていることがわかります。
<div class="wrapper">
<div>1つめのブロック要素</div>
<div>2つめのブロック要素</div>
<div>3つめのブロック要素</div>
</div>
.wrapper{
display: flex;
height: 300px;
}
.wrapper div{
border-radius: 10px;
border: green 1px solid;
background-color: lightgreen;
}
次に、交差軸の中央に配置するプロパティを見てみます。
中央配置するには、aligin-items:center;
を指定します。
先程のCSSに追加してみます。
.wrapper{
display: flex;
height: 300px;
align-items: center;/*追記*/
}
結果は以下のようになります。strechが指定されていないので、flex-itemの引き伸ばしがなくなったのと、交差軸に対して中央に配置されているのがわかります。
align-items
には、他にもalign-items: start;
やalign-items: end;
、があります。
参考リンクはこちらです。
flex-itemのサイズ変更 : flex-grow / flex-shrink / flex-basis
ここはちょっと難しいかもしれません。公式ドキュメントや記事下部の参考記事なども併せて確認してください。
flex-itemのサイズを変更するには以下3つのプロパティを使います。
- flex-grow
- flex-shrink
- flex-basis
flex-basis
順番が前後しますが、flex-growとflex-shrinkのまえにflex-basisから理解します。
flex-basis
はflex-item
の初期の幅(main-size
)を指定するプロパティです。
flex-basis
のデフォルト値はauto
になっているので、それぞれの幅はコンテンツに応じます。display:inline-bliock
に似ています。
display:flex;
を指定すると、子要素がぺちゃんと潰れてしまうのはこれが原因です。
<div class="wrapper">
<div class="item01">1つめのブロック要素</div>
<div class="item02">2つめのブロック要素</div>
<div class="item03">3つめのブロック要素</div>
</div>
.wrapper{
display: flex;
height: 100px;
}
.wrapper div{
border-radius: 10px;
background-color: lightgreen;
}
次に.item01
のflex-basis
を400pxに変更します。
.item01
の幅が400pxになって広がったのがわかります。
.wrapper .item01{
flex-basis: 400px;
}
だけど、ここで大事なのが、flex-basisはあくまで初期の幅ということです。
初期?(ここが結構難しい)
ためしに親要素の幅を縮めてみます。
.item01
の幅が400px以下になってしまいました。
フレックスボックスは親要素(フレックスコンテナ)の大きさを基準として、子要素であるflex-itemがうまく収まるように
「きみはこれだけ幅を取っていいよ」
と計算するようになっています。
そのとき、参考にするのがflex-basis
です。
flex-item
がそれぞれ
「ぼくはこれだけの幅が欲しいです!」
と主張をflex-basis
として形にするわけです。
例えば上記の例で言えば、
.item01
はflex-basis:400px;
なので
「ぼくはできれば400pxは幅が欲しいです!」
と主張していて、残りの.item02
と.item03
はflex-basis:auto;
なので
「ぼくらはまぁ、それなりの幅があればいいです」
と主張しています。
※あくまでイメージです。
それを聞いた、親要素のフレックスコンテナが
「じゃあ、.item01
には400pxあげて、そのほかの子たちにはコンテンツ分の幅だけあげよう」
というふうになるわけです。
これが親要素の幅に余裕があるときはいいのですが、flex-itemたちの主張する幅の合計が親要素の幅を超えてしまったときはどうでしょうか?
イメージとしては以下のような感じになります。
「幅が足りんから、.item01
に400pxもあげられんけど、他の子たちよりは多めに幅やるわ。」
となるわけです。
※あくまでイメージです。
flex-grow
flex-grow
は親要素の空間が余った場合の、子要素達の伸び具合を調整するプロパティです。
flex-grow
のデフォルト値は0です。
例えば、下記のようなフレックスボックスの場合、紫色のところが親要素の余った空間になっています。
<div class="wrapper">
<div class="item01">1つめのブロック要素</div>
<div class="item02">2つめのブロック要素</div>
<div class="item03">3つめのブロック要素</div>
</div>
.wrapper{
display: flex;
height: 100px;
}
.wrapper div{
border-radius: 10px;
background-color: lightgreen;
}
この余った空間をなくしたいときがあります。
そんなときは.item03
にflex-grow
を指定します。
.wrapper .item03{
flex-grow: 1;
}
.item03
が伸びて余った空間がなくなりました。
これは親要素の余った空間を、子要素たちで分けるときにどのくらいの割合にするかと指定したからです。
つまり、何も指定しなければ、.item01とitem02と.item03の余った空間の割合は0:0:0になるわけです。(flex-grow
のデフォルト値は0でした)
しかし、.item03にflex-grow: 1;
を指定したことで、割合が0:0:1になったので、.item03に余った空間をぜんぶ分け与えることになったのです。
flex-shrink
flex-shrink
は親要素の空間が足りない場合の、子要素達の縮み具合を調整するプロパティです。
flex-shrink
のデフォルト値は1です。
例えば、下記のようにflex-basis
を400pxに指定した.item01というflex-item
があるとします。
.wrapper .item01{
flex-basis:400px;
}
親の空間に余裕がある場合は、400pxまるまる確保されますが、、、
あくまでflex-basisは初期の幅なので、親要素の空間に余裕がなくなれば
400px以下になってしまいます。
ここまでは、flex-basisのときに説明しました。
だけど、時には縮んでほしくない場合もあるでしょう。
そんな時には、その要素にflex-shrink:0;
を指定します。
.wrapper .item01{
flex-basis:400px;
flex-shrink: 0;
}
こんな感じで、400pxが保たれたままになります。
おわりに
とりあえず、ひととおりフレックスボックスについて理解しておきたいことをまとめてみました。
このほかにも、wrapプロパティ
など、コーディングに大事なプロパティがいくつかありますが、ここに書いたことが前提知識としてあれば理解に苦しむことも少ないかなと思っています。
また、改めてフレックスボックスについてまとめてみたのは、個人的にグリッドレイアウトをちゃんと理解したいなと思ったからです。
フレックスボックスとグリッドレイアウトの違いをしっかり理解することで、グリッドの学習も捗るかなと考えた次第です。