CSS GridとFlexboxを使ってメディアクエリなしでレスポンシブにレイアウトする方法

Advertisement

レスポンシブなレイアウトにはメディアクエリが欠かせないわけですが、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だと以下の画像のようなレイアウトになります。

小、中、大のスクリーンでグリッドが変わるレスポンシブなレイアウトの例(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-grow1を指定して、親要素の幅に余りがある場合、flexアイテムに等分に幅が追加されます
  • flex-shrink0を指定して、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!

About the author

Rriverのステッカーが貼られたMacBookの向こうにいる自分のMemojiの似顔絵

「明日のウェブ制作に役立つアイディア」をテーマにこのブログを書いています。アメリカの大学を卒業後、ボストン近郊のウェブ制作会社に勤務。帰国後、東京のウェブ制作会社に勤務した後、ウェブ担当者として日英バイリンガルのサイト運営に携わる。詳しくはこちら

ウェブ制作・ディレクション、ビデオを含むコンテンツ制作のお手伝い、執筆・翻訳のご依頼など、お気軽にご相談ください。いずれも日本語と英語で対応可能です。まずは、Mastodon @rriver@vivaldi.net Twitter @rriver 、またはFacebook までご連絡ください。