CSSで「display: flex」が登場し、IE10を対象ブラウザリストから除外できるようになって要素の横並びの方法の最優先選択肢が「フレックスボックス」になりました。
しかし時々、思い通りにレイアウトできない状況に遭遇します。
毎回、ググって調べる時間を浪費してしまうので小さい壁にぶつかる前に実用的だと思われる部分のみまとめて紹介します。
対象ブラウザからIE11を外さない
「今の時代 IE11なんか使っている人いるの?」
おっしゃるとおりですが、IE11のサポート完全終了は2029年です。
そしてクライアントはIEで確認してくることが結構あります。
エンドユーザーはIEなんか使わないのですが注文者はIEで見てくるのです。
IE11でフレックスボックスはバグがありますので必ずIE11で確認しましょう。一番最初にIE11で確認してもよいくらいです。
IE11でのフレックスボックスで踏みがちな罠
■フレックスアイテムに「box-sizing」が効かない
IE11ではフレックスアイテム(display:flexを設定した要素の直の子要素)に「box-sizing」プロパティが効きません。
paddingの値によってはモダンブラウザ(Chrome等)では収まっている横並びアイテムがカラム落ちします。
■値に「calc()」は使えない
「flex-basis」の値に「calc()」を設定しがちですがIE11は対応していないので意図通りになりません。
※ショートハンドの時のみです。flex-basisを個別に設定するときは使えます。
.NG-flex-item {
flex: 1 0 calc(100% / 3); /* 3等分の幅を確保したいからこのコード書きがち */
}
.OK-flex-item-1 {
flex: 1 0 33.33%;
}
.OK-flex-item-2 {
flex-gorw: 1;
flex-shrink: 0;
flex-basis: calc(100% / 3);
}
■flex-basisの値は単位必須
IE11ではflex-basisに0などの数字だけを設定しても反映されない。px,em,rem,%などを設定しましょう。
自分がよくやってしまうIE11の罠は以上ですがこれらを含め以下の記事が非常に助かります
flexboxのバグに立ち向かう(flexboxバグまとめ) – Qiita
https://qiita.com/hashrock/items/189db03021b0f565ae27
最終行が思い通りにならない・・・
フレックスボックスで記事リストをレイアウトする場合、「justify-content: space-between」で並べると綺麗に並べることができますが、3列の場合で最終行の要素が2個になった場合、両端に要素がよってしまいます。
これを防ぐ方法は条件によってフレキシブル(柔軟)に対応します。
条件:3列に固定したい
方法:フレックスコンテナー(display:flexを適用している包括要素)に疑似要素afterを追加してそのwidthプロパティをフレックスアイテムの幅と同じにする。かつheightプロパティは指定しない(ここポイント)。
条件:4列に固定したい
方法:フレックスコンテナー(display:flexを適用している包括要素)に疑似要素before、afterを追加してそのwidthプロパティをフレックスアイテムの幅と同じにする。かつheightプロパティは指定しない(ここポイント)。before要素にorderプロパティ1を指定する。
条件:5列以上もしくは色々な列数対応
CSSだけでは対応できません。最終行の残りの子要素をjavascriptを使って空の子要素で埋めると一列の子要素の数の変化に対応できます。
javascript(jQuery)でフレックスコンテナーにフレックスアイテムを追加して最終行をかならず左寄せにするスクリプト
<ul class="flex-container">
<li class="flex-item">要素1</li>
<li class="flex-item">要素2</li>
<li class="flex-item">要素3</li>
<li class="flex-item">要素4</li>
<li class="flex-item">要素5</li>
<li class="flex-item">要素6</li>
<li class="flex-item">要素7</li>
<li class="flex-item">要素8</li>
</ul>
$(function() {
var $flexContainer = $('.flex-container');
var flexItems = [];
for(var i = 0; i < $flexContainer.find('.flex-item').length; i++) {
flexItems.push($('<li class="flex-item"></li>'))
}
$flexContainer.append(flexItems);
});