LoginSignup
36
51

More than 1 year has passed since last update.

【図解】ちゃんと理解するフレックスボックス【CSS】

Posted at

はじめに

CSSによるページレイアウト

Webページのレイアウトを作るとき、要素の位置を操作するCSSはいくつかあります。

代表的なものとしては下記です。

  • 通常フロー
  • フレックスボックス
  • グリッド
  • フロート(ほとんど使わない)
  • 位置指定(position)
  • 表レイアウト(table)
    など

通常フロー

CSSが何も適用していない場合、Webページ上の要素はもともとHTMLが持つルールで表示されます。

ブロックレベル要素のコンテンツは、親要素の幅の100%で、高さがコンテンツに準じます。

インライン要素は、コンテンツと同じ幅・高さを持ちます。

視覚的にみると以下のような感じです。

sample01.png

<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:flexdisplay:gridの2つです。

今回は、display:flex;についてまとめようと思います。

フレックスボックス

フレックスボックスは、要素を行もしくは列の1次元にレイアウトするための方法です。

1次元とは「行」または「列」のことです。どちらかひとつしか扱うことができません。

フレックスボックスを使うには、display:flex;をレイアウトしたい親要素に適用します。

こうすることで、その直下の子要素はすべてflex-itemというものになります。

フレックスボックスは、要素を行もしくは列の1次元で扱うと書きましたが、デフォルトでは行として表示される(flex-direction:row;)ので、横並びになります。

flex-itemflex-direction:row;については後述

sample02.png

<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;
}

フレックスボックスの構造

フレックスボックスを理解するには、構造を知ることが欠かせません。

下記が構造図です。

flex_terms

引用 : 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を指定します。

sample03.png

<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を使います。

sample04.png

.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が引き伸ばされていることがわかります。

sample05.png

<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の引き伸ばしがなくなったのと、交差軸に対して中央に配置されているのがわかります。

sample06.png

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-basisflex-item初期の幅main-size)を指定するプロパティです。

flex-basisのデフォルト値はautoになっているので、それぞれの幅はコンテンツに応じます。display:inline-bliockに似ています。

display:flex;を指定すると、子要素がぺちゃんと潰れてしまうのはこれが原因です。

sample07.png

<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;
}

次に.item01flex-basisを400pxに変更します。

.item01の幅が400pxになって広がったのがわかります。

sample08.png

.wrapper .item01{
    flex-basis: 400px;
}

だけど、ここで大事なのが、flex-basisはあくまで初期の幅ということです。

初期?(ここが結構難しい)

ためしに親要素の幅を縮めてみます。

sample09.png

.item01の幅が400px以下になってしまいました。

フレックスボックスは親要素(フレックスコンテナ)の大きさを基準として、子要素であるflex-itemがうまく収まるように

「きみはこれだけ幅を取っていいよ」

と計算するようになっています。

そのとき、参考にするのがflex-basisです。

flex-itemがそれぞれ

「ぼくはこれだけの幅が欲しいです!」

と主張をflex-basisとして形にするわけです。

例えば上記の例で言えば、

.item01flex-basis:400px;なので

「ぼくはできれば400pxは幅が欲しいです!」

と主張していて、残りの.item02.item03flex-basis:auto;なので

「ぼくらはまぁ、それなりの幅があればいいです」

と主張しています。
※あくまでイメージです。

それを聞いた、親要素のフレックスコンテナが

「じゃあ、.item01には400pxあげて、そのほかの子たちにはコンテンツ分の幅だけあげよう」

というふうになるわけです。

これが親要素の幅に余裕があるときはいいのですが、flex-itemたちの主張する幅の合計が親要素の幅を超えてしまったときはどうでしょうか?

イメージとしては以下のような感じになります。

「幅が足りんから、.item01に400pxもあげられんけど、他の子たちよりは多めに幅やるわ。」

となるわけです。
※あくまでイメージです。

flex-grow

flex-growは親要素の空間が余った場合の、子要素達の伸び具合を調整するプロパティです。

flex-growのデフォルト値は0です。

例えば、下記のようなフレックスボックスの場合、紫色のところが親要素の余った空間になっています。

sample07.png

<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;
}

この余った空間をなくしたいときがあります。

そんなときは.item03flex-growを指定します。

.wrapper .item03{
    flex-grow: 1;
}

sample10.png

.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があるとします。

sample08.png

.wrapper .item01{
    flex-basis:400px;
}

親の空間に余裕がある場合は、400pxまるまる確保されますが、、、

あくまでflex-basisは初期の幅なので、親要素の空間に余裕がなくなれば

sample09.png

400px以下になってしまいます。

ここまでは、flex-basisのときに説明しました。

だけど、時には縮んでほしくない場合もあるでしょう。
そんな時には、その要素にflex-shrink:0;を指定します。

.wrapper .item01{
    flex-basis:400px;
    flex-shrink: 0;
}

sample11.png

こんな感じで、400pxが保たれたままになります。

おわりに

とりあえず、ひととおりフレックスボックスについて理解しておきたいことをまとめてみました。

このほかにも、wrapプロパティなど、コーディングに大事なプロパティがいくつかありますが、ここに書いたことが前提知識としてあれば理解に苦しむことも少ないかなと思っています。

また、改めてフレックスボックスについてまとめてみたのは、個人的にグリッドレイアウトをちゃんと理解したいなと思ったからです。

フレックスボックスとグリッドレイアウトの違いをしっかり理解することで、グリッドの学習も捗るかなと考えた次第です。

参考記事

36
51
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
51