LESSで3倍ラクするスマートフォンコーディング

第8回Media Queriesの弱点をLESSで補う

前回はwhenやwhen notを使い、値によって場合分けをするmixinを作成しました。

今回はさらに上級編として、CSS3のMedia Queriesを利用し、解像度ごとの振り分けや、iPhoneのRetina Displayの対応まで含めたmixinを作成してみましょう。

Media Queriesでさまざまな画像解像度に対応する

スマートフォンのデザインで問題となるのは、画面解像度に対応しなければならないことです。画面解像度によって、指定するCSSを変えたり、高解像度の画像と通常の画像を振り分けるのは、めんどうな作業です。

そんな問題を解決するのに役立つのが、⁠Media Queries」です。

Media Queriesとは、CSS3から採用された新しい書式で、CSS2で採用されていたMedia Type(印刷用CSSを定義するprintなど)を拡張したものになります。

W3C Media Queries
http://www.w3.org/TR/css3-mediaqueries/

このMedia Queriesを利用すると、以下のような指定ができます。

  • 画面解像度(スクリーンサイズ)ごとにCSSを指定
  • iPhoneのRetina Displayをはじめとした高解像度の画面に対応した画像と、通常画像の振り分けを指定

大前提として、スマートフォンの多くは何も指定しないとWebサイトなどを全体表示するために、ドットバイドットではなく、自動的に縮小表示をしてしまいます。

そのため、下記のようなviewport指定をhtmlファイル側で行い、端末側では拡縮が行われないようにしたうえで、Media Queriesを利用してください(本連載では、viewportの細かな説明は割愛します⁠⁠。

<!-- html -->
<meta name="viewport" content="width=device-width, maximum-scale=1.0" />

画面解像度(スクリーンサイズ)ごとにCSSを指定する

まずは、以下のように解像度によってCSSの指定を振り分ける例を見てみましょう。

  • スクリーンの横幅が最大640pxまでの場合 ⇒ 背景が赤
  • スクリーンの横幅が最大320pxまでの場合 ⇒ 背景が青
//CSS
@media screen and (max-width: 640px){
     body {
          background: red;
     }
}
@media screen and (max-width: 320px){
     body {
          background: blue;
     }
}

max-widthの値を変更することにより、さらに細かく指定することもできます。ここでは@mediaでbodyの指定を挟んでいますが、基本的なCSSルールと変わりはありません。

「最大幅が640pxの」と指定してしまうと、⁠最大幅が320pxの場合」という指定が無効になってしまうように思えるかもしれません。しかし

  • 「セレクタの深さが同じであれば、後に書いたものが優先される」

というCSSの基本ルールのもと、⁠最大幅が320pxの場合」で指定したbackground: blue;が、前のbackground: red;を上書きする形になります。

また、max-widthだけでなく、min-widthという指定もできます。

同時に、andで条件をつないでいくこともできます。

そのため、下記のようなコードで「幅が640px以上1000px以下」という指定をすることもできます。

//CSS
@media screen and (min-width: 640px) and (max-width: 1000px){
     body {
          background: green;
     }
}

高解像度画像と通常画像の振り分けを指定する

たとえばiPhoneのRetina Displayでは、画像の幅を320pxと指定すると、画像が幅いっぱいに表示されます(縦持ちの場合⁠⁠。しかし、液晶の解像度は640px分の幅があるため、画像がぼやけて表示されてしまいます。

つまり、液晶のサイズはHTMLやCSS上で指定したpx数の倍あるので、その密度は2倍ということになるのです。

その密度を表すための単位として「device pixel ratio」という単位ができました。Retina Displayの場合、device pixel ratioは2です。

Retina Displayで画像をドットバイドットで表示するためには、幅640pxの画像を用意して、以下のように指定することになります。

  • width: 320px

このように指定することで、Retina Displayを搭載した端末ではよりきれいに、そうでない端末でも縮小されて適度な見栄えで表示されます。

しかし、1つ問題があります。

画像のサイズが大きいと、当然その分容量も大きく、Retina Displayでない端末ではオーバースペックで容量の大きい画像を強制的に読みこまされることになります。

そこで、Media Queriesを利用し、device pixel ratioで画像を指定してみましょう。

以下は、Retina用画像として「bg_x2.png⁠⁠、通常画像として「bg.png」を用意した場合の例です。

//CSS
@media screen and (-webkit-device-pixel-ratio:2){
     body {
          background-image: url('bg_x2.png');//640px × 960pxのRetina用画像
          background-size: 320px 480px;
     }
}
@media screen and (-webkit-device-pixel-ratio:1){
     body {
          background-image: url('bg.png');//320px x 480pxの非Retina用画像
          background-size: 320px 480px;
     }
}

先ほどのmax-widthなどの指定と同様、⁠-webkit-device-pixel-ratio」と指定している点に注目してください。これにより、以下の指定ができています。

  • -webkit-device-pixel-ratioが2の場合 ⇒ 高解像度のbg_x2.pngを読み込む
  • -webkit-device-pixel-ratioが1の場合 ⇒ 低解像度のbg.pngを読み込む

なお、-webkit-device-pixel-ratioは、名前のとおり、webkit(SafariやChrome、Android標準ブラウザ)の独自拡張となります。その他のブラウザでは利用できないので、注意してください。

LESSを利用してMedia Queriesの指定をかんたんに行うには

ここまでの例のように、bodyの背景色や背景画像を差し替えるだけの場合、特にLESSを利用するメリットは見あたりません。しかし、実案件で画像の振り分けなどを行い始めると、大きなメリットが浮かんできます。

まず、Media Queriesは、セレクタの内側では利用できない仕様となっています。

つまり、下記のような記述は文法上まちがっており、無効な記述として無視されてしまうのです。

//CSS
body  #foo {
     background-size: 320px 480px;
     @media screen and (-webkit-device-pixel-ratio:2){
          background-image: url('bg_x2.png');
     }
     @media screen and (-webkit-device-pixel-ratio:1){
          background-image: url('bg.png');
     }
}

正しくは、下記のように、セレクタの外側で@mediaを宣言しなければなりません。

//CSS
body #foo {
     background-size: 320px 480px;
}
@media screen and (-webkit-device-pixel-ratio:2){
     body #foo {
          background-image: url('bg_x2.png');
     }
}
@media screen and (-webkit-device-pixel-ratio:1){
     body #foo {
          background-image: url('bg.png');
     }
}

上記の例では、body #fooが3箇所で宣言されてしまっています。

どんなに階層が深くなってもこのような記述が必要です。

これは、効率良くCSSを記述していくために、致命的な問題と言えるでしょう。

しかし、この点もLESSは非常に都合よく解釈してくれます。

先ほど、CSSでは文法エラーとなってしまった内容を、LESSでコンパイルしてみましょう。

//LESS
body {
     #foo {
          background-size: 320px 480px;
          @media screen and (-webkit-device-pixel-ratio:2){
               background-image: url('bg_x2.png');
          }
          @media screen and (-webkit-device-pixel-ratio:1){
               background-image: url('bg.png');
          }
     }
}



/* Compiled CSS */
body #foo {
     background-size: 320px 480px;
}
@media screen and (-webkit-device-pixel-ratio: 2) {
     body #foo {
          background-image: url('bg_x2.png');
     }
}
@media screen and (-webkit-device-pixel-ratio: 1) {
     body #foo {
          background-image: url('bg.png');
     }
}

このように、ネストの内側で宣言した@mediaも、コンパイルの段階で、記述を一番外側へ移してくれるのです。

ですから、LESSで記述していく限り、手間のかかる記述をする必要はありませんし、管理もぐっと楽になりますね。

以上、Media Queriesの記述上の問題と、それをLESSで少しラクにするための方法をご紹介しました。

とはいえ、まだイマイチ効率的ではありませんね。

次回はさらにこちらをmixinにして、LESSを最大限に利用する記述法を紹介していきます。

おすすめ記事

記事・ニュース一覧