フレキシブルボックスレイアウト
フレキシブルボックス(可変ボックス)レイアウトは、親要素「flex コンテナ」内の子要素「flex アイテム」を任意の方向にレイアウトできます。また、異なるサイズの画面でも利用可能領域を使って柔軟にレイアウトします。 最近のモダンブラウザは接頭辞のベンダープレフィックスは必要ありません。(2015年 10月)
Contents
- マルチカラムレイアウト風 3 カラムレイアウト例−1
- フレキシブルボックスの指定
display:flex
- flex アイテムの向きの指定
flex-direction
- flex アイテムの可変性の設定
flex
- flex のショートハンド
- マルチカラムレイアウト風 3 カラムレイアウト例ー2(折り返しの例)
- flex アイテムの折り返し指定
flex-wrap
- 方向と折り返しのショートハンド
flex-flow
- flex アイテムの向き
flex-direction
と折り返しflex-wrap
の表示例 - 縦書き日本語の折り返し
- 3 カラムレイアウト例ー3
- 陳列順序プロパティ
order
- flex アイテム整列プロパティ
- flex アイテム整列プロパティによる整列例
- 自動(auto)マージンによる整列
- flex コンテナに適用されないプロパティ
- 絶対配置のflex アイテム
- flex アイテム z方向の重なり順序付け
- Flexbox による CSS レイアウトの厄介な問題と対策
- Flexbox では画像 img タグを囲んだ方がよい?
マルチカラムレイアウト風 3 カラムレイアウト例ー1
3 個の通常フローのボックスを flex
で均等に横並びにする例です。
#box {
border: 1px dashed gray;
display: flex; /* flex コンテナーに指定 */
flex-direction: row; /* 初期値で省略可(左→右)*/
}
#box div {
padding: 20px;
flex: 1; /* flex: 1 1 0px; の省略形 */
}
【HTML】
<div id="box">
<div>
<p>裏から回って婆さんに聞くと・・・・・</p>
</div>
<div>
<p>「御勉強ですか」と丁寧に聞いた。・・</p>
</div>
<div>
<p>「いや、帰ってもらうほど邪魔・・・・</p>
</div>
</div>
フレキシブルボックスの指定 display: flex;
親ボックスの display: flex;
指定により flex コンテナとしてフレキシブルレイアウトを有効にして可変コンテナを作ります。可変コンテナは子要素の flex アイテムを含む可変ボックスになります。
インラインボックスに対しては、display: inline-flex;
があります。
flex コンテナはブロックレイアウトに代わって、新たな flex 整形文脈をつくり flex レイアウトになります。flex アイテムも新たな整形文脈をつくり、ブロックレベルのボックスではなく flex レベルのボックスになります。
flex コンテナが、display: inline-flex;
の場合は、display: inline-block;
と同じように幅や高さが指定できるインライン要素の flex コンテナになります。
flex アイテムのいくつかの例
flex の初期状態で flex アイテムが、ブロックボックス、フロートボックス、匿名ブロックボックス、インライン要素内にブロックボックスが入った場合の flex アイテムのレイアウト例です。
【参考】 CSS Flexible Box Layout Module Level 1 日本語訳の「flex アイテム」の項
/* flex コンテナ */
.container { display: flex; }
/* flex コンテナの飾り */
div, span {
margin: 0.125em;
padding: 0.125em;
border-radius: 0.25em;
color: white;
text-align: center;
}
.container { background: #555; float: left; }
.container > * { background: #888; }
【HTML】
<div class="container">
<!-- flex item: ブロックボックス -->
<div>ブロックボックス<br>item1</div>
<!-- flex item: フロートされた要素:その効果は無視される -->
<div style="float: left;">フロートボックス<br>item2</div>
<!-- flex item: インラインコンテンツの匿名ブロックボックス
(ラッパー要素を持たないのでスタイリングはできないボックス)-->
匿名ブロックボックス<br>item 3
<!-- flex item: インラインの子要素 -->
<span>
item 4
<!-- flex アイテムはブロックの周囲で分割されることはない -->
<q style="display: block">item 4</q>
item 4
</span>
</div>
flex アイテムとしてブロックボックスの他に、フロートボックス、匿名ブロックボックス、インラインボックスもボックスとして並びます。フロートボックスはその効果は無視されます。
インライン内に子要素がある item4 の例からは、「flex アイテムの子要素はブロックの周囲で分割されない」ことが分かります。複数のブロックがあっても分割されて横並びにはならず通常のレイアウトになります。
flex アイテムの向きの指定flex-direction
flex アイテムを横方向か、縦方向かのどちらの方向に伸張、縮小させるかの主軸の方向を下記の値で設定します。初期値は、flex-direction: row;
です。
disply: flex;
設定だけでもすでにこの初期値は設定されていることになります。
プロパティ値 | 説 明 |
---|---|
row |
横方向左→右(初期値 ) |
row-reverse |
逆横方向右→左 |
column |
縦方向上→下 |
column-reverse |
逆縦方向下→上 |
以上は、親要素 flex コンテナに対する設定でしたが、次は子要素の flex アイテムに設定します。
flex アイテムの可変性の設定flex
flex プロパティは、flex アイテム要素の可変性を設定し制御するフレキシブルボックスレイアウトの要になるもので難しいプロパティです。一連の flex アイテムを利用可能範囲を埋めるため、子要素の横幅または高さを可変にするかどうかを指定し、 子要素に割り当てられる比率を示します。 次の3 種類のプロパティを組合せて使用します。
flex-grow
は、親要素 flex コンテナのレイアウト軸方向の余白を子要素の flex アイテムにどれだけ拡大分配するかの、「比率」を指定します。flex アイテムの幅や高さを変更し利用可能な範囲全体を使うことができます。(初期値は "0
")flex-shrink
は、子要素の各 flex アイテムの幅や高さサイズに対して親要素のサイズが足りないとき、オーバーフローを避けるためどこまで縮小するかの、「比率」を指定します。(初期値は "1
")flex-basis
は、width、height
プロパティと同じですが、flex アイテムである場合は、要素のサイズではなく、flex プロパティに基づいて決められた「推奨サイズ」を示し、余白を与えられる前の初期値になります。(初期値は "auto
")
flex のショートハンド
上記の flex-grow、flex-shrink、flex-basis
プロパティ値を一括指定します。
flex: none | [<‘flex-grow’> <‘flex-shrink’>? || <‘flex-basis’>]
CSS 構文記号の ||
は、いずれか 1つは存在するが省略可能で順序は問わないという意味で、?
は、省略可能で 0 回または 1 回出現するという意味です。
flex: none
を除き、基本的に3値を並べますが、flex-basis
以外に1つの値があれば、flex-grow
になります。flex-grow
と flex-shrink
の順序は変えられません。
プロパティ | 説 明 |
---|---|
flex-grow 伸張係数 |
正の可変性を指定する整数または小数部ある実数 省略すると " 1 " です。負は無効 |
flex-shrink 縮小係数 |
負の可変性を指定する整数または小数部ある実数 省略すると " 1 " です。負は無効 |
flex-basis 基底 |
flex アイテムの推奨サイズを width、height プロパティ値で指定します。省略すると " 0px " です。auto の場合、flexアイテムの width、height の値になります。単位の指定は必須です。 |
上表の flex ショートハンド指定の「省略値(初期値)」は、flex アイテムとしての初期値になる前記 flex アイテムの可変性プロパティの初期値と異なるので注意してください。
flex キーワード例
下表は flex プロパティのキーワード例です。flex: none
は、「縮まない」のに対して、flex アイテムとしての初期値になる flex: initial
は、「縮む」ので注意してください。
flex キーワード | 意 味 | |
---|---|---|
initial (初期値) |
flex: 0 1 auto; |
flex アイテムは伸びない、縮む |
none |
flex: 0 0 auto; |
flex アイテムは伸びない、縮まない |
auto |
flex: 1 1 auto; |
flex アイテムは伸びる、縮む |
整数 |
flex: 整数 1 0px; |
利用領域すべてフリー空間として整数比分伸びる、縮む |
【 flex キーワード表示例 】
下図 flex コンテナーの右下を左右にスライドして、IE、MS Edge 以外のブラウザで伸縮動作を確認できます。通常、flex アイテムは最小コンテンツサイズよりも収縮することはありません。ここでは、分かりやすくするため min-width: 0;
指定しています。
.container {
resize: horizontal;
overflow: hidden;
display: flex;
}
.container > div {
box-sizing: border-box;
margin: 5px;
padding: 5px;
width: 60px;
min-width: 0;
background-color: blue;
color: white;
font-family: monospace;
font-size: 13px;
text-align: center;
}
.initial { flex: initial; }
.auto { flex: auto; }
.none { flex: none; }
.n4 { flex: 4; }
.n2 { flex: 2; }
.n1 { flex: 1; }
【HTML】
<div class="container">
<div class="initial">initial</div>
<div class="auto">auto</div>
<div class="none">none</div>
</div>
<div class="container">
<div class="auto">auto</div>
<div class="none">none</div>
<div class="auto">auto</div>
</div>
<div class="container">
<div class="initial">initial</div>
<div class="none">none</div>
<div class="none">none</div>
<div class="initial">initial</div>
<div style="flex: 0 0 150px;">flex: 0 0 150px</div>
</div>
<div class="container">
<div class="n2">2</div>
<div class="n4">4</div>
<div class="n1">1</div>
</div>
<div class="container">
<div class="auto">auto</div>
<div style="flex: 1 0 100px;">flex: 1 0 100px</div>
<div style="flex: 0 1 200px;">flex: 0 1 200px</div>
</div>
ここで冒頭のサンプルに戻って、子要素の flex: 1;
というのは、flex: 1 1 0px;
の略で、下図のように、基底ゼロによる「絶対的 flex」となって 3 個のボックスに対して親要素の利用可能領域すべてを均等に分割して配置します。
flex-grow
は、" 1 " になっていますが、対象が同じなので整数ならば何でもいいようです。flex: auto;
では均等になりません。flex: auto;
は、flex: 1 1 auto;
の意味なので、
flex-basis
は auto
になり、アイテムの内容サイズから得られる基底による「相対的 flex」となります。余った領域が flex 係数比分だけ各アイテムに配分されるので均等にはなりません。
auto
以外の「絶対的 flex 」では、各アイテムがいったん幅ゼロの状態にされるので、利用可能領域すべてがフリー空間にあてがわれた上で、それが flex 係数に応じた比率で各アイテムに配分されます。
従って、flex: auto;
指定の場合に、flex-basis
または、width
を追加すると、「絶対的 flex 」として数値には関係なく flex コンテナすべての領域がフリー空間としてあてがわれ flex 係数に応じて配分するように動作します。
ここでは、各アイテムに同じ値を指定しているので、flex-basis
や width
の数値は何でもよいのですが、後述の「折り返しflex-wrap
」のときには、flex の要となるアイテムの基底値として効いてきます。
このサンプルのような均等分割ではなく各アイテムに個別に異なる数値を指定した場合は、余った領域が flex 係数比分だけ各アイテムに配分されます。
※ 3 個のアイテムの flex 係数は、順に 1, 1, 2 にされている例の図です。 flex 係数 2 を伴うアイテムが他の2倍伸長する参考例ですが、当該例での flex 係数はすべて " 1 " の等量なので、図の " 2 " は " 1 " になります。 画像は、「CSS Flexible Box Layout Module Level 1 日本語訳」より借用しました。
その他に、flex-grow
と width
を指定しても同じように分割します。flex: 1;
のような、「flex: 整数
」キーワード指定は、使いやすくするためによく工夫されていることがわかります
折り返しなし(単ライン flex-wrap: nowrap
) flex 使用例
以上の説明ではわかりにくいので、簡単なサンプルにしたものです。
【参考】折り返し(複ライン flex-wrap: wrap
) flex 使用例
親ボックスに display: flex;
指定で、初期値の flex-wrap: nowrap;
「折り返しなしの単ライン」になりますが、flex-wrap: wrap;
が入ると、後述の「折り返しの複ライン」になります。上記サンプルの親ボックスにそれを追加したサンプルです。
画面サイズ 800px〜 300px〜 で折り返します。
ショートハンド指定の省略時の値(初期値)は、flex プロパティを各々個別に指定する場合の flex アイテムとしての「初期値」とは異なります。flex プロパティを各々指定する通常の初期値は、0 1 auto
ですが、ショートハンド指定の省略時の値は、1 1 0px
です。これは flex ショートハンド指定が、よくある事例により適応できるように未指定の成分を正しく再設定するためのようです。
これら 3 個のプロパティの多くの組合わせのなかで選択性があり過ぎて戸惑いますが、現実にはよくある事例のキーワード指定などで十分対応できるようです。3 個のプロパティ flex-grow、flex-shrink、flex-basis
の必要なものだけを単独で指定する場合は、
省略している他のプロパティ値(初期値 0 1 auto
)を把握しておく必要があります。仕様では 3 個を同時に指定するショートハンド指定を推奨しています。
flex ショートハンド指定の省略した例
前記 flex ショートハンド構文書式により、ショートハンド指定の初期値が 1 1 0px
から、下表の例のように値を 1 個または 2 個に省略したり順序を変えて指定できます。
flex 省略形 |
意 味 |
---|---|
flex: 2; |
flex: 2 1 0px; |
flex: auto; |
flex: 1 1 auto; |
flex: 10em; |
flex: 1 1 10em; |
flex: 2 200px; |
flex: 2 1 200px; |
flex: 200px 2; |
flex: 2 1 200px; |
flex: 1 2; |
flex: 1 2 0px; |
flex: 2 1; |
flex: 2 1 0px; |
マルチカラムレイアウト風 3 カラムレイアウト例ー2 (折り返しの例)
前記の例と同じもので画面の幅が狭い場合に、下に折り返し自動的に再配置する例です。マルチスクリーン、レスポンシブに簡単に対応できます。
#box {
display: flex; /* flex コンテナに指定 */
flex-direction: row;/* 初期値のため省略可(左→右)*/
flex-wrap: wrap; /* 折り返す */
}
#box div {
border: 1px dashed gray;
padding: 20px;
flex: 200px; /* flex: 1 1 200px; の省略形 */
}
flex アイテムの折り返し指定 flex-wrap
可変コンテナのサイズが変更された場合などに、可変アイテムをどう折り返すかを、前記 flex
アイテムの向きを指定する flex-direction
と、次の flex-wrap
プロパティで行ないます。
プロパティ値 | 説 明 |
---|---|
nowrap |
折り返ししない(初期値) |
wrap |
折り返しする |
wrap-reverse |
逆方向で折り返しする |
サンプルでは、flex アイテムの flex: 1 1 200px;
の省略形 flex: 200px;
により、200px の横幅で3個が横並びになるパッディングを含めたサイズ(240×3=720px)より親要素 flex コンテナの幅が小さくなると、
オーバーフローになり、下図のように右端のボックス C が下に折り返します。そして、2列+1行になって横幅が再調整されます。更に画面幅が狭まくなって(240×2=480px)より小さくなると縦に1列3行に並び横幅が再調整されます。
画面幅を少しずつ狭めてみてください。flex コンテナ幅が、720px、480px のポイント付近で変化します。
方向と折り返しのショートハンドflex-flow
flex-flow
プロパティは、方向 flex-direction
プロパティと、折り返しflex-wrap
プロパティのショートハンドです。
flex-flow: <‘flex-direction’> || <‘flex-wrap’>
flex-direction:*
と flex-wrap:*
は、flex-flow:*
でそのまま兼用になり、初期値のflex-direction: row;
と flex-wrap: nowrap;
を除いて11種類の組み合わせになります。
/* flex-flow: <'flex-direction'> */
flex-flow: row;/* 初期値 */
flex-flow: row-reverse;
flex-flow: column;
flex-flow: column-reverse;
/* flex-flow: <'flex-wrap'> */
flex-flow: nowrap;/* 初期値 */
flex-flow: wrap;
flex-flow: wrap-reverse;
/* flex-flow: <'flex-direction'> および <'flex-wrap'> */
flex-flow: row nowrap;/* 初期値 */
flex-flow: row-reverse wrap;
flex-flow: row-reverse wrap-reverse;
flex-flow: column wrap;
flex-flow: column wrap-reverse;
flex-flow: column-reverse wrap;
flex-flow: column-reverse wrap-reverse;
上記サンプルは、display: flex;
で、すでに初期値で flex-direction: row;
が入っているので flex-wrap: wrap;
または flex-flow: wrap
のどちらでもよい。
#box {
display: flex;
flex-flow: wrap;
} /* flex-flow: row wrap; の省略形 */
flexアイテムの向き flex-direction
と折り返し flex-wrap
の表示例
3 個の flex アイテムを flex-direction
で向きを指定、どう折り返すかを flex-wrap
で指定したときの折り返し例をすべて表示したものです。
縦書き日本語の折り返し
縦書き日本語の場合は、書字モードの writing-mode: vertical-rl;
または writing-mode: tb-rl;
(IE 独自仕様)を使用します。
親要素の flex
コンテナを縦書き書字モードにした場合、主軸は自動的に横書きと同じ row
になります。表示は下図のように横書き書字モードを 90 度回転した状態になり、折り返しも 90 度回転した状態になります。
親要素の flex
コンテナは通常の横書き書字モードでレイアウトし、子要素の flex
アイテムを縦書き書字モードにすれば、子要素 flex
アイテム内は縦書きになり、横書きレイアウトでの折り返し動作になります。
flex コンテナに縦書き書字モード指定の折り返し図(HTML ファイル)
flex コンテナに縦書き書字モード指定の flex アイテム折り返し例
flex
コンテナの書字モードを縦書きにして flex-flow: row wrap;
の折り返し例です。折り返して固定されるレイアウトになります。
flex コンテナに縦書き書字モード指定のレイアウト例
※長い間未対応だった Firefoxは、v60 から対応された。(2018年 5月)
縦書き日本語 flex
は flex
アイテムに縦書き書字モード指定
前記の横書き 3 カラムレイアウト例で、子要素の flex
アイテムに縦書き書字モード指定した例です。float: right;
と同じ動きになります。
#box {
display: flex;
flex-flow: row-reverse wrap;/* 右 → 左方向 */
}
#box div {
border: 1px dashed gray;
padding: 20px;
height: 350px;
flex: auto;
writing-mode: tb-rl; /* IE独自仕様 */
writing-mode: vertical-rl;
}
縦書き 3 カラムレスポンシブレイアウト例 (Firefoxは、v60 から対応 2018年 5月)
縦書き日本語の場合は、flex
コンテナは通常の横書き書字モードでレイアウトし、子要素の flex
アイテムに縦書き書字モード指定するほうが分かりやすく現実的のようです。(2017年 4月)
3 カラムレイアウト例ー3
Web でよく使われる 3 カラムレイアウト例です。画面幅が 3 カラム表示には狭すぎる場合、前記の折り返し機能 flex-flow: wrap;
を使用できます。
通常は、メディアクエリを使用して制御しますが、ここでは両方使用して下図のように画面幅に応じて 4 段階にレイアウトが変化するようにしています。
#main {
display: flex;
flex-flow: wrap;/* flex-flow: row wrap; 短縮形*/
} /* flex-wrap: wrap; と同じ*/
#main article {
background: #eee;
flex: 600px; /* flex: 1 1 600px; の省略形 */
}
#main nav {
background: #ddd;
min-height: 50px;
flex: 150px; /* flex: 1 1 150px; の省略形 */
order: -1; /* 表示順を1番目にする */
}
#main aside {
background: #ccf;
min-height: 50px;
flex: 150px; /* flex: 1 1 150px; の省略形 */
}
header h1, nav, aside, footer {
font: normal 20px arial, sans-serif;
padding: 10px;
}
【HTML】
<body>
<header>
<h1>Header</h1>
</header>
<div id="main">
<article>
<p>裏から回って婆さんに聞くと・・・・</p>
</article>
<nav>Nav</nav>
<aside>Aside</aside>
</div>
<footer>Footer</footer>
</body>
ソースドキュメントは主コンテンツ部の article
を最初にしているので、通常フローでは article
が最初に表示されますが、ナビボックスを最初にして左側に配置するためナビボックスに後述の order
プロパティ order: -1;
を指定しています。
また、例ー2 と同じように画面幅が狭くなった場合に折り返したいので、親要素に flex-flow: wrap;
を指定し 3 個の子要素の flex-basis
には、flex アイテムとしての推奨値の幅を指定します。それを確保しながら利用可能範囲を超えた余白分を分配する比率の、
flex-grow
は、すべて " 1 " にして同じにしています。
画面幅を狭めたときの最初の変化は、画面幅が flex アイテム幅の合計がパッディング(nav, aside
の10px )を含め、(170px+600px+170px)=940px より狭くなるとき、aside
が折り返し、次は(170px+600px)=770px より狭くなるとき、article
が nav
の下に折り返します。
最後は、画面幅が 640px 以下のとき flex アイテムの表示順を order: 0;
の初期値に戻してソースのドキュメント順になるように下記のメディアクエリで設定しています。ここは必要ないかもしれませんが参考例です。
@media all and (max-width: 640px) {
#main {
flex-direction: column;/* 縦方向に戻す(上→下)*/
}
#main article, #main nav, #main aside {
order: 0; /* ドキュメントの順番に戻す */
}
#main article {
min-height: 1100px;/* IE 高さ認識不具合バグ対策 */
}
#main nav, #main aside {
max-height: 50px;
}
}
画面幅を少しずつ狭めてみてください。画面幅が、940px、770px、640px のポイント付近で変化します。1000px以上の画面でないと最初の 3 カラムは表示されません。
折り返す前の両サイドカラム幅を固定幅にする
上記の例では flex-basis
は、すべて " 1 " の状態なので余白部分は 3 カラムに等しく配分されますが、カラム article
だけ値を大きく " 100 "以上くらいにして余白部分の配分をひとり占めするようにすると、折り返す前の両サイドのカラム幅は追いやられ 170px の幅に固定された動作になります。
#main article {
background: #eee;
flex: 600px;
flex: 100 600px; /* flex: 100 1 600px; の省略形 */
}
以上の flexbox レイアウト例から、マルチカラムレイアウト(段組みレイアウト)と同じように、「メディアクエリを使用しなくてもマルチスクリーン、レスポンシブに対応できる」ことになります。
メディアクエリを使用すれば更に複雑な制御が可能になります。また、従来 float
や、display:table
などを使用していたナビメニューやドキュメント内部の小規模レイアウトなどにも簡単に置き換えできます。
陳列順序プロパティorder
flex アイテムの表示順序を視覚的な理由によりソースドキュメント順から変更するものです。「flex アイテム」と、後述の「grid レイアウトアイテム」にだけ使えます。値は整数で初期値は " 0 " です。 上記の例で、ナビボックスに " −1 " を指定していますが、他のアイテムは初期値の " 0 " なので1番目になります。
order
プロパティによって flex アイテムの表示順をソースドキュメント順とは無関係に自由に設定できます。
flex アイテム整列プロパティ
flex アイテムを並べて伸縮し折り返しなどの flex 処理後に、flex コンテナ内で主軸方向と交差軸方向に残されたフリー空間の配分や収納処理をする整列プロパティです。
従来のボックスレイアウトでは難しい縦横、両方向の中央寄せや縦横の両端寄せなどを逆順も含めて下表のプロパティで簡単に行うことができます。
プロパティ | 属性値 |
---|---|
justify-content |
flex コンテナに設定し flex アイテムを主軸方向に整列flex-start | flex-end | center | space-between | space-around |
align-items |
flex コンテナに設定し flex アイテムを交差軸方向に整列flex-start | flex-end | center | baseline | stretch |
align-self |
align-items で、すでに定まった個々の flex アイテムに設定し個別に上書き整列flex-start | flex-end | center | baseline | stretch | auto |
align-content |
折り返し配置した複ライン flex コンテナの交差軸に余った空間があるときにコンテナ内で整列し、単ライン flex コンテナに対しては効果はない。flex-start | flex-end | center | stretch | space-between | space-around |
flex アイテム整列プロパティによる整列例
下図は初期値の方向、flex-direction: row;
複ラインの折り返しは flex-wrap: wrap;
状態の flex アイテムの整列プロパティによる整列例です。
方向を row-reverse、column、column-reverse
に、折り返しは wrap-reverse
に一部の CSS 変更で他に nowrap
以外で 8 種類の整列パターンが確認できます。
使いたいレイアウトパターンが見つかるかもしれません。ち〜とシートにもなりますよ。
.container {
max-width: 1000px;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.wrapper-1 {
border: 1px dotted gray;
margin-left: 5px;
width: 180px;
}
.wrapper-2 {
border: 1px dotted gray;
margin-left: 5px;
width: 150px;
}
.box { /* 親要素 flex コンテナ */
display: flex;
flex-direction: row;/* row-reverse, column, column-reverse */
height: 180px; /* に変更してみて下さい */
}
.box-wrap { /* 複ライン align-content 用コンテナ */
display: flex;
flex-direction: row;/* row-reverse, column, column-reverse */
flex-wrap: wrap; /* wrap-reverse に変更してみて下さい */
height: 180px;
}
.box div, .box-wrap div {/* 子要素 flex アイテム */
color: #fff;
background: #38f;
text-align: center;
margin: 5px;
padding: 6px;
} /* column のときは height → width に */
.align div:nth-child(1) { min-height: 40px;}
.align div:nth-child(2) { min-height: 70px; background: #3cf;}
.align div:nth-child(3) { min-height: 30px;}
/* ボックス D は高さ指定なし*/
【HTML】
<h3>1、主軸方向の整列 justify-content</h3>
<article class="container">
<section class="wrapper-1">
<h4>flex-start</h4>
<div class="box" style="justify-content: flex-start;">
<div>A</div>
<div>B</div>
<div>C</div>
</div>
</section>
・・・(以下、省略)
</article>
自動( auto )マージンによる整列
通常のブロックボックスフローの下での自動マージンは、margin-left: auto; margin-right: auto;
の横方向だけですが、flex アイテムでは margin-top: auto; margin-bottom: auto;
の縦方向も加わり、まとめて上下左右の margin: auto;
ができます。(IE は未対応)
flex アイテム上の自動(auto)マージンの効果
flex アイテム上での自動( auto )マージンは、flex 基底、flexible 長さの計算を行なう間は " 0 " に扱われ、flex アイテム整列プロパティによる整列などの flex 処理後に正のフリー空間の下で自動マージンによる整列が行われます。従って、自動マージンが優先されるため各種整列プロパティによる効果はなくなります。
各種の整列プロパティの補助として自動マージンを併用することで、flex アイテム整列プロパティによるレイアウトの範囲が広がります。
auto マージンによる flex アイテムの整列例
flex アイテム整列プロパティ設定なしの初期値、水平方向 justify-content: flex-start;
、垂直方向 align-items: stretch;
の状態で、前記 flex アイテム整列プロパティによる整列例を自動 auto マージンで置き換えてみた例です。
flex アイテムに個別に auto マージンを設定することでも、row
方向での align-items: baseline;
は難しいですが他の大部分を行なうことができます。(下記 CSS は一部分)
【HTML】
<h3>1、主軸方向の整列 justify-content に該当</h3>
<article class="container">
<section class="wrapper-1">
<h4>flex-end</h4>
<div class="box">
<div style="margin-left: auto;">A</div>
<div>B</div>
<div>C</div>
</div>
</section>
<section class="wrapper-1">
<h4>center</h4>
<div class="box">
<div style="margin-left: auto;">A</div>
<div>B</div>
<div style="margin-right: auto;">C</div>
</div>
</section>
・・・(以下、省略)
</article>
自動マージン auto による flex アイテム整列例 (IE は未対応)
auto マージンによる上下左右中央揃えの例
flex アイテム整列プロパティによるものと、IE は未対応ですが auto マージンによる場合の上下左右中央揃えの CSS 例です。どちらも上下左右中央揃えが簡単にできます。子要素を個別に適用する場合には flex アイテムに margin: auto;
だけで便利です。
どちらも flex アイテム整列プロパティは設定なしの初期値の状態で、body { height: 100vh; margin: 0; }
を追加し、box セレクタの高さを 100vh
または 100%
にすれば画面中央になります。
<div class="box">
<p>Flex auto マージンでど真ん中!</p>
</div>
.box {
height: 300px;
background: #eee;
display: flex;
justify-content: center;
align-items: center;
}
p {
color: #fff;
padding: 10px;
background: #38f;
}
.box {
height: 300px;
background: #eee;
display: flex;
}
p {
color: #fff;
padding: 10px;
background: #38f;
margin: auto;
align-self: center;/*IE対策*/
}
flex アイテムに auto マージンよる上下左右中央揃えの例
flex コンテナに適用されないプロパティ
flex コンテナは flex アイテムとともに、新たな flex 整形レイアウトを確立します。 例えば、浮動体 float が flex コンテナ内に侵入することはなく、入っていれば無視します。
flex コンテナのマージンとその内容の「マージンの相殺」はありません。flex コンテナは、ブロックコンテナと同じように自身の「包含ブロック」を形成します。flex コンテナはブロックコンテナではないので、
ブロックレイアウトを前提にした下記のプロパティは、flex レイアウトでは適用されません。overflow
プロパティは適用されます。
マルチカラムモジュール(2017年 10月 仕様改定)column
プロパティ- 浮動体
float
プロパティ、clear
プロパティ - flex アイテム上の
vertical-align
プロパティ - 擬似要素
::first-line / ::first-letter
flex コンテナ内でマルチカラム column
プロパティを使用した例
2分割した flex コンテナ内で、マルチカラム「段抜き」プロパティ column-span: all;
を使用したマルチカラムレイアウト例です。(参考)
カラム要素を分割して column-span: all;
を使ってみる (Firefox は v71 から対応)
float
と flex
の併用で簡単マルチデバイス/ブラウザ対応 ?
IE9 以前の float
で横並びボックスレイアウトを、flex
に置き換えてマルチ(クロス)ブラウザ対応する場合は、IE5〜IE9 だけに機能する IE 独自機能の「条件付きコメント」を HTML 内に記述して CSS を切替えるようにしますが、
上記 flex コンテナの特性から、「float には必須の width 指定も含めて、float と flex を同じセレクタに設定してもそれぞれ独立した動作になる」ため、周辺のレイアウトに影響しなければ、条件付きコメントで分離する必要ありません。
マルチブラウザ対応の必要性はともかく、簡単に IE 以外のブラウザにも flex 未対応対策ができます。
下記の例では上段セレクタの基底値は 800px で、下段セレクタは 600px になります。
#flex-item-1 {
flex: 800px; /* flex 基底値 800px */
float: left; /* flex としては無視 */
width: 600px; /* flex としては無視、float 幅 600px */
}
#flex-item-2 {
flex: auto; /* flex 基底値は width: 600px */
float: left; /* flex としては無視 */
width: 600px; /* flex の基底値、float 幅 600px */
}
絶対配置の flex アイテム
絶対配置された flex アイテムの静的位置は、コンテナーの中の唯一のflex アイテムであったかのように配置されます。フロー外なので flex レイアウトには関与しません。
静的に配置された絶対配置ボックスの整列には、配置の起点になるブロック始点(オフセット)が利用されます。例えば、align-self: center;
の場合、コンテナーの交差軸で中央寄せにすることになりますが、絶対配置されたボックスは固定サイズと見なされるので、
stretch
は flex-start
と同じになります。絶対配置の例は、次の「z方向の重なり順序付け例 」を参照してください。(2018年 12月)
flex アイテム z方向の重なり順序付け
flex アイテムは、position
が static
であっても、relative
であったときと同じように、z-index
値により重なり順序付けができます。
絶対配置を含む flex アイテム z方向の重なり順序付け例
下図は、flex コンテナーに絶対配置ボックスと、マイナスマージンで重なるようにしたボックスを並べた例です。絶対配置ボックスは、flex レイアウトには関与しませんが、IE は旧仕様(2012年)のままなので、位置決めオフセット値(top
,right
,bottom
,left
)の初期値(auto
)の決め方が異なるようです。
<div class="container">
<div class="box">
<div class="absolute-1">Absolute Box<br>z-index: 3;</div>
<div class="box-1">Box-A<br>z-index: 2;</div>
<div class="box-2">Box-B<br>z-index: 1;</div>
</div>
</div>
【CSS 】body {
font-family: Arial, sans-serif;
}
* {
margin: 0; padding: 0;
box-sizing: border-box;
}
.container {
max-width: 700px;
margin: 0 auto;
}
.box{
position: relative;
display: flex;
justify-content: space-between;
text-align: center;
}
.absolute-1 {
position: absolute;
top: 25px;
width: 250px;
height: 150px;
background-color: #fdd;
border: 2px dashed red;
opacity: 0.8;
z-index: 3;
}
.box-1 {
width: 600px;
height: 150px;
margin-top: 50px;
background-color: #cfc;
border: 2px dashed black;
opacity: 0.8;
z-index: 2;
}
.box-2 {
width: 500px;
height: 100px;
margin-left: -500px;
background-color: #ffc;
border: 2px dashed blue;
opacity: 0.8;
z-index: 1;
}
絶対配置を含む flex アイテム z方向の重なり順序付け例
散らかしタイプフォトギャラリー例
写真を傾斜させたことによりエッジが重なるフレキシブルボックスレイアウトを使用したメディアクエリなしのシンプルな CSS レスポンシブフォトギャラリー例です。
Flexbox による CSS レイアウトの厄介な問題と対策
最近、Flexbox によるレイアウトの Web をよく見かけるようになりました。それらのほとんどは、「flex アイテム整列プロパティ」を使用したレイアウトです。一方で、「伸縮性(flex 性)」を利用したものは少ないようです。 メディアクエリを使用しないでコンテンツベースで連続的にレスポンシブにできるのですが、理解しにくいのと、次のような厄介なことがあるからかもしれません。その対策の一例をご紹介します。(2019年 2月)
厄介な最後のボックス
問題は最後のボックスで起こります。前記の「 3 カラムレイアウト例ー2(折り返しの例)」のように、折り返したボックスは空きスペース全体に広がり、折り返し始めは下図の左側(緑色)のように横長ボックスになります。狭い画面サイズでは同じサイズになりますが、下図の右側(青色)のように、いつも上段のボックスと同じくらいのサイズにしたい場合があります。
対策
擬似要素 :after
を使用して最後のボックスの後に、配置されたボックスと同じように伸縮する空の flex アイテムを追加し、最後のボックスのスペース配分量を分け合い伸び過ぎないよう強制的に空きスペースを制限するようにします。(上図の赤色点線部分)
.container:after {
content: "";
flex: 150px;/* marginを含めてflex: 160px;でも可 */
margin: 5px;
}
flex パラメーターは、margin
を含めて配置ボックスと同じにします。領域だけを確保するので margin
指定なしの flex: 160px;
でも同じです。
折り返し 3 カラムレイアウト例
下図 flex コンテナーの右下を左右にスライドして、IE、MS Edge 以外のブラウザで折り返し動作を確認できます。
<div class="container">
<div></div>
<div></div>
<div></div>
</div>
【CSS 】body {
max-width: 600px;
}
.container {
display: flex;
flex-wrap: wrap;
}
.container > div {
flex: 150px;
margin: 5px;
height: 25px;
background-color: blue;
}
.container:after {
content: "";
flex: 150px;
margin: 5px;
}
折り返し3 カラムレイアウト例 (上記CSS値と異なる全画面用)
【 gap プロパティを使用した場合 】
最近のブラウザは、Grid レイアウトと同じように gap
プロパティが使用できるようになりました。上記の margin
を gap
プロパティに置き換えた例です。コンテナのpadding
は、margin
の例に合わせるものです。(2021年 3月)
body {
max-width: 600px;
}
.container {
display: flex;
flex-wrap: wrap;
gap: 10px;
padding: 0 5px;
}
.container > div {
flex: 150px;
height: 25px;
background-color: blue;
}
.container:after {
content: "";
flex: 150px;
}
最後のボックスの折り返し方
【 3 カラム折り返し 】
上記の3 カラムでは、空きスペースを制限するために追加した flex アイテムの flex 伸縮パラメーターは、配置ボックスと同じにしているので、空きスペースを半分ずつ分け合い配置ボックス幅は上段と同じ幅になります。
【 4 カラム折り返し 】
4 カラムになると、最初の折り返しでは下図 B のようにコンテナ領域の半分になります。以降、画面サイズが狭くなると上段と同じサイズのボックスになります。カラム数が更に多くなるとコンテナ領域の半分のサイズからしだいに上段と同じサイズとなって折り返します。
4 カラムの場合に折り返しボックスを上段ボックスと同じサイズにする場合は、下図 C のように領域だけの追加ボックスの flex パラメーター flex-grow
、flex-basis
と、左右マージンを 2 倍にして 2 個分の大きさにすると上段のボックスサイズで折り返すようになります。
更にカラム数が増えた場合に同じようにすると、最初に折り返したときは、1個分のサイズになりますが画面サイズが狭くなると追加ボックス自身が先に折り返すため制限カラム数が 1 個ずつ減り、しだいに元の無い状態に移行していくので 1 カラムボックスずつの折り返しにはなりません。4 カラムが限界になります。
【 5 カラム以上での折り返し 】
5 カラム以上の数量で折り返しの最後の行の空きスペースが大きい場合は、3 カラムのときと同じように追加した flex アイテムのflex-basis
は配置ボックスと同じにして、flex-grow
だけ大きくして折り返したボックスの空きスペースを狭くして上段のボックスサイズに近づけることはできますが、あらゆる表示領域で同じにすることは難しいです。
初期表示ですでに折り返しているカラムで、「最後の行が折り返したとき上段のカラム数が3 カラムか、4 カラムになるようにブレークポイント flex-basis
値を調整する」と、全体のカラム数が多くても最後の行を横長でなく上段のカラム幅と同じにすることは可能です。
Flexbox ではなく CSS Grid レイアウトにすると、各カラム幅が等しい場合にのみカラム数に無関係にレイアウトできます。
折り返し4 カラムレイアウト例
上図 C のように、追加した領域だけの flex アイテムボックスが 2 個分になるように flex パラメーター flex-grow
、flex-basis
と左右マージンを 2 倍にします。
併せて、CSS Grid レイアウトの例としてブレークポイントが同じになるようにflex-basis: 120px
に左右マージン 5px を含めて minmax
関数の最小値を(120px + 10px)に設定した例です。IE は旧仕様のため未対応です。
下図コンテナの右下を左右にスライドして、IE、MS Edge 以外のブラウザで折り返し動作を確認できます。
Flexbox layout
CSS Grid layout
<h2>Flexbox layout</h2>
<div class="container">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<h2>CSS Grid layout</h2>
<div class="container-grid">
<div></div>
<div></div>
<div></div>
<div></div>
</div>
【CSS 】
body {
max-width: 600px;
}
/* Flexbox layout */
.container {
display: flex;
flex-wrap: wrap;
}
.container > div {
flex: 120px;
margin: 5px;
height: 25px;
background-color: blue;
}
.container:after {
content: "";
flex: 2 240px;/* flexパラメーターと左右marginを2倍にする */
margin: 5px 10px;
}
/* CSS Grid layout */
.container-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
}
.container-grid > div {
margin: 5px;
height: 25px;
background-color: blue;
}
折り返し4 カラムレイアウト例 (上記CSS値と異なる全画面用)
【 gap プロパティを使用した場合 】
最近のブラウザはgap
プロパティが使用できるようになったので、上記のmargin
を gap
プロパティに置き換えた例です。前記と同じように追加した領域だけのflex アイテムボックスが 2 個分になるように flex パラメーターを 2 倍にし、flex-basis
に gap
分を加えます。コンテナのpadding
は、margin
の例に合わせるものです。(2021年 3月)
body {
max-width: 600px;
}
/* Flexbox layout */
.container {
display: flex;
flex-wrap: wrap;
gap: 10px;
padding: 0 5px;
}
.container > div {
flex: 120px;
height: 25px;
background-color: blue;
}
.container:after {
content: "";
flex: 2 250px; /* flexパラメータを2倍にしgap 10pxを加える */
}
/* CSS Grid layout */
.container-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
gap: 10px;
padding: 0 5px;
}
.container-grid > div {
height: 25px;
background-color: blue;
}
考察
メディアクエリを使用しないことを前提に、Flexbox の伸縮性を利用したレイアウトの不具合に対する対応例を記述しました。カラム数が 3 〜 4 カラムくらいの折り返しには効果がありそうです。
カラム数が多く折り返しスペースが広い場合、折り返し制限用ボックスの flex-basis
を配置ボックスと同じにして、伸張係数 flex-grow
だけを大きくすると上段のボックス幅に近づけられますが調整が難しくバラバラ感が出てきます。伸張しない flex-grow: 0;
の状態で利用する「flex アイテム整列プロパティ」による整列は、充実しているので必要に応じて使い分けられます。
Flexbox では画像 img タグを囲んだ方がよい?
画像img
はインライン要素です。内在サイズを持ち文書スタイルに影響されない「埋め込み要素」です。img
タグだけでも表示できますが、p、div
や span
タグなどで囲んで使用するのが一般的です。では、「Flexbox ではどうなのか?」についての内容です。Flexbox を使用する上で意外と気付かなかったことがわかります。
下図のような、Web ではよく見られるパターンの画像とテキストを横に並べた例で検証します。(2020年 1月)
画像アイテム img タグを囲まない例
画像 img
タグを囲まないで、画像表示サイズも指定しない例です。縦方向の整列プロパティ align-items
が初期値のstretch
状態ではボックスの幅が狭くなれば画像は下に伸びるので align-items: flex-start
を指定しています。
この場合は、Firefox では画像が縮小します。画像サイズを指定すると、Chrome、IE、が縮小するなどブラウザによって異なります。
Firefox は v.83 から縮小しなくなりました。画像サイズをオリジナルサイズより大きく指定すると、Firefox は、縦横比を維持した横幅に縮小します。Chrome は、画像オリジナル幅に縮小します。画像をオリジナルサイズで表示する場合は、Firefox、Chrome どちらも問題ありません。(2020年 11月 補足訂正)
Firefox 84、Chrome 88 から画像サイズをオリジナルサイズより大きく指定しても、縮小しないで指定サイズで表示されるようになりました。
従って、下記の「画像サイズをオリジナルサイズより大きくする場合」の項で flex: none;
指定は必要なくなりました。
画像表示サイズを指定しないでオリジナルサイズで表示する場合は、ボックスの幅が狭くなると縦方向が下に伸びるので align-items: flex-start;
は必要になりますが、img
タグを他のタグで囲まなくても特に問題はなくなりました。(2021年 1月 補足訂正)
<div class="box">
<img src="./image/forget-f6.gif" alt="ワスレナグサ">
<div>
<h3>ワスレナグサ</h3>
<p>ヨーロッパ原産で日本に渡来したのは明治時代です。「Forget me not」
という英語名でとても美しい名前の花です。</p>
</div>
</div>
【CSS 】
* { margin: 0; padding: 0; }
.box {
display: flex;
align-items: flex-start;/* 画像が下に伸びないように */
padding: 10px;
line-height: 1.5;
}
.box img {
margin-right: 10px;
}
h3 {
margin-bottom: 10px;
}
img タグを囲まないで画像とテキストを横並びにする Flexbox 例
【画像サイズをオリジナルサイズより大きくする場合(Chrome 87、Firefox 83 以前)】
画像を含む flex アイテムは、初期値のflex: initial
状態のflex: 0 1 auto
なので img
のスタイルに flex-shrink: 0
または flex: none
を指定します。ショートハンド指定の後者が分かりやすくスマートです。画像の表示サイズを指定しているので、縦方向の整列プロパティ align-items: flex-start;
は不要になります。
.box img {
flex: none;/* flex-shrink: 0; でも可 */
margin-right: 10px;
}
画像サイズをオリジナルサイズより大きくする場合は、これでブラウザによる表示の違いはなくなります。もう少しスマートにしたいので、本題の画像アイテム img
タグを囲んだ例です。
画像アイテム img タグを囲む例
img
タグをインライン要素かブロックレベル要素のタグで囲んだ例です。そのタグを何にするかは文書スタイルに合うようにします。画像表示サイズも入れます。サイズ指定がないと画像を読み終わってからレイアウトが確定するので表示スピードが遅れます。
画像サイズを指定しなくても下に伸びないので、縦方向の整列プロパティ align-items: flex-start;
は必要ありません。画像オリジナルの内在サイズが認識されたことが分かります。 画像サイズをオリジナルサイズより大きく指定しても縮小しません。真ん中や最下部に配置したい場合は、center
や flex-end
を指定できます。
<div class="box">
<span><img src="./image/forget-f6.gif" alt="ワスレナグサ"
width="157" height="103"></span>
<div>
<h3>ワスレナグサ</h3>
<p>ヨーロッパ原産で日本に渡来したのは明治時代です。「Forget me not」
という英語名でとても美しい名前の花です。</p>
</div>
</div>
【CSS 】
* { margin: 0; padding: 0; }
.box {
display: flex;
align-items: flex-start;
padding: 10px;
line-height: 1.5;
}
.box img {
margin-right: 10px;
}
h3 {
margin-bottom: 10px;
}
img タグを囲んで画像とテキストを横並びにする Flexbox 例
考察
代表的なブラウザの Chrome、Firefox は、迅速な対応で Flexbox での img
要素の表示が更新され、img
タグを他ののタグで囲まなくても特に問題はなくなりました。ここでは、「Flexbox は最小コンテンツサイズより縮小しない」ことを、img
タグで挿入する画像の表示で確認することが主旨でした。
img
タグは、終了タグがない、子要素をもたない空要素なので、文書スタイルに合うタグで囲むことでインライン要素かブロックレベル要素なのか確定し、画像の内在サイズが確定するのでimg
タグは囲んだ方がよいと個人的には思いますが、Flexbox で最近のブラウザの対応では、img
タグを囲まなくても内在サイズの横幅は認識するようになり、画像サイズをオリジナルサイズより大きく指定しても縮小しなくなりました。(2021年 1月 補足訂正)
HTML5 では、インライン要素とブロックレベル要素の概念はなくなり、「カテゴリ」と「コンテンツ」モデルに分類されましたが、文書構造は同じなので本質的には変わりません。
画像以外の通常ボックスの場合は、縦横の空きスペースを埋めて縮小するので min-width
指定や、固定サイズには flex: none
と width
指定が必要になります。