htmlcss Viewport と Media Queries に関するメモ

2013年9月16日

Viewport の指定

スマートフォンの多くは「Viewport」と呼ばれる仮想ウィンドウサイズが設定されていて、設定された Viewport サイズに Web ページを縮小して表示する。

Viewport
ブラウザの表示領域のことで、デバイスごとに異なる。(デバイス幅や解像度とは別)「Viewport」にはブラウザの表示領域をピクセル単位(何px X 何px)での値が設定されている。
デバイスの解像度(device-width や device-height)
デバイスの解像度は、デバイスピクセル比を持つスマートフォンなどではデバイスピクセル比から求められた解像度の値を指す。これは「デバイスの画面解像度 ÷ デバイスピクセル比」で求められる。
画面解像度が 320px X 480px、デバイスピクセル比「1」の iPhone 3GS では 320px X 480px。
画面解像度が 640px X 1136px、デバイスピクセル比「2」の iPhone 5 では 320px X 568px。
メディアクエリやビューポートの指定で device-width や device-height を使う場合の対象はデバイスピクセル比より求められた解像度の方になる。
デバイスピクセル比(device-pixel-ratio)
画像の1ピクセルをデバイスで何ピクセルとして描画するかを表した値。この比率を利用することで、高解像度のディスプレイでも通常の解像度のディスプレイと見た目のサイズが同じように表示される。
iPhone 3GS:CSS ピクセルと物理ピクセルが一致しているので値は「1」
iPhone 4:CSS ピクセルを縦横2倍の物理ピクセルで拡大しているので値は「2」
Android 端末などは「1.5」などが多い
Viewport サイズの例
OS ブラウザ 標準 Viewport サイズ(幅)
iOS(Phone) Safari 980px
Android Android 800px
Windows Phone Mobile Internet Exploler 1024px
Opera Mobile 850px

Viewport は HTML の head 要素内に meta 要素で設定する。

<meta name="viewport" content="プロパティ">

Viewport のプロパティを複数指定する場合はカンマ「,」で区切って指定する。

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

デバイスの横幅に合わせてコンテンツを表示する場合は、viewport の値を「width=device-width」として指定すると、解像度と viewport を一致させることができる。

「device-width」の値は「各デバイスの解像度 ÷ デバイスピクセル比」となっている。iPhone5 では「640px ÷ 2 = 320px」、iPhone3GSなどでは「320px ÷ 1 = 320px」となて、デバイスの解像度が異なっていてもデバイスピクセル比で調整され同じような表示領域で描画させることが可能で、viewport の幅(width)の値は、「device-width」が一般的に使用される。

初期拡大率(initial-scale=1)を指定しても良いが、デバイスを回転させた際にきれいに収まらない端末もあり、それが気になるようであれば、「width=device-width」だけでよい。

<meta name="viewport" content="width=device-width, initial-scale=1">
または
<meta name="viewport" content="width=device-width">
Viewport のプロパティ
プロパティ 意味
width 任意の幅に px で指定 200~10,000px
または device-width(デバイスの幅)
height 任意の高さに px で指定 200~10,000px
または device-height(デバイスの高さ)
initial-scale 最初の縮小率を 0~10.0 の範囲で指定 0~10.0(デフォルト:0.25)
minimum-scale 最小の縮小率を 0~10.0 の範囲で指定 0~10.0(デフォルト:0.25)
maximum-scale 最大の縮小率を 0~10.0 の範囲で指定 0~10.0(デフォルト:1.6)
user-scalable ユーザーによる拡大・縮小の許可を指定 yes (有効)または no (無効)
無効にするとユーザーは拡大・縮小ができなくなる

メディアクエリー(Media Queries)の設定

レスポンシブ Web デザインでは、メディアクエリーを使ってスクリーン幅に応じて CSS を切り替える。

メディアクエリー
デバイスの解像度、ウィンドウの幅、向きなどの指定条件に合わせて別々の CSS を適用できる機能。link 要素中の media 属性や CSS の @media 規則を使ってデバイスやスクリーンサイズで適用範囲を切り替えることができる。
link 要素を利用して複数ファイルを読み込むより、@media の方が HTTP リクエストの回数が少なくページの読み込みが早くなる。

メディアクエリーを使った CSS の切り替えでは、CSS を切り替える条件である「ブレイクポイント(Break Point)」を決め、それぞれの条件に沿ったスタイルシートを記述する。

ブレイクポイント
メディアクエリーによって CSS を切り替える条件となるポイント(レイアウトを切り替える画面サイズの値)のこと。
ブレイクポイントの値
どの画面サイズでは、どのようなレイアウトが良いかを検討し、更にその際にどのようなデバイスがターゲットになるのか等を考慮して決める。

以下のようなブレイクポイントを決めてみる(実際にはコンテンツによりブレイクポイントは変わってくる)。

デバイスとブレイクポイントの例
対象デバイス ブレイクポイント
iPhone のポートレイト(縦向き) 320px
iPhone のランドスケープ(横向き) 480px
iPad のポートレイト(縦向き) 768px
デスクトップ PC 1024px

以下はブレイクポイントの設定例。

  • 幅768pxまでは、デフォルトのレイアウト(1段組)を使用
  • 幅768px~1024pxでは、1段組のまま文字を左寄せにする
  • 幅1024px以上では、レイアウトを2段組にしてコンテンツの位置や画像のサイズを変更する

画面幅768px以上の指定

幅768px以上、1024px未満の場合は以下のように指定する。(以下の指定だけだと「幅768px以上」だが、この後に記述するメディアクエリーが「幅1024px以上」なので「 幅768px以上、1024px未満」)

@media screen and (min-width : 768px){
    /* ここに幅768px~1024pxまでの CSS を記述する */
}

幅320px用(デフォルト)の CSS の後に768px用の CSS を記述すれば、画面幅が768px以上の場合にのみ CSS を上書きできる。

以下の例では文字を左寄せするように記述。

/*768px*/
@media screen and (min-width : 768px){
   #contents { text-align : left}
}

画面幅1024px以上の指定

幅1024px以上の場合にだけ CSS を適用する場合は以下のように指定する。

/*1024px*/
@media screen and (min-width : 1024px) {
  /* ここに幅1024px以上の CSS (グリッドを使ったレイアウトなど)を記述 */
}

メディアクエリの記述例

メディアタイプのみを指定する場合

//デバイスがスクリーンの場合に適用
@media screen {
  * {font-size: 14px; }  
}

メディアクエリに対応していないブラウザには CSS を読み込ませない

//only を付けるとメディアクエリに対応していないブラウザには CSS を読み込ませないようにできる
@media only screen {
  * {font-size: 14px; }  
}

メディアタイプとメディア特性を指定する場合

//デバイスがスクリーンで幅が 960px 以上の場合
@media screen and (min-width:960px){
  * {font-size: 14px; }  
}

2つ以上のメディア特性を指定する場合

//デバイスがスクリーンで幅が 480px 以上で 960px 以下の場合
@media screen and (min-width:480px) and (max-width:960px){
  * {font-size: 14px; }  
}

メディアタイプを問わずメディア特性のみを指定する場合

//デバイスの種類は問わずスクリーンで幅が 480px 以上で 960px 以下の場合
@media (min-width:480px) and (max-width: 960px){
  * {font-size: 14px; }  
}

特定のメディアタイプを除外する場合

//プリント出力でないデバイス全てに適用
@media not print {
  * {font-size: 14px; }  
}

特定のメディアタイプとメディア特性を持つメディアを除外する場合

//「デバイスがスクリーンで幅が 480px 以上で 960px 以下ではない」デバイスに適用
@media not screen and (min-width:480px) and (max-width:960px){
  * {font-size: 14px; }  
}

画面の向きで判定する場合

//向きがポートレイトの場合に適用
@media screen and (orientation:portrait){
  * {font-size: 14px; }  
}
//向きがランドスケープの場合に適用
@media screen and (orientation:landscape){
  * {font-size: 14px; }  
}

デバイスピクセル比を判定する場合

//デバイスピクセル比が2以上の場合に適用
@media screen and (-webkit-min-device-pixel-ratio:2){
  * {font-size: 14px; }  
}

効率の良いメディアクエリーの書き方

メディアクエリーは「モバイルファースト」の考え方に沿って、スマートフォンなどの小さなスクリーン用から記述する。

メディアクエリーを指定していない部分の CSS には、以下のようなデフォルトのスタイルシートを指定する。

  • デスクトップを含めたデバイスで共通で利用する、フォントや背景色などのベースとなるスタイルの指定
  • スマートフォンに最適化したレイアウトの指定

メディアクエリーを使った部分では、メディアクエリーを指定していないデフォルトのスタイルシートとの差分を記述する。

@charset "utf-8";
/* デフォルト(最小幅 0px 以上の指定)
   デバイスで共通で利用するスタイル
   スマートフォンに最適化したレイアウト
  */
@media screen and (min-width : 480px){
  /* 最小幅 480px 以上の指定 */
}
@media screen and (min-width : 768px){
  /* 最小幅 768px 以上の指定 */
}
@media screen and (min-width : 1024px){
  /* 最小幅 1024px 以上の指定 */
}

ブラウザは最初の「@media screen and (min-width:###px)」の部分を読み込み、その後の読み込みを判定する。もし、ウィンドウ幅が480px未満の場合、ブラウザは以下の 2 以降の指定を読み込まない。

  1. 全てのデバイスに共通の指定 + 320px 以上の指定
  2. @media screen and (min-width:480px) { /* 480px 以上の指定 */ }
  3. @media screen and (min-width:768px) { /* 768px 以上の指定 */ }
  4. @media screen and (min-width:1024px) { /* 1024px 以上の指定 */ }

メディアクエリーを効率よく記述することで、無駄なスタイルシートの読み込みをなくすことができる。

Media Queries が動作しない環境への対応

IE6~IE8 では Media Queries は動作しないので、Media Queries を有効にするライブラリを利用する。以下のようなものがある。

css3-mediaqueries-js
CSS 内の @media 規則のみを解析する。
HTML 内の link 要素で指定した場合や CSS 内の @import で読み込ませた場合は無効。
Respond.js
HTML 内の link 要素かつ rel 属性が stylesheet に指定された stylesheet または
CSS 内の @media 規則のみを解析する。
CSS 内の @import 規則は無効

Respond.js の読み込みの例

ダウンロードした JavaScript ファイルを CSS ファイルの後(body の閉じタグの直前など)に読み込む。

<!--&#91;if lt IE 9&#93;>
<script src="js/respond.min.js"></script>
<!&#91;endif&#93;--> 
</body>

HTML5 ベースのマークアップ

IE9 以前のバージョンでは、HTML5 に対応していないので、IE の旧来のバージョンのブラウザでも HTML5 を認識し追加要素がブロックレベル要素として認識されるように「html5shiv (http://code.google.com/p/html5shiv/)」というライブラリを head 要素内で読み込む。

参考:IE対応でよく利用するhtml5shivの使用方法変更について

読み込みの例

</footer>
<!-- //footer -->
<!--&#91;if lt IE 9&#93;>
<script src="assets/js/html5shiv-printshiv.js"></script>
<script src="assets/js/respond.min.js"></script>
<!&#91;endif&#93;-->  
</body>
</html>

WordPress のテーマの例

<?php // Loads HTML5 JavaScript file to add support for HTML5 elements in older IE versions. ?>
<!--&#91;if lt IE 9&#93;>
<script src="<?php echo get_template_directory_uri(); ?>/js/html5.js" type="text/javascript"></script>
<!&#91;endif&#93;-->

またそれに合わせてIE の最新の仕様でレンダリングされるように meta 要素に「http-equiv=”X-UA-Compatible”」を追加する。

<meta http-equiv="X-UA-Compatible" content="IE=edge">
または、
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />

但し、上記の方法だと W3C のチェックでエラーになるので以下のように記述することもできる。

<?php 
if (isset($_SERVER&#91;'HTTP_USER_AGENT'&#93;) && (strpos($_SERVER&#91;'HTTP_USER_AGENT'&#93;, 'MSIE') !== false))
    header('X-UA-Compatible: IE=edge,chrome=1');
?>

IE の過去バージョンに対する CSS ハックをクラス指定で行う方法

<!DOCTYPE html>
<!--&#91;if lt IE 7 &#93;> <html class="ie6" lang="ja"> <!&#91;endif&#93;-->
<!--&#91;if IE 7 &#93;> <html class="ie7" lang="ja"> <!&#91;endif&#93;-->
<!--&#91;if IE 8 &#93;> <html class="ie8" lang="ja"> <!&#91;endif&#93;-->
<!--&#91;if IE 9 &#93;> <html class="ie9" lang="ja"> <!&#91;endif&#93;-->
<!--&#91;if (gt IE 9)|!(IE)&#93;> <!-->
<html class="" lang="ja"> <!--<!&#91;endif&#93;-->

これで「.ie7 div#xxx」と記述すると IE7 のみに適用するスタイルが指定できる。

以下は WordPress の TwentyEleven の例。

<!DOCTYPE html>
<!--&#91;if IE 6&#93;>
<html id="ie6" <?php language_attributes(); ?>>
<!&#91;endif&#93;-->
<!--&#91;if IE 7&#93;>
<html id="ie7" <?php language_attributes(); ?>>
<!&#91;endif&#93;-->
<!--&#91;if IE 8&#93;>
<html id="ie8" <?php language_attributes(); ?>>
<!&#91;endif&#93;-->
<!--&#91;if !(IE 6) | !(IE 7) | !(IE 8)  &#93;><!-->
<html <?php language_attributes(); ?>>
<!--<!&#91;endif&#93;-->
<head>
<meta charset="<?php bloginfo( 'charset' ); ?>" />
<meta name="viewport" content="width=device-width" />