レスポンシブWebデザインで、スクリーンサイズが中途半端なときにデザインが崩れないようにするための実装方法
Post on:2020年6月4日
Webページを実装する際、注意すべき点の一つは表示されるスクリーンサイズです。スマホとタブレット、そしてデスクトップの3種類を想定している人も多いと思いますが、現在ではさまざまなサイズのスクリーンが存在しています。
スクリーンサイズが中途半端な「中間のデザイン」で、デザインの見栄えが悪くなったり、崩れたりしないようにするための実装方法を紹介します。横一行配置のアイコンが改行してしまう、画像が横長になってしまう、フォームの入力欄がやたら広くなる、など一般的なデザインで見かけると思います。

Thinking About The In-between Design Cases
by Ahmad Shadeed
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- レスポンシブにおける中間のデザイン
- 中間のデザインとは
- 中間のデザインに備えておく理由
- 一般的なデザインで見かける中間の問題点
- 中間のデザインに対応する方法
- 中間の問題点をより適切に見つける方法
- おわりに
レスポンシブにおける中間のデザイン
レスポンシブWebデザインでは、ページの異なるバリエーションで作業するのが一般的です。典型的なWebページには少なくとも2つのバリエーションがあり、1つは小さなスクリーンサイズ(例: スマホ)、もう1つは大きなスクリーンサイズ(例: デスクトップ)です。多くの場合、その中間のデザインバリエーションを忘れてしまい、コンポーネントやセクションの幅が広すぎたり狭すぎたりすることがあります。
私はいつも、このような中間のケースを考慮に入れられないだろうか、もし可能ならどのようにすればよいのだろうか、と考えています。デザイナーであり、デベロッパーでもある私は、このことを深く考えるようになり、in-between中間のデザインケースと呼ぶことにしました。中間とは、わたし達があまり気にせず、無視しているスクリーンサイズのことです。
この記事では、この問題とその解決方法を明確に浮き彫りにするための試みです。少しでもあなたのお役に立てたなら幸いです。
では、in-between中間に飛び込んでみましょう!
中間のデザインとは
in-between中間とは何を意味するか、簡単に説明します。
下記のモックアップには、3つのバリエーション(スマホ・タブレット・ラップトップ)のデザインがあります。

典型的なWebページのバリエーション
一見すると、何の問題もありません。しかし、中途半端なスクリーンサイズでは少し違った感じになります。その理由を視覚的に説明します。

in-between中間のデザイン
カードはスマホで表示すると期待通りに見えますが、スクリーンの幅が広いと、タブレット用のメディアクエリが始まるまでカードが広がりすぎてしまいます。このカードが幅広になっている時が、in-between中間です。
私ははっきりしているのが好きなので、明確にするためにさらに例を挙げて説明します。
下記は、ロゴ・ナビゲーション・ソーシャルリンクを含むシンプルなフッタです。デスクトップでもスマホでも問題なく表示されています。しかし、タブレットや中間の状態では、奇妙に見えます。アイコンのスペースが限られているため、ソーシャルリンクのアイコンが改行されてしまいました。

中間だと、左のアイコンの配置が変
次の行に押しやられた小さなアイコンは、誰も気にしてくれない子供のように寂しがっているのではないかと思ってしまいます。
最後に、もう1つ例を見てましょう。
3つの列を持つセクションで、それぞれのカラムにはテキストコンテンツとアイコンがあります。中間のデザインが非常に悪いように見えます。これは水平方向のスペースを取り過ぎていますね。

中間だと、水平に広がりすぎ
中間のデザインに備えておく理由
Webサイトのコンテンツタイプを考慮せずにメディアクエリを使用していることが、その主な理由だと思います。CSSフレームワークで最も人気が高いBootstrapには、Webでよく使用されるブレイクポイントが用意されています。
.container要素のCSSを見てましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
.container { width: 100%; } @media (min-width: 576px) { .container { max-width: 540px; } } @media (min-width: 768px) { .container { max-width: 720px; } } @media (min-width: 992px) { .container { max-width: 960px; } } @media (min-width: 1200px) { .container { max-width: 1140px; } } |
コンテナの幅を固定してしまうと、一部の要素の幅が広すぎたり狭すぎたりすることがあります。上記のCSSを視覚的に確認してみましょう。

ビューポートに応じて変化するコンテナの幅
ビューポートのサイズに応じて、コンテナの幅は固定値で変化し、ビューポートが小さすぎると100%に変化することに注目してください。
より良いメディクエリを作成するためには、Webサイトの性質やコンテンツに基づいたクエリを作成する必要があります。上記のメディアクエリがすべてのWebサイトに適しているとは限りません。すべてのWebサイトはユニークで、わたし達はそのことに注意を払う必要があります。
一般的なデザインで見かける中間の問題点
上記で説明したin-between中間の問題で一般的なデザインの例を取り上げます。
ヘッダ
ほぼすべてのWebサイトに、ロゴやナビゲーションを含むヘッダがあります。私が見つけたのは、多くの実装が必ずしも完璧ではないということです。一般的にヘッダには、ロゴとメニューの切り替えボタン、あるいはハンバーガーメニューを備えたスマホ用のデザインがあります。もう1つは、タブレットやラップトップ、デスクトップなどの大きなスクリーンでナビゲーションが表示されるデザインです。
下記のモックアップをご覧ください。

スクリーンサイズごとのヘッダの表示
in-between中間の状態では、水平方向のスペースが少なくなるため、ナビゲーションのアイテムが改行しています。ヘッダをFlexコンテナで実装している場合は、下記のように表示されるかもしれません。

Flexboxを使用した場合
ナビゲーションのアイテムが同じ行にあることに注目してください。「How it works」のアイテムが行に折り返されています。これは、別のCSSのテクニックでも異なる場合があります。ここでのポイントは、中間の状態が意図しない見え方になることを示すものです。
ヘッダの場合、ナビゲーションのアイテム数をコントロールするのが複雑になることがあります。デベロッパーは注意して実装したかもしれませんが、コンテンツ管理者が新しいアイテムを追加して、レイアウトが崩れてしまったのかもしれません。私が見る限り、これを完成形と言うことはできません。しかし、この問題を防ぐ、もしくは減らすことができます。
flex-wrap: wrap;を使用する
Flexコンテナがflex-wrap: wrap;に設定されている場合、その子アイテムは互いに触れあう時に新しい行になります。
コードとどのように表示されるかご覧ください。
1 2 3 4 |
.header { display: flex; flex-wrap: wrap; } |

上: flex-wrap: wrap;なし、下: flex-wrap: wrap;あり
これが唯一の解決方法というわけではありません。他にも「More」ボタンを用意し、水平方向のスペースがない場合にそのボタンを表示する方法もあります。
参考: The Priority+ Navigation Pattern

「More」ボタンで対応
解決方法は他にもあると思いますが、私が言いたいのは、それぞれの問題はより多くの時間と労力を費やすことで解決できる、ということです。
スマホ用のメニュー
ヘッダのデザインを紹介したので、それに関係したスマホ用のメニューのデザインを見てましょう。通常、スマホ用のメニューはユーザーがボタンをタップしてアクティブにするまで非表示になります。トグルボタンの下にメニューが非表示になる瞬間が重要となります。
下記のモックアップをご覧ください。

スマホ用のメニュー
一般的なスマホのスクリーン(幅375px)では、メニューの見栄えは非常によいです。しかし、タブレットのスクリーンでは、スペースが多く、レイアウトがおかしく見えます。デスクトップの場合は、メニューは非表示になりません。in-between中間の状態をもっとよく見せることはできないでしょうか?
このビューポートサイズでナビゲーションを非表示にする必要があるのでしょうか? もしそうだとしたら、その理由は何ですか?
- 同じ行にすべてのアイテムを収めるのにスペースが十分ですか?
- あるいは、アイテムが追加される可能性があることを考慮して、デベロッパーが意図的にそうしたかもしれませんか?
- もしかして、デベロッパーが怠け者で、トラブルやデザイン面での課題を抱えたくないだけなのでは?
理由はいろいろ考えられますが、確実なのは、これは解決できる問題であることです。いくつかの解決方法を見てましょう。
解決方法を掘り下げる前に、私は自分自身に次の質問をします。
- ナビゲーションは変更される可能性があるか? 例えば、優先順位に基づいてナビゲーションリンクを時間で変更するニュースみたいなサイト。
- アイテムの最大数は? アイテムが増えるほど、実装はより複雑になる。例えば、アイテムをメニューの下にグループ化する必要があるかもしれない。
ここではアイテム数は変わらないと仮定して、in-between中間の状態をよりよいデザインにしてみようと思います。

中間の状態のデザインを改善
スカスカに見えないデザインで、スペースを効果的に使用しました。このデザインでビューポートが小さい場合は、どのようになるでしょうか? CSS Gridのminmax()関数を使用して、使用可能なスペースに応じてサイズを変更できます。
1 2 3 4 |
.nav { display: grid; grid-template-coluumns: repeat(auto-fit, minmax(150px, 1fr)); } |

ビューポートが小さい場合
カード
カードは通常、サムネイル画像とタイトルや説明文などのテキストを含むコンポーネントです。このコンポーネントをレスポンシブ対応で実装した時に、in-between中間の状態でデザインの問題がいくつか発生することに気がつきました。

カード
in-between中間の状態だと広がりすぎです。
- 行が長いためテキストが読みにくくなります。
- サムネイル画像の幅が広すぎるため、画像の重要な部分がトリミングされる可能性があります。特に、Eコマースなどで商品画像を表示する場合は、UXに大きな影響を与えてしまいます。
デスクトップでは4カラム、タブレットでは2カラム、スマホでは1カラムにサイズを変更するグリッドを使用することは、レスポンシブデザインではありません。私は無責任なデザインと呼んでいます。デベロッパーが既製のグリッドを使用したり、ビューポートに合わせてサイズを変更するだけのグリッドを使用しただけです。ちなみに、私は何が正しい動作なのかを学ぶまで、何度もこのミスをしてきたので、誰かを批判するためではないことをご理解ください。
- カード内のコンテンツはどうすればよいか? 読みやすく見栄えもよくすることに価値があるのではないだろうか?
- 各要素のサイズを変更すればいい? ビヘイビアも考慮し、カードを使用するユーザーの立場になって考えるべき?
下記のモックアップでは、カードのサムネイル画像とテキストを隣り合わせにする(画像とテキストを積み重ねない)解決方法です。

中間の状態のデザインを改善
この解決方法は、サムネイル画像を広げて表示するよりもはるかに優れています。テクニック的にはFlexboxを使用するだけで、簡単に実装できます。複雑な作業はありません。
font-sizeの単位にremを使用する
Web上のフォントサイズは、Webページを読みやすくするために最も重要な要素の1つです。font-sizeの単位にremを使用するテクニックがあり、スマホとデスクトップでルートのフォントサイズを変更することで、ビューポートの幅に応じて要素のフォントサイズを増減させることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
html { font-size: 13px; } @media (min-width: 700px) { html { font-size: 16px; } } h1 { font-size: 2rem; /* 1rem on mobile = 13px, 1rem on desktop = 16px */ /* 26px on mobile, 32px on desktop. } |
いい感じですね、レスポンシブ用のタイポグラフィにぴったりなテクニックです。しかし、このままではin-between中間の状態に欠点があります。

中間の状態のデザインに対応していない
前述のCSSでうまくいくかもしれませんが、完璧ではありません。px単位とビューポート単位を組み合わせてより動的にする方法をお勧めします。
1 2 3 |
.element { font-size: clamp(16px, (1rem + 5vw), 50px); } |
CSSのclamp()関数を使用すると、最小フォントサイズを16px、推奨サイズを1rem + 5vw、最大フォントサイズを50pxのように定義できます。こうすることで、中間の状態を考慮した動的なフォントサイズを実現できます。
clamp()関数など、CSSの比較関数について詳しく知りたい場合は、それらについて詳細な記事を書きました。
フォーム要素
これはよく見かけるパターンです。入力項目やボタンの幅が変に広がる場合、目障りになるかもしれません。下記のモックアップをご覧ください。

中間の状態だと、幅は変に広い
2つのフォーム要素があり、1つは名前用、もう1つはメールアドレス用です。この2つの要素は親要素の全幅を占めるように実装されているため、中間の状態では幅が広すぎるように見えることを除いて、見栄えは良いです。ちなみに、デスクトップではラッパーのmax-widthが効いているので、幅が狭くなっています。
これに対応するには、ビューポートの幅に関係なくmax-widthを設定して幅を制限した方がよいでしょう。そうすることで、フォーム要素の幅が広くなりすぎることはなくなります。
アイコン付きのリスト
もう1つよく見かけるパターンは、機能リストです。通常は左にアイコン、右にテキスト(見出しと説明文)があります。このリストはスマホでもデスクトップでも見栄えがよいです。スマホではアイコンのサイズが小さくなり、デスクトップでは大きくなります。ただし、中間の状態は考慮されていません。

中間の状態が考慮されていない
中間の状態のアイコンのサイズは、ビューポートの幅に対して小さすぎます。アイコンのサイズには、スマホ用・中間用・デスクトップ用の3つのサイズが必要です。
CSSの比較関数を使用すると、メディアクエリを使用せずに対応できます。しかし、より多くのブラウザをサポートするためには、メディアクエリでフォールバックが必要になります。
中間のデザインに対応する方法
一般的な事例が分かったところで、中間のデザインを処理する方法について少し話してみましょう。私にとっては、直接的なアプローチはありませんが、むしろその点で役立つステップやテクニックについて紹介したいと思います。
スクリーンサイズだけで考えるな
デザインのin-between中間の状態を無視してしまう原因の1つは、既製のグリッドシステムに頼るか、いわゆる「標準のメディアクエリのブレイクポイント」を使用することにあります。デザインにおける効果的なブレイクポイントは、スクリーンサイズではなく、コンテンツに基づく必要があります。そうすることで、中間の状態にもフォーカスを当てたより良いレイアウトを作成できます。
デザイナーとコミュニケーションを取る
デザイナーからデザインソースを入手したら、そこにあるすべてのセクションとコンポーネントを理解するようにしてください。そして、それらのコンポーネントがすべてのビューポートサイズでどのように表示されるか・動作するかについてたくさんの議論を重ねてください。
CSSの新しいテクニックを使用する
CSS Flexbox, Grid、そして比較関数を使用して、中間の状態を含むすべてのスクリーンサイズで見栄えのよいデザインを構築できます。それらの実際の使用方法をいくつか見てましょう。
CSS Flexbox
まず頭に浮かんだのは「整列シフトラッピング」というテクニックです。スマホで積み重ねる要素が2つあり、デスクトップでは水平に配置されます。その中間はどうなるでしょうか?

上: スペースがある、下: スペースが足りない
前述したヘッダを例に見てましょう。
スマホではロゴとナビゲーションが積み重なり、それらが触れあうときに動的に表示されるようにするにはどうすればよいでしょうか?
Flexboxのおかけで、簡単に実装できます。
1 2 3 4 |
.header { display: flex; flex-wrap: wrap; /* Important to make it work */ } |
CSS Grid
CSS Gridにはminmax()関数があり、最小値と最大値に基づいてグリッドのアイテムのサイズを変更することができます。デスクトップでは4、タブレットでは2、スマホでは1になる静的グリッドの代わりに、より動的なアプローチをとることができます。
Flexible layouts without media queriesで使用されているテクニックがぴったりです。CSS Gridと比較関数を組み合わせて、カードの最大サイズを設定します。
1 2 3 4 |
.wrapper { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr)); } |
minmax()関数はグリッドアイテムの最小値と最大値を設定します。最小値はビューポートの幅よりも大きくしてはいけません。そのため、minmax()関数の最初の値にはmin()関数を使用します。
CSSの比較関数
さきほども紹介しましたが、CSSの比較関数は非常に便利です。実際の使用例をあげて記事を書いたので、参考にしてください。
中間の問題点をより適切に見つける方法
デザインのin-between中間の状態をテストし、見極めるために必要なスキルを持つことが重要です。私はデザインに取り組む際に、シンプルなアプローチをとっています。
- デベロッパーツールを開き、
- テストする要素を除いて、他をすべてを削除します。
- ビューポートのサイズを変更します。
テストする要素以外を削除する理由は、テストする要素に戻るために上下にスクロールしてしまうページジャンプを避けるためです。そのため、他をすべて削除し、テストしたい要素だけを残しておくことをお勧めします。そうすれば、中間の問題点を見逃すことはありません。
この挙動はFirefoxとSafariでのみ見られます。Chromeでは、スクリーンサイズを変更すると、ブラウザがスクロールします。その違いを示すために、テストをしてみました。
下記はフッタのデザインで、ページの一番下までスクロールした状態です。

ページの一番下までスクロールした状態
次に、ビューポートをスマホのサイズに変更します。Chromeがスクロールの位置を保持していることに注目してください。

FirefoxとSafariは、ページジャンプしてしまう
このような些細なことが原因で、テストを漏らしてしまう可能性があるので、テスト中は問題点に集中できるようにすることが重要です。
おわりに
この記事のアイデアが浮かんだ時のことをよく覚えています。ノートアプリにタイトルを入力し、アウトラインの計画を立てました。私の目的は、この無視されがちなデザインの状態に光を当てることです。この記事で、あなたのワークフローに役立つ何かを得られることを願っています。
コメントや提案があれば、@shadeed9までお願いします。
sponsors