理系ジン

しばらくPythonに力を入れる予定です。

レスポンシブWebデザイン(1)

概要

これから数回レスポンシブWebデザイン関係の記事を書きます。

この記事では、レスポンシブWebデザイン、メディアクエリ、ブレイクポイント、viewport、確認方法について書きます。

レスポンシブWebデザインとは

レスポンシブWebデザインResponsive Web Design)とは、Webサイトにアクセスするデバイス(パソコン、スマートフォンなど)によらず、HTMLソースは一つで、CSS3のメディアクエリMedia Queries)により、画面サイズなどの基準で、読み込まれたり利用されるCSSを切り替えて表示を変える(例:はてなブログのプロフィールの表示場所を右側・下部に切り替え)デザイン方法です。

レスポンシブWebデザインの他に、ユーザーエージェントというデバイスからWebサイトにアクセスした時のHTTPリクエストのUser-Agentヘッダの内容によりWebサーバーでデバイスを判定して種別毎に異なるHTML、CSSを返す方法や、デバイスにより別々のURLにアクセスしてもらう方法もあります。

はてなブログでは、デフォルトではユーザーエージェントで判別しパソコンとスマートフォンで別のHTMLが使われていますが、各ブログの設定で[ダッシュボード]>[デザイン]>[スマートフォン]>[詳細設定][レスポンシブデザイン]にチェックを入れればレスポンシブWebデザインが使われるようになります。はてなブログのテーマはレスポンシブWebデザイン向けではないものが多数派のようです。

GitHub Pagesでは、(多分)HTML、CSSJavaScriptはデバイスによらず同じものが返されるので、レスポンシブWebデザインにするのがいいと思われます。

メディアクエリ

メディアクエリは、メディアタイプMedia Type)と、メディア特性Media Feature)による条件で利用するCSSを選択する方法です。

メディアクエリは次の3通りの指定方法があります。1, 2番目はCSSで、3番目はHTML要素です。これらは並べて複数指定することができます。一つのCSSファイルで済ます場合は1番目の方法を使います(ファイル読み込みの効率からこれが推奨されています)。

@media mediaType and (mediaFeature) {
    /* CSSコード */
}
@import url("my.css") mediaType and (mediaFeature) ;
<link rel="stylesheet" media="mediaType and (mediaFeature)" href="my.css">

メディアクエリ(mediaType and (mediaFeature))の前に次を付けるとそれぞれの作用があります。メディアクエリを満たす場合をtrue、満たさない場合をfalseと表します。

  • only:メディアクエリに対応していない古いブラウザからスタイルシートを隠す(よく分かりません)
  • not:メディアクエリの否定(true, falseをそれぞれfalse, trueにする)

複数のメディアクエリ(mediaType and (mediaFeature))を次で区切るとそれぞれの作用があります。

  • ,:どちらかのメディアクエリがtrueなら全体がtrue、そうでなければfalse
  • and:両方のメディアクエリがtrueなら全体がtrue、そうでなければfalse

メディアタイプ

主なメディアタイプは次のものです。メディアタイプを省略した場合はallと認識されます。

メディア特性

主なメディア特性は次のものです。

  • orientation:デバイスがlandscape(横置き)かportrait(縦置き)かを指示
  • height, width:ブラウザ等の描画域の高さ, 幅を記述
  • -webkit-device-pixel-ratioWebKit系、デバイスのピクセル密度(1ピクセルを何ドットで表すか)を指示
  • resolutionW3Cの仕様(Firefoxなど)、デバイスの解像度(ピクセル密度)を指示、単位はdpi(dot per inch), dpcm(dot per cm), dppx(dot per px)

dppx単位は-webkit-device-pixel-ratioと同じ値になります。また、ピクセル密度は小数値になることもあります。

height, width, -webkit-device-pixel-ratio, resolutionには、前置詞min-, max-付きのものがあり、それぞれ以上, 以下を表します(少々分かり難いですが)。ただし、-webkit-device-pixel-ratioは、-webkit-max-device-pixel-ratio-webkit-min-device-pixel-ratioとなります。

device-heightdevice-widthは利用しないことを推奨されています(参照:CSS メディア クエリを使用してレスポンシブにする - Web Fundamentalsmin-device-widthについての注意)。

また、width, heightは、物理的ドット数をピクセル密度で割った値になります。例えばRetina DisplayであるiPhone 5cの物理的ドット数は640px × 1136pxですが、-webkit-device-pixel-ratioが2なのでwidth=320px, height=568px(ブラウザの枠の分小さい値)になります(iPhone 6 Plusは例外的に1割ほど値がずれます)。

この基準になるwidthなどのメディア特性の値をブレイクポイントと言います。

ピクセル密度のメディア特性は次のように-webkit-device-pixel-ratioresolutionの両方を指定するのが良いようです。

@media (-webkit-min-device-pixel-ratio: 2),
       (min-resolution: 2dppx) {
  /* CSS */
}

次のページでブラウザの画面サイズやピクセル密度を表示できます。

メディアクエリのよくある使い方

メディアクエリの利用方法を見ると、CSSファイルの大部分でパソコン[スマートフォン]用の設定を行い、最後にメディアクエリを指定してスマートフォン[パソコン]用のCSSを指定して上書きするものが多いです。

ブレイクポイント

メディアクエリでCSS切り替えの基準となる値であるブレイクポイントは、レスポンシブデザインのウインドウサイズの切替えについてまとめてみました:アシアルブログによると、縦向きでは768px、横向きでは960pxがスマートフォンタブレットのブレイクポイントに良さそうです(これは2012年の記事ですが以後発達したピクセル密度はwidth, heightに余り影響しないので今でも通用すると考えられます)。

ちなみに、Hatena-Blog-Themes/boilerplate/less/_media-queries.lessは次のようになっています。

/* Media Queries - Retina Display */
@media (-webkit-min-device-pixel-ratio: 2) {
  /* CSS */
}

/* Media Queries - Tablet */
@media (min-width: 768px) and (max-width: 1024px) {
  /* CSS */
}

/* Media Queries - Small Tablet & Smartphone */
@media (max-width: 767px) {
  /* CSS */
}

/* Media Queries - Smartphone */
@media (max-width: 480px) {
  /* CSS */
}

はてなブログについてはいずれ詳しく調べる予定です。

viewport

スマートフォンタブレットはデフォルトでは幅が980pxとして描画されるそうです(メディアクエリのwidthは確かにそのように動作しているようです。JavaScriptのscreen.widthの値は物理的ドット数をピクセル密度で割った値になっているようです)。

レスポンシブWebデザインを行う場合はこれはまずいので、次のように、HTMLのmeta要素name属性viewportを指定し、content属性に設定値を記述します。,区切りで複数の値を指定できます。

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

content属性の設定値には、表示領域の幅・高さ初期のズーム倍率ズーム倍率の最大・最小ズーム操作の可否の項目があります。次のページを見てください。

はてなブログでは、テーマのCSSの先頭に、Responsive: yesという行を含んだコメントがあればHTMLのヘッダーに次の要素が出力されます(参照:はてなブログテーマ制作の手引き - はてなブログ ヘルプレスポンシブデザインのテーマを作成するには)。

<meta name="viewport" content="width=device-width">

これは、表示領域の幅をデバイスの幅に合わせる設定です。

Jekyllのサイトは次のようになっています。

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

これは、表示領域の幅をデバイスの幅に合わせ初期のズーム倍率を1にする設定です。

ゲームは大抵次のようにズーム操作ができないようにされています。widthが固定値のこともあります。

<meta name="viewport" content="width=device-width, user-scalable=no">

ChromeブラウザのデベロッパツールのDevice Modeによる確認

Chromeブラウザのデベロッパツールを起動([option]+[command]+[i]キーやメニューから)して、虫眼鏡と[Elements]の間にあるスマートフォンのアイコンをクリックするとDevice ModeになりiPhoneAndroidのブラウザをエミュレートできます(再クリックで元に戻ります)。

Device pixel density tests - Bjangoにアクセスした表示例です。

f:id:rikeizine:20150104222015p:plain

理系ジンが確認したところ実際のデバイスとは少々動作が違うようです(特に、<meta name="viewport" content="width=device-width">が設定されてなくても設定されているような動作をします)。

参考資料

メディアクエリ

ブレイクポイント

viewport

ChromeブラウザのデベロッパツールのDevice Mode

予定

今後しばらくの記事の予定は次のようになっています。

  • レスポンシブWebデザイン(2):レイアウト
  • レスポンシブWebデザイン(3):画像、Webフォント、CSS Sprite、SVGCanvasの扱い方
  • less
  • Webページ情報取得
  • はてなブログ分析
  • はてなブログテーマ作成
  • Metalsmithの調査

これ以降は状況により変わります。