CSSでメディアクエリはもう必要ないかも -メディアクエリなしで実装するテクニックのまとめ

Webサイトやアプリをレスポンシブ化するためにメディアクエリに頼っているのであれば、CSSの機能を見直して、昔ながらのブレークポイントを新しい流動的なアプローチで実装ができないか検討する時期かもしれません。

CSSの実装はデバイスベースからコンテンツベースに移行しているのが現状です。grid, flexbox, vh, vw, calc, clamp, min, maxなど、CSSの機能を使用してレスポンシブ対応にするテクニックを紹介します。

CSSでメディアクエリはもう必要ないかも

You Probably Don't Need Media Queries Anymore
by Kathryn Grayson Nanz

下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。

はじめに

古き良き時代のWeb制作ではレスポンシブなWebサイトやアプリを制作する場合、特定のデバイスのブレークポイントに基づいてメディアクエリを定義し、それぞれのサイズに合わせてコンテンツを作り直すことを意味しました(本当の昔はテーブルレイアウトだったとコメントでありますが、私もそれを覚えていますし、最悪でした)。

そして、デバイスのブレークポイントを容易にするために、Bootstrap、SkeletonなどのCSSフレームワークが登場しました。ブレークポイントをすべて記述するのは大変な作業だったからです。

さまざまな大きさや形のデバイスが登場するにつれ、メディアクエリの定義に関するベストプラクティスはデバイスベースからコンテンツベースに移行しているのが現状です。ブレークポイントの時代は終わり、フルード(流動的)デザインの時代が到来したのです。

あるポイントに到達すると新しいレイアウトに切り替わるのではなく、コンテンツは常に利用可能なスペースの量に基づいて最適化される必要があります。

ありがたいことに、CSSも大きく進化しました。多くのデベロッパーはレスポンシブ対応のためにメディアクエリを1つまたは複数定義することに慣れてしまい、その習慣が抜け出せないままになっています。しかし、grid, flexbox, vh, vw, calc, clamp, min, max, aspect-ratioなどのCSSがある現在、メディアクエリに頼る必要はありません。

この記事では、大局的なレイアウトから小粒の単位にいたるまで順を追って解説したいと思います。古いスタイルシートはリファクタリングが可能です。わたし達はそれらのテクニックを使用できます!

大局的なgridとflexbox

まずは、最もポピュラーなレスポンシブの表示に使用するgridflexboxから始めます。gridは2017年に、flexboxは2013年にブラウザで完全にサポートされるようになりました。この2つの違い、どちらか1つ(または2つとも)を使用する必要があるのかきちんと理解しておく必要があります。誤った同等性を想定している人もいますが、実際にはこの2つは使用例は大きく異なるだけでなく、お互いに補完するために一緒に使用することもできます(そうすべきです)。

参考:

この記事では、メディアクエリを使用せずに、レスポンシブの調整や自然な折り返しを可能にする方法でページ上の要素のレイアウトを処理する方法にフォーカスします。

Grid

grid複数の行と列を持つグリッドを作成し、そこに要素を配置することを主な目的としています。ラッパーとなるグリッドコンテナを作成し、その中に子要素を配置します。グリッドの行、列、セルはさまざまななカスタマイズが可能で、シンプルなグリッドから複雑なグリッドまで作成できます。

参考:

シンプルでレスポンシブなデザインを目指しているわたし達にとって、最も重要な機能を見てみましょう。gridは列や行を自動的に繰り返す機能(repeat())、利用可能なスペースに列のサイズを自動的に調整する機能(auto-fit)があります。例えば、以下のようなコードです。

このCSSではグリッドはコンテンツをスペースに収まるカラムに変換し、各カラムの最小幅を300px以上、最大幅を1fr以下に設定しています。1frは分数を意味するCSSの単位で、スペースを均等に分割し、各カラムにそのスペースの分数を分配するようにブラウザに伝えます。この場合では、3つの均等なカラムを作成し、それぞれが利用可能なスペースの1/3を占めますが、300pxより小さくなることはありません。さらにdivを追加したり削除すると、gridは自動的に計算して表示を調整します。また、スクリーンが小さすぎてカラムを横一列に配置できない場合は、残りのカラムを自動的に次の行に折り返します。

gridを使用してより複雑なレイアウトを作成したい場合は、以下のリソースをご覧ください。

  • A Complete Guide to Gridは、さまざまな幅のカラムの作成、template-areasの定義、グリッドセル間のgapの定義など、gridをカスタマイズするためのあらゆる方法が解説されています。
  • Grid By Exampleは、gridの新しい構造を作成するための出発点を探しているときに、私がよく使う場所です。
  • さらに複雑な実装方法を知りたい場合は、kendo-demoアプリのframe.scssをご覧ください。gridを多用して、すべてのページで使用されるメニューフレームを作成しています。

参考:

Flexbox

flexboxも同様のアプローチ(ただしまったく同じではない)で、ページ上に要素を配置し、必要に応じて自動的に調整することができます。ただし、flexboxは複数の行と列を持つグリッドを作成するのではなく、親要素内での子要素の相対的な位置を調整するものです。

基本的には、一度に2つの方向(行と列)が必要な場合はgridを使用してください。1つの方向(1つの行または列)が必要な場合はflexboxが適しています。

繰り返しになりますが、gridflexboxをそれぞれいつ使用するのか、用途の違いは何なのか、は他の記事に譲ります。この記事ではflexboxがどのようにレスポンシブ対応を処理するかにフォーカスして、不要なメディアクエリを削除できるようにします。

参考:

ここで注目したいのは、flex-wrapプロパティです。
flexは子要素をすべて1つの行または列に収めるようにしますが、それがうまくいかない場合は、flex-wrap: wrap;を定義することで折り返しを許可できます。flex-wrapが定義されていない場合は要素を縮めてすべてを同じ行に収めるか(子要素にmin-widthが指定されていない場合)、または(min-widthが指定されている場合)要素を表示されないようにします。

基本的にはgridflexコンテンツを変形させたいのか、折り返したいのかを決めて、それに合わせてプロパティを定義すればよいのです。どちらも、レスポンシブなUIを作成することに適したツールです。

flexboxを使いこなしたい場合は、以下のリソースをご覧ください。

  • Flexbox Froggyは愛らしいカエルのイラストを使用して、さまざまなプロパティが何をするかをマスターするのに役立つ楽しいゲームです。
  • FLEXは作業中に参照できるシンプルで視覚的なチートシートです。

参考:

活躍するCSSのプロパティ

大局的なレイアウトの次は、要素に特定のプロパティを定義しましょう。
朗報です、ここでもメディアクエリは必要ありません!

aspect-ratio

アスペクト比に特化されたCSSのプロパティがあるのをご存知でしたか?aspect-ratioプロパティは、動画や大きなヒーロー画像を扱う際に正しいアスペクト比を維持させるのに非常に便利です。詳しくはCSS Tricksをご覧いただきたいのですが、実装は非常に簡単です。

aspect-ratioと一緒にwidthを定義するとそれが基準となり、それに合わせてheight値が自動的に生成されます(またはその逆)。ただし、widthheightの両方を定義してしまうと、aspect-ratio値よりもそちらが優先させるのでご注意ください。

参考:

min-height, max-height, min-width, max-width

minmaxheightwidthのプロパティは多くのケースでclamp()関数(次のセクションで説明します)に置き換えることができますが、依然として有益なCSSで、常に念頭においておくとよいでしょう。また、これらのプロパティはその言葉通りの働きをするので、簡単です。

このCSSではまず最初のwidth: 100%;で画像サイズを最大幅までのスペースを確保するように指示し、デフォルトで最大の画像サイズになるようにしています。次にmax-width: 50%;でコンテナ(親要素)の半分以上を占めないようにしつつ、サイズがあまり小さくなりすぎないようにmin-width: 200px;を定義しています。

この場合、絶対値を定義するのは小さい方だけにして、画像が認識できなくなるまでにどれだけ小さくできるかを正確に把握しておきます。これでスクリーンがどんなサイズでも画像は常に可能な限り大きなサイズで表示されます。とてつもなく巨大になったり、何か分からないほど小さくなったりすることはありません。

参考:

完全に機能するCSSの数学関数

数学関数はCSSに新しく追加されたもので、信じられないほど強力です。CSSのデベロッパーが長年にわたって不満を抱いていたもの、つまりスタイルシート内で値を計算したり、プロパティに範囲を定義する機能が使用できます。これらの関数をマスターするのが早ければ早いほど、より多くのメリットが得られます。

clamp()

clamp()プロパティは、3つの値を定義します。基本となる推奨値を設定し、それを調整するための最小値と最大値を設定します。これはブレークポイントを定義しなくてもレスポンシブな限界値を設定できるため、メディアクエリを捨てるための最高のツールのひとつです。仕組みは以下の通りです。

画像の幅の最小値と最大値を定義しました。このCSSではclamp()を使用して1行で定義しています。画像は利用可能なスペースの100%を占めますが、コンテナサイズの幅50%より大きくなったり、200pxより小さくなることはありません。

参考:

calc()

CSSで数学ができたらいいのにと思ったことがある人には、calc()がお勧めです。スタイルシートで、CSSの単位を使って簡単な計算ができます。これは、絶対的ではない単位に基づいて何かを計算する場合に最適です。また、計算にCSS変数を使用することで、さらに柔軟性を高めることができます。たとえば、ブラウザの現在の幅に基づいて均等に分割されたカラムを作成したいとします。

%を使用して幅1/3を設定することは0.333の繰り返しがあるため難しかったのですが、現在では「CSS、お前に任せる!」と言えるようになりました。このCSSでは、ブラウザの全幅(100vw)を3で割り、widthプロパティに設定しています。

参考:

min(), max()

CSSに処理を委ねたい場合には、min()max()がお勧めです。clamp()と似た機能ですが、最小値と最大値を同時に設定するのではなく、1つだけにフォーカスし、計算結果に応じて最小値(または最大値)のみを設定します。繰り返しになりますが、固定されていない値を処理するのに非常に便利なツールで、レスポンシブなものを作成するときには何度もお世話になるプロパティです。

2つの異なる画像の幅を設定しています。
.img1の画像ではmin()を使用し、200pxが親コンテナの30%より大きいか小さいかを評価し、小さい値を採用します。

.img2の画像ではmax()を使用し、800px50vhより大きいか小さいかを評価し、大きい値を採用します。

参考:

小粒だけど重要なCSSの単位

ページ上の要素をレイアウトする際に鳥瞰図のような視点で考えるのは良いことですが、小さな要素、つまりさまざまなプロパティのサイズを指定する単位についても忘れてはいけません。すべてをpxなどのハード単位で定義してしまうと、サイズを変更する必要があるたびに手動で変更しなければなりません。しかし、レスポンシブな単位を使用すれば、仕事はその単位に任せることができます!

vw, vh

CSSのレスポンシブな単位で私が好んでよく使用するのがvwvh、つまりビューポート幅とビューポート高さです。パーセントの記号はありませんが、vwvhはパーセントベースの単位で、1vwはビューポート幅の1%です。

ビューポートのサイズをwindow.innerWidthwindow.innerLengthで取得していた時代は終わりました(これも暗黒時代の話です)。現在では、CSSでそれらの値を取得できます。また、ユーザーがウィンドウのサイズを変更すると自動的に更新されるため、ジャンプする必要もありません。

vhは要素を垂直方向の中央に配置したり、下部に配置するときに特に便利です。たとえば、ユーザーの現在のブラウザの幅と高さに合わせたコンテナ要素を作成するには、下記のように記述するだけです。

参考:

rem, em

もしまだフォントサイズをpxで定義しているのであれば、remとemの素晴らしさを紹介しましょう。emという名は古い活版印刷の測定基準に由来しており、Mの文字の幅に基づいています(これは、em-dashやen-dashという言葉の由来にもなっています(MやNの幅に等しいダッシュです)。
フォントサイズにemを使用するときは、下記のように記述します。

このCSSで.h2の見出しのフォントサイズは、親要素のbodyに定義したフォントサイズの2.5倍になります。

remを使用すると、ページ全体のルートフォントサイズを基準にしてフォントサイズを宣言できます。remという名はルート(root)のemを意味しています。rememはどちらも同じように機能しますが、違いは何をベースサイズにしているかです。そのベースサイズを基にスケーリングをおこないます。

私はemよりremの方が一貫性があるため使いやすいですが、全体のスタイルとは異なる特定のエリアのデザインを作成したい場合はemを使用します。

CSSのテクニックを探しているのであれば、vwremclamp()に組み合わせて、流動的なフォントサイズを定義することができます。

フォントサイズの基準値を2.5vwにし(1vwはビューポート幅の1%です)、最小値と最大値を定義して、文字が読めないほど小さくなったり、大きくなりすぎないようにしています。

参考:

パーセント(%)

最後になりましたが、地味だけど重要な単位%です。gridflexなどのレイアウトツールではなく、何らかの理由で手書きで幅を定義する場合は、絶対的な単位ではなく、%を使用したいと思うでしょう。

ここでは、要素が親の幅の1/4になるように設定しています。つまり、親の幅が変更されると、この要素も自動的に調整されます。シンプルですが、レスポンシブUIの構築には欠かせない要素です。

終わりに

Webサイトやアプリをレスポンシブ化するためにメディアクエリに頼っているのであれば、CSSの機能を見直して、昔ながらのブレークポイントを新しい流動的なアプローチで実装ができないか検討する時期かもしれません。

完全に流動的なスタイルのレイアウトを実装することで、ユーザーが利用する際にスマホとデスクトップでの変更は大幅に少なくなり、デザインに変更があるたびにブレークポイントを見直す必要がなくなるため、メンテナンスの手間も軽減されます。この記事で紹介したアダプティブ(適応性)のアプローチを活用して、流れに乗る準備をしてください!

sponsors

top of page

©2024 coliss