レスポンシブなレイアウトにはメディアクエリが欠かせないわけですが、CSS GridやFlexboxを使えばメディアクエリなしでもレスポンシブなレイアウトが可能です。メディアクエリが全くいらなくなるということはないと思いますが、CSS GridとFlexboxを使えば、メディアクエリの記述を減らす方法があります。しかもコンテンツの幅に合わせて中身のレイアウトを調整するようなエレメント・クエリ的な使い方も、ある程度なら実現できます。
応用すれば今後のレスポンシブなレイアウトのCSSの組み方を変えてしまうような方法です。
※デモはFirefox 58.0.2、Chrome 64.0.3282.140、Safari 11.0.3でテストしています。
CSS Gridを使ったレスポンシブレイアウト
CSS Gridで以下の2つのCSS関数を使うと、メディアクエリなしでレスポンシブなレイアウトが実現できます。
- repeat()(auto-fillまたはauto-fit)
- minmax()
デモ を見てもらうのが早いと思いますが、下図のようなレスポンシブなレイアウトが簡単なCSSで実装できます。
必要なHTMLとCSSは以下のとおりです。
これだけでレスポンシブなレイアウトができちゃうんですね。CSS Gridは、レスポンシブな時代に作られた仕様なだけあって、マルチデバイス対応が組み込まれてるんですね。かなり便利です。
repeat()とminmax()がポイント
ここで、repeat()とminmax()という2つのCSS関数について、少しだけ書いておきます。
- repeat()はグリッドの指定の繰り返しを可能にします
- minmax()は最小値と最大値を指定するCSS関数です
これら2つのCSS関数とauto-fillまたはauto-fitを組み合わせて以下のような記述をすると、display: grid;を指定した親要素の幅に応じてグリッドを自動的に調整して子要素を配置してくれます。
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
リアルなコンテンツでレイアウトした例
上の例だとシンプル過ぎてリアリティがないので、よくありそうなレイアウトのデモも作ってみました。
デモはこちら。
floatとメディアクエリを使う場合
以前「表示件数と高さが変わるブロックの一覧を、画面サイズに合わせてカラム数を変えて表示する方法」という記事で似たようなレイアウトのデモを作ったんですが、同じレイアウトをfloatでやるとメディアクエリが必要になります。また、コンテンツの高さが変わる場合、nth-child()を使ってclearを入れたり面倒なCSSが必要になります。
CSS Gridだとgrid-gapでアイテム間のガッターも簡単に指定できますけど、floatでやるとmarginの調整とか結構面倒です。
デモはこちら。
CSS
参考までに、floatを使った場合のCSSを載せておきます。ほぼ同じようなレイアウトが実現できるんですけど、CSS Grid版の方がシンプルでいいですね。
.float {
border: 1px solid #ddd;
padding: 1%;
margin: 0 0 2em;
width: auto;
overflow: hidden;
}
.float > div {
background: #ddd;
overflow: auto;
padding: 1em;
margin: 2% 2% 3%;
}
.float > div:last-child { margin: 2%; }
@media screen and (min-width: 660px){
.float > div {
width: 48%;
margin: 1%;
float: left;
}
.float > div:last-child { margin: 1%; }
}
@media screen and (min-width: 990px){
.float > div {
width: 31.333333%;
}
}
Flexboxを使ったレスポンシブレイアウト
CSS Grid版とは少しレイアウトが異なりますが、Flexboxでもメディアクエリを使わずにレスポンシブなレイアウトが可能です。Flexboxだと以下の画像のようなレイアウトになります。
CSS Grid版だと全てのアイテムが同じ幅になるんですが、このやり方だと、Medium Screenで2カラムになる際に、5つ目のアイテムが親要素の全幅に、Large Screenで3カラムになる際に、4つ目と5つ目のアイテムが親要素の半分の幅になります。
CSS
CSSは以下のようになります。HTMLはCSS Grid版と同じです(class以外)。
.flexbox {
display: flex;
flex-wrap: wrap;
border: 1px solid #ddd;
padding: 0.4em;
margin: 0 0 2em;
}
.flexbox > div {
background: #ddd;
padding: 1em;
flex: 1 0 300px;
margin: 0.4em;
}
flex-wrapとflexの指定がポイント
display: flexを指定した親要素にflex-wrap: wrapを指定すると、子要素が入りきらない場合は自動で改行してくれます。また、子要素のflexアイテムにflex: 1 0 300pxを指定することで、このレイアウトを実現しています。
flex: <flex-grow> <flex-shrink> <flex-basis>
- flex-basisでベースの幅を300pxに指定
- flex-growに1を指定して、親要素の幅に余りがある場合、flexアイテムに等分に幅が追加されます
- flex-shrinkに0を指定して、flexアイテムが300px以下にならないようにしています
さいごにひとこと
以上、CSS GridとFlexboxを使ったメディアクエリなしのレスポンシブなレイアウトの方法でした!
CSS Gridを使ったレスポンシブなレイアウトの方法は、以前どこかのブログ(どこか忘れてしまいました…)で見かけて気になっていたんですけど、先日公開されたSmashing Magazineの「Using Media Queries For Responsive Design In 2018」という記事でRachel Andrewさんがわかりやすく解説してくれています。
僕にとってはかなり画期的な内容で、嬉しすぎて初めてSmashing Magazineで記事にコメント入れちゃいました。笑
※この記事は「CSS GridとFlexboxを使ってメディアクエリなしでレスポンシブにレイアウトする方法」の転載です。
タイトルおよびリード文はWPJ編集部によるものです。
Copyright ©️ 2018. Ryo Watanabe.