レスポンシブなレイアウトにはメディアクエリが欠かせないわけですが、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は以下のとおりです。
HTML
<div class="cssgrid">
<div>アイテム1</div>
<div>アイテム2</div>
<div>アイテム3</div>
<div>アイテム4</div>
<div>アイテム5</div>
</div>
CSS
.cssgrid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
grid-auto-rows: 1fr;
grid-gap: 0.8em;
border: 1px solid #ddd;
padding: 0.8em;
margin: 0 0 2em;
}
.cssgrid > div {
background: #ddd;
overflow: auto;
min-width: 0;
padding: 1em;
}
これだけでレスポンシブなレイアウトができちゃうんですね。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で記事にコメント 入れちゃいました。笑
Have fun making grids!
2018年2月13日に公開された記事です。
About the author
「明日のウェブ制作に役立つアイディア」をテーマにこのブログを書いています。アメリカの大学を卒業後、ボストン近郊のウェブ制作会社に勤務。帰国後、東京のウェブ制作会社に勤務した後、ウェブ担当者として日英バイリンガルのサイト運営に携わる。詳しくはこちら。
ウェブ制作・ディレクション、ビデオを含むコンテンツ制作のお手伝い、執筆・翻訳のご依頼など、お気軽にご相談ください。いずれも日本語と英語で対応可能です。まずは、Mastodon @rriver@vivaldi.net 、Twitter @rriver 、またはFacebook までご連絡ください。