CSS

レスポンシブ Web デザインのサイトを作成する時に、知っておきたいこと

最近、レスポンシブ Web デザインのサイトを仕事で作成しています。レスポンシブは、PC・タブレット・スマートフォンなどのあらゆるデバイスに適したサイトを単一 HTML で表現する手法です。このブログもレスポンシブを採用していて、左右の横幅を狭めていくとページのレイアウトが変わります。

この記事では、レスポンシブサイトを作成する時に、知っておきたいコトをまとめてみました。今までレスポンシブサイトを作ったことがないけれど、ある程度 HTML/CSS を学んだ人向けに書いています。

目次

  • そもそもレスポンシブを採用するかどうか
  • スマートフォンにおける表示の最適化
  • PC では幅一定で画面中央に、スマートフォンでは画面いっぱいに表示
  • Responsive Grid System
  • CSS 記述量が減るメディアクエリの書き方
  • 画像を画面いっぱいに引き伸ばすクラスを用意しておくと便利
  • 伸縮する画像を背景にする
  • 画面幅に応じて画像を出し分ける方法
  • リンクを押せる領域を意識する

そもそもレスポンシブを採用するかどうか

レスポンシブを採用するかどうかは、一考する必要があります。万能ではありません。レスポンシブは、モバイル向けのデザインを PC 向けに組み直すという流れで実装していきます。そのためどうしても PC で見た時の情報量やデザインに影響してきます。

下記が、僕が考えているレスポンシブサイトを作る上のメリットです。また、加えて仕事で扱うサイトのユーザー分布が、スマートフォンに極端に寄っているから採用している面もあります。

  • PC/スマートフォン向けサイトを別々に作るのに比べて、開発スピードが見込める
  • テンプレートエンジンを使って HTML ファイルを出力する場合、テンプレートをひとつ用意するだけで良い

実際に、レスポンシブを採用することになった場合、デザイナさんとの入念なコミュニケーションが必要となります。デザイナさんが本格的に作業に入る前に、実際にモックサイトを作ると、デザイナさんと実装する人の認識の差を埋めるのに役立ちます。

スマートフォンにおける表示の最適化

Viewport は、スマートフォンのブラウザが採用している仮想ウィンドウです。例えば、iPhone の横幅は 320px ですが、Viewport は横幅 980px が適用されています。サイトを見ている時に、よく文字が小さく見えることがあるのですが、それはこの Viewport が影響しています。

スマートフォンの Viewport が、その端末の横幅となるように、以下のタグを head タグの中に記述します。これで iPhone で見えるサイトの横幅が 320px になります。レスポンシブサイト・スマートフォン向けサイトを作る時の一種のおまじないみたいなものです。

<meta name="viewport" content="width=device-width, initial-scale=1">

PC では幅一定で画面中央に、スマートフォンでは画面いっぱいに表示

PC では幅 728px で画面中央に、スマートフォンでは画面いっぱいに表示する実際のコードが下記になります。レスポンシブサイトを作る時の大枠として使います。

.container {
  max-width: 728px; /* 最大横幅 */
  width: 100%;
  margin: 0 auto;
}

Responsive Grid System

「PC は2カラム、スマートフォンは1カラム」といったレイアウトをレスポンシブサイトではよく使用します。グリッドシステムは、ざっくり言えば、そのようなレイアウトがあらかじめ用意された CSS ファイルです。

グリッドシステムを実現するライブラリはたくさんあるのですが、僕は Responsive Grid System を使用しています。例えば、「PC は2カラム、スマートフォンは1カラム」を作るには、次のように記述します。

<div class="container">
  <div class="row">
    <div class="col span_8">
      <!-- 左カラム -->
    </div>
    <div class="col span_4">
      <!-- 右カラム -->
    </div>
  </div><!-- div.row -->
</div><!-- div.container -->

Responsive Grid System では、全セレクタに box-sizing: border-box; を指定しています。全セレクタに指定するので端末負荷は上がってしまいますが、paddingborder の変化に強くて記述が楽になります。

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

CSS 記述量が減るメディアクエリの書き方

メディアクエリ(Media Queries)は、デバイスの横幅に応じて読み込む CSS を変えるための機能です。

メディアクエリを使用する場合、画面幅に応じて表示を変えたい場合には、小さい画面幅から大きい画面幅へと記述するのが良いです。メディアクエリ内では、小さい画面幅との差分を書き足していきます。差分を意識して書くことにより、意味が把握しやすく記述量の減る CSS になります。

/* 568px より小さい場合に適用される。スマートフォンでよく使われていてその中で小さい画面幅を持つのは、iPhone の 320px なので実質 320px ~ 567px の範囲 */
.column {
  width: 100%;
  max-width: 1024px;
  display: block;
  /* 全画面サイズで共通の指定をここで行う */
}

/* 568px ~ */
@media (min-width: 568px) {
  .column {
    width: 50%;
    float: left;
  }
}

/* 728px ~ */
@media (min-width: 728px) {
  .column {
    width: 25%;
  }
}

また、このような書き方をすることでスマートフォンにおける CSS 読み込みの効率が良くなります。基本的な考え方として、PC に比べて端末スペックが低いスマートフォンでは、多くのスタイルを読み込ませたくありません。

例えば、この場合、端末画面幅が 320px の iPhone は、最初のメディアクエリを指定しない CSS だけを読みます。もしこれが、大 → 小さい画面幅のようにメディアクエリが書かれている場合、上から順に三回もスタイルを読み込む必要があり、スマートフォンにとって相性の悪い CSS になります。

画像を画面いっぱいに引き伸ばすクラスを用意しておくと便利

画像を画面いっぱいに表示するのに使用するクラスを用意しておくと便利です。Twitter Bootstrap では、そのために .img-responsive クラスが用意されています。これに倣って、最近作成するレスポンシブサイトの CSS では、以下のクラスを宣言しています。

/* css */
.img-responsive {
  display: block;
  width: 100%;
  height: auto;
}

/* html */
<img src="photo.jpg" class="img-responsive" />

逆に、画面幅を縮めた時に、画像が幅からはみ出ないようにするために、以下のように img タグそもそもの max-width の限界値を 100% にしておきます。

img {
  max-width: 100%;
  height: auto;
  border: 0;
}

基本的に、比率を維持したまま拡大・縮小出来るのは、img タグだけなのですが、padding の仕様を利用すれば、例えば YouTube を埋め込んだ iframe をレスポンシブ対応することが出来ます。以下のサイトが詳しいです。

伸縮する画像を背景にする

基本的に、画像の伸縮を利用できるのは、img タグで画像を直接置いた場合なのですが、background-size: cover; を利用すれば、擬似的に伸縮する画像を背景にすることができます。「擬似的に」というのは、縦幅を固定する必要があるからです。

以下のように実装すれば、伸縮する画像を背景にできます。AppBankアプリサポートページのように、ブラウザの横幅を移動すると画像が伸縮するように見えます。

/* css */
#hero {
  width: 100%;
  height: 200px;
  background: url(images/hero.jpg) no-repeat center;
  background-size: cover;
}

/* html */
<div id="hero"></div>

よくあるレスポンシブのサイトでは、画面幅いっぱいに表示することが多いのですが、その場合、ある程度大きな画像を用意する必要があります。

大きい画像は読み込むスピードが遅いので以下のような対応で画像サイズを落とします。経験的に、100kb 以下がボーダーラインと思っています。

画面幅に応じて画像を出し分ける方法

画面幅に応じて画像を出し分けるには、2つの実装方法があります。

  • JavaScript による画面幅の監視
  • メディアクエリと background を使用する

以下のコードは、JavaScript で画面のリサイズを監視し、画面幅 768px を境界に img タグの画像ファイルを変えています。

function changeImgSrc(width) {
  if (width > 768) {
    document.getElementById('img-hero').src = "images/hero.jpg";
  } else {
    document.getElementById('img-hero').src = "images/hero_sp.jpg";
  }
}

var width = window.innerWidth;
changeImgSrc(width); // 初回

window.onresize = function resize() {
  var currentWidth = window.innerWidth;
  if ( (width < 768 && 768 <= currentWidth) || ( width > 768 && 768 >= currentWidth) ) {
    // 画面幅が 768px を堺に変わった時だけ呼ばれる
    changeImgSrc(currentWidth);
  }
  width = currentWidth;
};

また、メディアクエリと background に画像を指定することで似たようなことを実現できます。実装と運用はこちらのほうが楽ですが、background に指定した画像は、伸縮ができない点に注意です。

.change-img {
  display: block;
  width: 150px;
  height: 150px;
  background: url(images/photo.png) no-repeat;
  background-size: 150px 150px;
}

@media (min-width: 480px) {
  .change-img {
    width: 300px;
    height: 300px;
    background: url(images/photo@2x.png) no-repeat;
    background-size: 300px 300px;
  }
}

リンクを押せる領域を意識する

これは、レスポンシブサイトに限らず、スマートフォンサイトでも大事な考え方です。

例として、リストを使用して、その中にリンクテキストを書く場合を想定します。次のようなコードになるかと思います。ちなみに、タップしやすいと言われる縦幅 44px を意識しています。

/* css */
ul.vertical-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

ul.vertical-list li {
  width: 100%;
  height: 43px;
  line-height: 43px;
  border-bottom: 1px solid #ddd;
}

/* html */
<ul class="vertical-list">
  <li>
    <a href="">尋常ではないもふもふ</a>
  </li>
</ul>

これを iPhone からタップしてみます。灰色の領域が押せる領域を示しています。左側の画像が押せる領域です。

幅を 44px 用意したのですが、テキストの縦幅分しか存在していません。これは、a タグが display: inline 要素(テキスト幅に追従する)であることに因ります。右側の画像のように 44px を押せる範囲にするには、以下のように block を指定してあげます。

/* css */
ul.vertical-list li a {
  display: block;
  width: 100%;
}

参考

レスポンシブWebデザイン マルチデバイス時代のコンセプトとテクニック (WEB PROFESSIONAL)