flexbox

グリッドレイアウトの中でフレックスボックスを使う

─ Guide to page sections ─

完成イメージ
グリッドレイアウトの中でフレックスボックスを使う

Flexboxを習得して行または列方向の1次元レイアウトを簡単に実現できるようにしたい。特にグリッドレイアウトの中で併用して使うことに慣れてくれば、レイアウトはより完全になる。


First

フレックスボックスの概要

CSS グリッドレイアウトはレイアウトを行うための完全なシステムの一部として、 CSS の他の機能と一緒に動作するよう設計されている。

通常フレックスボックスと呼ばれている 「flexible Box Module」 は一次元のレイアウトモデルとして、またインターフェイス中のアイテム間で余白の分配をする機能と強力な位置合わせをする機能を提供するものとして設計された。flexbox は flex コンテナと flex アイテムで構成され、各々に定義されたプロパティに値を指定することができる。

  • container

    display: flex;

    justify-content / align-items

    (align-content / flex-wrap)

    place-content

    align-self / flex

    flex-grow / flex-shrink / flex-basis

コンテナに「display: flex;」と記述するだけで直下のアイテムは以下のような配置を実行する。

1
2
3
4
5

アイテムを一括指定して配置するには、flex コンテナjustify-content と align-items を定義する。

1
2
3
4
5
<div class="container-position-top-2">
  <div class="cercle-1">1</div>
  <div class="cercle-1">2</div>
  <div class="cercle-1">3</div>
  <div class="cercle-1">4</div>
  <div class="cercle-1">5</div>
</div>
    
.container-position-top-2 {
  display: flex;
  height: 80px;
  width: 100%;
  border: 1px dashed #333;
  background-color: #f7f7f7;
  font-size: 10px;
  justify-content: center;
  align-items: center;
  margin-bottom: 16px;
}

長さを定義したい場合、flex プロパティ(flex-grow / flex-shrink / flex-basis)を用いてフレックスアイテムにて指定する。

1
2
3
4
5
<div class="container-position-top-2">
  <div class="cercle-1" style="flex-grow: 0;">1</div>
  <div class="cercle-1" style="flex-grow: 0; flex-shrink: 0; flex-basis: 50%;">2</div>
  <div class="cercle-1" style="flex-grow: 1;">3</div>
  <div class="cercle-1" style="flex-grow: 1;">4</div>
  <div class="cercle-1" style="flex-grow: 1;">5</div>
</div>

アイテムにalign-self:を再設定して配置を変えることができる。

1
2
3
4
5
<div class="container-position-top-2">
  <div class="region cercle-1" style="flex-grow: 0;">1</div>
  <div class="region cercle-1" style="flex-grow: 0; flex-shrink: 0; flex-basis: 50%; align-self: flex-end;">2</div>
  <div class="region cercle-1" style="flex-grow: 1;">3</div>
  <div class="region cercle-1" style="flex-grow: 1;">4</div>
  <div class="region cercle-1" style="flex-grow: 1;">5</div>
</div>

Second

flex propertyの一括指定を使ってアイテムの長さ(横並び)を指定する

アイテムを一括で設定

flex property

flexプロパティは CSS の一括指定プロパティで、フレックスアイテムをフレックスコンテナの領域に収めるために、どのように伸長・収縮させるかをフレックスアイテムに指定する。

/* 値を 3 つ指定: flex-grow | flex-shrink | flex-basis */
flex: 2 2 10%;

flex: initial

"flex: 0 1 auto" と同等

flex: auto

"flex: 1 1 auto" と同等

flex: none

"flex: 0 0 auto" と同等

<'flex-grow'>

省略時の既定値は 1 。 (初期値は 0)

<'flex-shrink'>

省略時の既定値は 1 。 (初期値は 1)

<'flex-basis'>

省略時の既定値は 0 。

flex: の初期値は flex: 0 1 auto;

  • flex-grow: 0
  • flex-shrink: 1
  • flex-basis: auto
A
B
C
.flex-wrapper {
  display: flex;
}
<div class="flex-wrapper">
  <div>A</div>
  <div>B</div>
  <div>C</div>
</div>

flex: 1 や flex: 2; など数値がひとつの場合

flex で指定した数値に単位をつけない場合、flex の値は flex-grow の値をとる。

フレックスコンテナに余白があるときに、伸びてほしければflex-grow: 1;、そうでなければflex-grow: 0;とする。flex: 1;、flex: 2; の場合は flexアイテムは 1 : 2 の割合である。

A
B
C
<div class="flex-wrapper">
  <div style="flex: 1;">A</div>
  <div style="flex: 1;">B</div>
  <div style="flex: 2;">C</div>
</div>

flexの数値が単位無しの 2 つのとき

A
B
C
<div class="flex-wrapper">
  <div style="flex: 1 1; background-color: #f1c0c0; border: 1px dashed #333;">A</div>
  <div style="flex: 2 2; background-color: #c0e5f1; border: 1px dashed #333;">B</div>
  <div style="flex: 3 3; background-color: #e9f1c0; border: 1px dashed #333;">C</div>
</div>

flexの数値が 3 つのとき

flexの値が3つのとき、flex は flex-grow、flex-shrink、flex-basis のショートハンド指定となる。

A
B
C
<div class="flex-wrapper">
  <div style="flex: 1 1 25%; background-color: #f1c0c0; border: 1px dashed #333;">A</div>
  <div style="flex: 2 2 25%; background-color: #c0e5f1; border: 1px dashed #333;">B</div>
  <div style="flex: 3 3 25%; background-color: #e9f1c0; border: 1px dashed #333;">C</div>
</div>

フレックス伸長係数を設定

flex property

このプロパティは、フレックスコンテナー内の残りの空間のうち、どれだけがそのアイテムに割り当てられるか (フレックス伸長係数) を設定する。主軸方向の寸法は、アイテムの幅または高さのどちらかで、 flex-direction の値に依存して決まる。

flex-growプロパティ

A
B
<div class="flex-wrapper">
  <div style="flex: 1; ">A</div>
  <div style="flex: 1; ">B</div>
</div>

flex-growプロパティ + width:

A
B
<div class="flex-wrapper">
  <div style="flex: 1; width: 20%; ">A</div>
  <div style="flex: 1; width: 20%; ">B</div>
</div>

フレックス縮小係数を設定

flex-shrink

親要素にスペースがなくすべての子要素が入り切らない場合、指定のある子要素が他の子要素に対してどれくらい縮小するかを指定する。また、要素を縮めたくないときに指定する。

flexアイテムが親要素の幅を超えるとき、各flexアイテムは均等な幅となる性質がある。そこで flex-shrink を使用すれば、親要素の幅からはみ出た部分を縮小することができる。flexアイテムは flex-shrink の初期値が1であるため、親要素の幅を超える場合は自動的に縮小し、親要素の幅に収まる。

フレックスコンテナに余白がないとき(はみ出るとき)に、縮んでほしければflex-shrink: 1;、そうでなければflex-shrink: 0;とする。

A
B
C
<div style="display: flex; text-align: center; border: 1px dashed #333; width: 300px;">
          <div style="width: 60%; background-color: #f1c0c0; border: 1px dashed #333;">A</div>
          <div style="width: 50%; background-color: #c0e5f1; border: 1px dashed #333;">B</div>
          <div style="width: 40%; background-color: #e9f1c0; border: 1px dashed #333;">C</div>
        </div>

この状態を「flex-shrink:」を使って変えてみる。

A
B
C
<div style="display: flex; text-align: center; border: 1px dashed #333; width: 70%;">
  <div style="width: 60%; flex-shrink: 1; background-color: #f1c0c0; border: 1px dashed #333;">A</div>
  <div style="width: 50%; flex-shrink: 2; background-color: #c0e5f1; border: 1px dashed #333;">B</div>
  <div style="width: 40%; flex-shrink: 3; background-color: #e9f1c0; border: 1px dashed #333;">C</div>
</div>

flex-shrink: 0;

ポイント

「flex-shrink: 0;」を指定すると、縮小されない。

<div class="flex-wrapper" style="align-items: center; width: 100%; height: 100px; padding: 0;">
  <h1 style="height: 80px; color: #fff; font-size: 16px; line-height: 80px; background: green; margin-right: 10px; flex-shrink: 0; padding: 0; margin: 0 0 0 16px;">ポイント</h1>
  <p style="padding-left: 16px;">「flex-shrink: 0;」を指定すると、縮小されない。</p>
</div>

主要部分の初期の寸法を設定

flex-basis

width と同じように子要素の幅の値を指定できる。auto 指定した場合は子要素のコンテンツのサイズが適応される。「flex:」 で指定した数値に単位をつけた場合、flex の値は flex-basis の値をとる。

flex-basis: と width の優先順位

基本的に幅を指定する際は、widthを指定するが、flex-basisを指定した際には、flex-basisプロパティが優先される。flex-basisは、flex-grow、flex-shrinkがついてなければ、widthやheightプロパティと同じになる。

150px
150px
150px
<div class="flex-wrapper">
  <div style="width: 50px; flex-basis: 150px; background-color: #f1c0c0; border: 1px dashed #333;">150px</div>
  <div style="width: 50px; flex-basis: 150px; background-color: #c0e5f1; border: 1px dashed #333;">150px</div>
  <div style="width: 50px; flex-basis: 150px; background-color: #e9f1c0; border: 1px dashed #333;">150px</div>
</div>

flex-basis は max-width によって制限される

flex-basis: 250px;を設定したのに max-width: 100px の制限に達した。したがって、この場合の最終局面はflex-basis: 100px; であり、アイテムは次のようにフレックス コンテナに収まる。

100px
100px
100px
<div class="flex-wrapper">
  <div style="max-width: 100px; flex-basis: 250px; background-color: #f1c0c0; border: 1px dashed #333;">100px</div>
  <div style="max-width: 100px; flex-basis: 250px; background-color: #c0e5f1; border: 1px dashed #333;">100px</div>
  <div style="max-width: 100px; flex-basis: 250px; background-color: #e9f1c0; border: 1px dashed #333;">100px</div>
</div>

flex-basis: の値を%に指定した場合

20%
30%
50%
<div class="flex-wrapper">
  <div style="flex-basis: 20%; background-color: #f1c0c0; border: 1px dashed #333;">20%</div>
  <div style="flex-basis: 30%; background-color: #c0e5f1; border: 1px dashed #333;">30%</div>
  <div style="flex-basis: 50%; background-color: #e9f1c0; border: 1px dashed #333;">50%</div>
</div>

flex: auto = flex: 1 1 auto; の設定の例

この Flexbox の配置の例を使って、このページのセクション 5 のレイアウトを実行。

flex-item
raw-item
<div id="flex-container">
  <div class="flex-item">flex-item</div>
  <div class="raw-item">raw-item</div>
</div>
#flex-container {
  display: flex;
  flex-direction: row;
}
#flex-container > .flex-item {
  flex: auto;
}
#flex-container > .raw-item {
  width: 5rem;
}

主軸上での位置合わせの auto マージン

One
Two
Three
Four
Five
<div class="box-3">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div class="push">Four</div>
  <div>Five</div>
</div>
.box-3 {
  display: flex;
}
.push {
    margin-left: auto;
}

4 つめのアイテムに対して margin-left に auto を設定すれば、先頭の 3 つから分離できる。両側のマージンが取れるだけの余白を取ろうとするために、ブロックが中央に押し出されることになる。


Third

フレックスアイテムを配置する方法

フレックスアイテムを配置するには次の二段階で構築する。

一段階目はフレックスコンテナにてアイテムを一括指定して効率よくアイテムを配置する。

justify-content(主軸)とalign-items(交差軸)プロパティを使うと全てのフレックスアイテムを一括で配置できる。

justify-content

flex-start

先頭寄せ(初期値)

flex-end

末尾寄せ

center

中央寄せ

space-between

両端にアイテムを配置し、アイテムを均等に配置

space-around

両端は半分の間隔をあけ、アイテムを均等に配置

space-evenly

両端も同じ間隔をあけ、アイテムを均等に配置

stretch

各アイテムを均等に配置しサイズが 'auto' であるアイテムは、コンテナーに合わせて引き伸ばす

CSS の justify-content プロパティは、フレックスコンテナの主軸およびグリッドコンテナのインライン軸に沿って、中身のアイテムの間や周囲に間隔を配置する方法を定義する。「flex-grow」が 0 ではないフレックス要素が少なくとも 1 つある場合は利用可能な空間がなくなるので、このプロパティの効果はない。

このプロパティをフレックスコンテナに設定して表示したのが以下の図である。

center

1
2
3
4
5
.container-position-situation-0 {
  display: flex;
  width: 100%;
  height: 80px;
  border: 1px dashed #333;
  background-color: #f7f7f7;
  font-size: 10px;
  justify-content: center;
  align-items: center;
  margin-bottom: 16px;
}

flex-start

1
2
3
4
5
.container-position-situation-1 {
   display: flex;
  width: 100%;
  height: 80px;
  border: 1px dashed #333;
  background-color: #f7f7f7;
  font-size: 10px;
  justify-content: flex-start;
  align-items: flex-start;
  margin-bottom: 16px;

flex-end

1
2
3
4
5
.container-position-situation-2 {
  display: flex;
  width: 100%;
  height: 80px;
  border: 1px dashed #333;
  background-color: #f7f7f7;
  font-size: 10px;
  justify-content: flex-end;
  align-items: flex-end;
  margin-bottom: 16px;
}

justify-content: space-between;

各アイテムは、配置コンテナの中で主軸方向に均等に配置される。隣接するアイテム同士の間隔は同じになる。最初のアイテムは主軸の先頭側に寄せられ、最後のアイテムは主軸の末尾側に寄せられる。

1
2
3
4
5

justify-content: space-around

1
2
3
4
5

各アイテムは、配置コンテナの中で主軸方向に均等に配置される。隣接するアイテム同士の間隔は同じになる。最初のアイテムの前と最後のアイテムの後の余白は、隣接するアイテム同士の間隔の半分の幅になる。

align-items

flex-start

先頭寄せ(初期値)

flex-end

末尾寄せ

center

中央寄せ

stretch

flexboxコンテナのクロス軸の幅に合わせて、flexboxアイテムを伸縮する

CSS の align-items プロパティは、すべての直接の子要素に集合として align-self の値を設定する。フレックスボックスでは交差軸方向のアイテムの配置を制御します。

フレックスアイテムの cross-end 側マージンの端は、ラインの cross-end の端に寄せられる。

フレックスアイテムのマージンボックスは、交差軸上の中央に配置される。アイテムの cross-size がフレックスコンテナより大きい場合は、両方向へ均等にはみ出す。

アイテムのマージンボックスの cross-size が、幅や高さの制約の範囲内でラインと同じになるように拡張される。

二段階目はひとつひとつのアイテムを「align-self」を使って再配置する指定を行うことができる。

align-self:

グリッドコンテナ直下のひとつひとつのアイテムに対して、この align-self:プロパティを使って定義する。「align-self:」を上書きして表示したのが以下の図である。

One
Two
Three
Four

One (Y)align-self: stretch;

Two (Y)align-self: flex-start;

Three (Y)align-self: center;

Four (Y)align-self: flex-end;

また余白を設定したい場合、gapプロパティーを使用できる。1つ指定の場合は行間・列間を同一の値で指定する。2つの場合は、1つ目が行間、2つ目が列間の値になる。

フレックスボックスの実例サンプル

フレックスの入れ子を試す

flexible Box Module
<header style="display: flex; justify-content: space-between; align-items: start;"> <a href="#" class="flexible">flexible Box Module</a>
  <nav class="crumbs">
    <ul style="margin: 0; display: flex;">
      <li class="flexible">1</li>
      <li class="flexible">2</li>
      <li class="flexible">3</li>
      <li class="flexible">4</li>
    </ul>
  </nav>
</header>

フレックスを入れ子にしてアニメーションを試す

<div class="banner">
  <div class="banner_item">
    <p class="banner_title">CSS GRID</p>
  </div>
  <div class="banner_item">
    <p class="banner_title">FLEXBOX</p>
  </div>
</div>
    
.banner {
  display: flex;
  width: 100%;
  background: yellow;
  height: 120px;
}
.banner_item {
  flex-grow: 1;
  color: #fff;
  font-size: 12px;
  color: #fff;
  display: flex;
  justify-content: center;
  align-items: center;
  transition: flex-grow 0.2s;
  cursor: pointer;
}
.banner_item:hover {
  flex-grow: 10;
}
.banner_item:hover .banner_title {
  transform: rotate(0);
}
.banner_item:nth-child(1) {
  background: #FF1493;
}
.banner_item:nth-child(2) {
  background: #6998b9;
}
.banner_title {
  margin: 0;
  transform: rotate(-90deg);
  transition: transform 0.2s 0.2s;
  font-size: 1em;
  color: #fff;
}

フレックスで見出しを作る

flex Box

<h2 class="left-right-line">flexible Box Module</h2>
h2.left-right-line {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 16px;
  height:40px;
  line-height: 40px;
  color: deeppink;
}
h2.left-right-line::before,
h2.left-right-line::after {
  content: '';
  width: 70px;
  height: 1px;
  background-color: deeppink;
}

h2.left-right-line::before {
  margin-right: 30px;
}

h2.left-right-line::after {
  margin-left: 30px;
}

Fourth

例外的な flex-wrap プロパティと align-content プロパティ

flex-wrap

「flex-wrap:」はフレックスアイテムを単一行に押し込むか、複数行に折り返してもよいかを指定するものだ。「flex-wrap: wrap」を指定したものは複数行に折り返す。

「flex: wrap;」は「display: flex;」と共にフレックスコンテナにて使用する。

align-content

複数行にまたがるマルチラインのフレックスコンテナに対してのみ有効であるプロパティが「align-content」である。行間でのスペース分配を制御する。

flexアイテムを折り返したときに上下の配置や余白を指定するプロパティである。align-content はflexアイテムに対して有効なプロパティであるため、display: flex; と併用して親要素に記述する。また折り返したflexアイテムの配置を決定するという性質上、flex-wrap: wrap; もしくは flex-wrap: wrap-reverse; の指定が必要である。

display: flex;
flex-wrap: wrap; (flex-wrap: wrap-reverse;)
align-content: center;

align-content: center;

1
2
3
4
5

align-content: space-around

1
2
3
4
5

align-content: space-between

1
2
3
4
5

align-content: flex-start and flex-direction: column

1
2
3
4
5

Fifth

グリッドの中でフレックスボックスを使う

グリッドレイアウトは全体のレイアウトを掌り、その中の一部の文字列のレイアウト・デザインをフレックスボックスにして作る方法をここで試してみよう。

今回の要件を下に纏めてみてから作業に移る。

  • CSS グリッドでメディアオブジェクトの2 列のボックスを作成する
  • グリッドアイテムのひとつにフレックスボックスを使って文字列をレイアウトする
  • PC ではイメージの横にタイトルと日付を並べる
  • モバイルではイメージを単独で配置し、その下にタイトルと日付を並べる
  • タイトルはモバイルの幅も考えると複数行が必要

レイアウトを整える 1…フレックスボックスを使う

タイトルと日付をアイテムにしてフレックスコンテナを作成する。分かりやすいように背景色とボーダーを表示した。

<div id="flex-container">
  <div class="title-item">
    <h3>CSS grid で作るレイアウトは flexbox と完全に機能する</h3>
  </div>
  <div class="date-item">
    <p>2023.3.26</p>
  </div>
</div>
#flex-container {
  display: flex;
  flex-direction: row; /* 横方向 初期値 */
}
レイアウト-1
CSS grid と flexbox で組んだレイアウト

レイアウトを整える 2

この場合のタイトルには <h3> を、日付には <p> を使っているが、これを「display: inline;」にする。「display: inline-block;」を用いても同様のことができるが、インライン要素の方が設定の箇所が少なく簡単のようだった。

レイアウト-2
インライン要素にする

レイアウトを整える 3

.title-item に「line-height: 1.1; align-self: center;」を加える。

レイアウト-2
タイトルの行間、位置を整える

フレックスボックスをグリッドに組み込むのは容易い。フレックスの用意されたプロパティをどう使って実現するかについては、訓練が必要だろう。

レイアウトを整える 4

デザイン・レイアウトに調整を加える。背景色とボーダーを消す。

完成イメージ
レイアウト・デザインを調整後の表示

inline-block

表示形式について例えば、インラインブロックは要素を横並びにして、横幅・高さや余白を調整したい場面で使用する。デフォルトの幅は、要素の中身の幅に合わせた大きさになる。インラインレベルなので、要素の前後で改行せずに表示される。

内部の表示はブロックボックスと同じ扱いになるため、指定した横幅で改行する。

これで完成である。段落の先頭部分にこういう手法を使い熟せれば、「日付、タイトル、属性、他」などをスポット的にタイトにレイアウトすることが可能になる。

大まかに言って、レイアウトはグリッドで画一的にアウトラインを描き、その中にフレキシブルのレイアウトが塩梅良く収まる、というのが微調整し易い。