お気に入り

水平方向も垂直方向も!レイアウトのエキスパート「diplay:flex;」を使い倒す

ブロックを左右に並べたいと思ったら、考えるより先に打ち込んじゃってるお馴染みの「display:flex;」。
掴みは横並びのイメージですが、縦並びにレイアウトしたいときにもいい仕事してくれるんです。

cssプロパティ「display」の実態

要素の表示種別やレイアウトぶりを定義するプロパティ、display。

(どうでもいい情報ですが)このサイトのcssの中でも、約200回登場しているとっても働き者の彼です。
全容についてはとてもとても書ききれないので、ここでは割愛しますが、インライン要素をブロック要素に変換して余白を設定したり、要素を中央寄せにしたり、レスポンシブ対応で表示/非表示を切り替えたり・・・と、様々な用途に応じて「display」をマークアップします。

ブロック要素は垂直方向にどんどん流れていきますから、これを横並びにしたいとき真っ先に思いつくのが掲題のこちら、

display: flex;

どどーん!

コーディングでvisual studio codeを使っている方なら、手が覚えているでしょう。
エメット「d→f→tag」で登場してくれるアレです!

display: flex;で横方向に並べる

まずは基本のブロックレベルをご紹介

親ブロックの中に、子ブロックが2つあるデザインを用意します。

See the Pen displayflex-practice_01 by masuming (@Masum1ng) on CodePen.

親要素「.container」のcssにたった1行書くだけ

diplay: flex;

以上!

See the Pen displayflex-practice_02 by masuming (@Masum1ng) on CodePen.

親要素(フレックスコンテナー)に内包する子要素(フレックスアイテム)は、おしなべて横並びに配列されます。

フレックスアイテムを増やしてみる

4つ。健気に並び続けてくれます。

See the Pen displayflex-practice_03 by masuming (@Masum1ng) on CodePen.

8つまで増やしてみました。

See the Pen displayflex-practice_04 by masuming (@Masum1ng) on CodePen.

お~~

ある程度で折り返したいときの『flex-wrap』

並びすぎて、逆に困る、と。

フレックスアイテムは幅30%にしてあるので、3つ並んでコンテナーいっぱいに広がったら、次は折り返してほしいですよね。
そんなときはこの1行をコンテナー側に追加しておきます。

flex-wrap: wrap;

See the Pen displayflex-practice_05 by masuming (@Masum1ng) on CodePen.

3つごとに折り返してくれる、規則正しいレイアウトが完成しました。

「横並び」「縦並び」合わせ技のグリッド表示

同一コンテナー内にありながら、見出しと記事は縦並び、記事内は横並び・・・というわがまま要求にも対応可能。
自分の左右に要素を配したくないときは、「width: 100%;」をマークアップすればよいのです。

See the Pen displayflex-practice_08 by masuming (@Masum1ng) on CodePen.

寄せ具合を決めるのは『justfy-content』

横並びにしたとき、フレックスアイテムを左詰めにするのか、右詰めにするのか、等間隔にするのかをコントロールします。

justify-content: flex-start; /* 先頭に寄せる(デフォルト) */
justify-content: flex-end; /* 末尾に寄せる */
justify-content: space-between;  /* 親要素の横幅いっぱいに広げ、均等に配置 */
justify-content: space-around; /* 均等に配置し、先頭と末尾には均等余白の半値を置く */

これはズバリ、現物を見ていただきましょう。

See the Pen displayflex-practice_13 by masuming (@Masum1ng) on CodePen.

指定されたデザインに応じて、使い分けることができます(※)

垂直位置を制御する『align-items』

display: flex;はデフォルトで、横並びの高さを揃えるという性質があります。
アイテムの中身に差があっても、いちばん高い要素に合わせてくれるんです。

See the Pen displayflex-practice_06 by masuming (@Masum1ng) on CodePen.

なんかよさげですね。

たとえば背景なしで、文字の大きさがバラバラだった場合はどうなるでしょう。

See the Pen displayflex-practice_07 by masuming (@Masum1ng) on CodePen.

う・・・なんか、がったがた

そこで、垂直位置を整えるプロパティを親のコンテナーに追加します。

align-items: center;

See the Pen displayflex-practice_11 by masuming (@Masum1ng) on CodePen.

「垂直方向:真ん中」に揃いました。

ほかに、

【垂直方向:上揃え】

align-items: flex-start;

【垂直方向:下揃え】

align-items: flex-end;

もありますので、デザインに応じて使い分けるとよいでしょう(※)

垂直方向の伸び具合を調整するのも『align-items』

前述のとおり、display: flex;で横並びにすると、高さが揃います。
思わぬ副産物を生む例として、子アイテムが<p>タグと<img>タグでできているコンテナーをdisplay:flexしてみます。

See the Pen displayflex-practice_08 by masuming (@Masum1ng) on CodePen.

しゃ、写真が、テキストの長さにつられて縦に伸びてしまいました。

もしこの現象でお困りの方がいたら、

  1. imgタグにwidth属性とheight属性の実数を入れる(html)
  2. figureなど縦横サイズがコントロールされた親タグでimgを囲う(html&css)
  3. display:flex;のデフォルト=左右の高さを揃える性質を解除する(css)

などの方法で崩れを防ぎます。

ここはdisplay:flex;のページなので、3の方法を使い、不具合を解消することにします。
使うプロパティはやはり、「align-items」。

フレックスボックスの場合、

align-items: stretch;

がデフォルトで設定されていますので、前述の「align-items」プロパティの中から、キーワード「flex-start」を選択してみます。

align-items: flex-start;

See the Pen displayflex-practice_09 by masuming (@Masum1ng) on CodePen.

display: flex;で縦並びを制御する

縦並びレイアウトでできること

ブロック要素はそもそも自然と縦並びになるので、別に謳う必要ないんじゃ?とお思いですよね。

親要素の中に子要素を内包したとき、水平方向に子を配置するのは比較的楽なのですが、垂直方向の真ん中だったり、一番下に配置するのはコツが必要だったりします。

対策はいろいろあるのですが、display: flex;の並びの基準を「縦」にするのも一計となります。

並びの向きを変える『flex-direction』

デフォルトでは、水平方向に並びます。

flex-direction: row;

「flex-direction」で定義される向きは「主軸」
対して、主軸と垂直に交わる軸を「交差軸」と呼びます。

主軸を垂直方向に変えるには、

flex-direction: column; 

と書きます。

「flex-direction」で水平垂直に向きを変えると、主軸が90°回転するので、付随するプロパティ「justify-content」は垂直方向、同じく「align-items」は水平方向・・・と、横並びのときと逆に読み替えなければならなくなるので注意が必要です。

横並び/縦並びの向きを制御する他のキーワードとして、

flex-direction: row-reverse; /* 横並びで、右から左に向かって並べていく */
flex-direction: column-reverse; /* 縦並びで、下から上に向かって並べていく */

という、逆向きバージョンもあります。

【実例】アクションボタンを一番下に並べたい

「並びの向き=縦」を学んだところで、こんなデザインを実現してみます。

フレックスを使わずにレイアウトすると、アクションボタン「Start free」の位置はこうなるはずなので、下辺がガタガタにならないよう一律にボックスの底辺に置くことが目標です。

これを実現するために、

  1. グレーの枠線で囲われた3つの子ブロックを横並びに配するコンテナー
  2. 文字とボタンを縦並びに配する、グレー枠線が親になるコンテナー

の2つのフレックスボックスを作成します。

2のコンテンツは、「テキスト部分」と「ボタン部分」の2つのフレックスアイテムに分けておきます。

カギとなるのは、2のフレックス部分に

flex-direction: column;
justify-content: space-between;

をマークアップすることです。

See the Pen displayflex-practice_14 by masuming (@Masum1ng) on CodePen.

Completed!!

【実例】footerを最下部に置きたい

たとえばメインコンテンツのボリュームが少なくて、こんな見栄えになっているWEBサイト。

ファーストビューの途中でコピーライトが出てきて以下余白・・・。
footerに「position: absolute;」を書いても、他に影響が出て表示が崩れる・・・。
実に残念です(経験者)。

これも縦方向のフレックスでお悩み解決といきたいところです。

原理は既出の【実例】アクションボタンを一番下に統一して置きたいと一緒。今回はそれと合わせて、親ブロックに「最低限の高さ」を追加しておきます。

min-height: 100vh; 

結果は以下のようになります。

【フレックスなし】

See the Pen Untitled by masuming (@Masum1ng) on CodePen.

【フレックスあり】

See the Pen displayflex-practice_12_1 by masuming (@Masum1ng) on CodePen.

・・・と、ここで新たなcss「flex」が登場してきます。

『flex』プロパティで見栄えを完成させる

一括指定できる『flex』プロパティ

の【フレックスあり】を成功に導いているのは、mainタグにスタイリングした1行、

flex: 1;

の功績です。

flexは、3種の「flex-xxxx」を一括指定するためのプロパティで、上述の場合は、

flex-glow: 1;

と同義になります。

・・・然して、「flex-glow」とは何ぞや?

『flex-grow』でコンテナの収め具合を極める

flex:grow;は、フレックスアイテム(フレックスコンテナーに内包する子要素たち)に対して、更に細かい指示を渡すプロパティのひとつになります。

ざっくり、「フレックスさせたときに生じる余白にどう絡むか?」です。

上述の【実例】footerを最下部に置きたいでは、親ブロックの最低限の高さを100vh(表示させているウィンドウのmaxの高さ)にしていますから、何も策を講じなければコンテンツの少ない子ブロック同士には隙間ができてしまいます。
メインコンテンツ部に背景色を付けてみれば、その実態は一目瞭然です。

See the Pen displayflex-practice_12_2 by masuming (@Masum1ng) on CodePen.

「flex-grow」のデフォルト値は「0」で、「伸びない=生じた余白を使わない」の意。

ここで「flex-grow」の値を、

  • header0(デフォルト値)
  • main1
  • footer0(デフォルト値)

と定義することで、mainタグ部分が余白を独り占めすることになります。

結果、メインコンテンツがスカスカでも、ページ内に不自然な余白を生じさせることなく、footerをウィンドウの最下部に収めることができたんですね!

DEMO

grow以外のflexプロパティは?

「フレックスアイテムをどう伸縮させてコンテナーに収めるか?」を牛耳る「flex」一括指定プロパティには「-grow」の他に、

  • flex-shrink
  • flex-basis

があります。

私はほとんど使ったことがない()ので、後日検証ができたら別記事で結果をご報告したいと思います!

また、「float」に興味がある方のために、こんな記事もあります。

ブログランキング参加中

閲覧くださり、ありがとうございます。
当サイトは人気ブログランキングに参加しています。以下のリンクボタンを押してみなさまの清き1票を投じていただけるととっても励みになります。どうぞよろしくお願いいたします。