ピクセル パーフェクトの WebView

公開日: 2014 年 2 月 28 日

WebView に最適なインターフェースを作成するには、いくつかの方法があります。

ビューポート メタタグを設定する

ビューポート メタタグは、ウェブアプリに追加する最も重要なタグです。このタグがないと、WebView はサイトがパソコンのブラウザ用に設計されているように動作する可能性があります。これにより、ウェブページの幅が広くなり(通常は 980 ピクセル)、WebView の幅に合わせて拡大縮小されます。ほとんどの場合、ページの概要版が小さくなり、ユーザーがパンやズームしてコンテンツを実際に読む必要があります。

サイトの幅を WebView の幅の 100% にするには、ビューポート メタタグを設定します。

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

ページ レイアウトをより細かく制御するには、width を特別な値 device-width に設定します。

デフォルトでは、WebView はデスクトップ ビューポートではなく、ビューポートをデバイスの幅に設定します。ただし、信頼性が高く制御された動作を実現するには、ビューポート メタタグを追加することをおすすめします。

PC 版サイトを表示する

モバイル デバイス向けに設計されていないコンテンツを表示する必要がある場合もあります。たとえば、管理していないコンテンツを表示する場合があります。この場合は、WebView にデスクトップサイズのビューポートを使用するように強制できます。

これらのメソッドが設定されておらず、ビューポートが指定されていない場合、WebView はコンテンツのサイズに基づいてビューポートの幅を設定しようとします。

また、レイアウト アルゴリズム TEXT_AUTOSIZING を使用すると、フォントサイズを大きくしてモバイル デバイスで読みやすくすることができます。setLayoutAlgorithm をご覧ください。

レスポンシブ デザインを使用する

レスポンシブ デザインは、画面サイズに応じて変化するインターフェースを設計するアプローチです。

レスポンシブ デザインを実装する方法はいくつかあります。最も一般的なクエリの 1 つは @media クエリです。これは、デバイスの特性に基づいて要素に CSS を適用します。

たとえば、画面の向きに基づいて縦型レイアウトから横型レイアウトに変更する場合を考えてみましょう。CSS プロパティをデフォルトで縦向きに設定します。

.page-container {
    display: -webkit-box;
    display: flex;

    -webkit-box-orient: vertical;
    flex-direction: column;

    padding: 20px;
    box-sizing: border-box;
}

横向きのレイアウトに切り替えるには、向きに基づいて flex-direction プロパティを切り替えます。

@media screen and (orientation: landscape) {
  .page-container.notification-opened {
    -webkit-box-orient: horizontal;
    flex-direction: row;
  }

  .page-container.notification-opened > .notification-arrow {
    margin-right: 20px;
  }
}

画面の幅に基づいてレイアウトを変更することもできます。

たとえば、物理画面サイズが大きくなるにつれて、ボタンの幅のサイズを 100% から小さく調整します。

button {
  display: block;
  width: 100%;
  ...
}

@media screen and (min-width: 500px) {
  button {
    width: 60%;
  }
}

@media screen and (min-width: 750px) {
  button {
    width: 40%;
    max-width: 400px;
  }
}

これらは小さな変更ですが、UI によっては、メディアクエリを使用して、HTML を変更せずにアプリケーションの外観を大幅に変更できます。

鮮明な画像

画面サイズと画面密度の多様性も、画像の課題となります。サイズが小さい画像はメモリ使用量が少なく、読み込みも速くなりますが、スケールアップするとぼやけます。

どの画面でも画像を鮮明に表示するためのヒントをいくつかご紹介します。

  • スケーラブルなエフェクトには CSS を使用します。
  • ベクター グラフィックを使用する。
  • 高解像度の写真を提供してください。

スケーラブルなエフェクトに CSS を使用する

可能な限り、画像ではなく CSS を使用してください。CSS プロパティの組み合わせによっては、レンダリングに時間がかかる場合もあります。使用している特定の組み合わせを必ずテストしてください。

First Contentful Paint(FCP)の詳細を確認する。ユーザーがページに初めて移動してから、ページのコンテンツのいずれかの部分が画面上にレンダリングされるまでの時間を測定します。「コンテンツ」とは、テキスト、画像(背景画像を含む)、<svg> 要素、白以外の <canvas> 要素を指します。

ベクター グラフィックを使用

Scalable Vector Graphics(SVG)は、スケーラブルな画像を提供するための優れた方法です。ベクター グラフィックに適した画像の場合、SVG は非常に小さいファイルサイズで高品質の画像を提供します。

高解像度の写真を提供してください

高 DPI デバイスに適した写真を使用し、CSS を使用して画像を拡大縮小します。これにより、デバイス間で高品質の画像をレンダリングできます。画像の生成時に高圧縮(低画質設定)を使用すると、妥当なファイルサイズで優れた視覚効果を得ることができます。

このアプローチにはいくつかの潜在的なデメリットがあります。圧縮率が高い画像には視覚的なアーティファクトが表示される可能性があるため、許容できる圧縮レベルをテストする必要があります。また、CSS で画像のサイズを変更するのは、負荷の高いオペレーションになる可能性があります。

高圧縮がニーズに合わない場合は、WebP 形式を試してください。WebP 形式では、比較的小さなファイルサイズで高品質の画像を実現できます。WebP がサポートされていない Android バージョンには、必ず代替手段を用意してください。

きめ細かい管理

多くの場合、すべてのデバイスに 1 つのイメージを使用することはできません。この場合、画面サイズと密度に基づいて異なる画像を選択できます。メディアクエリを使用して、画面サイズと密度に応じて背景画像を選択します。

JavaScript を使用して画像の読み込み方法を制御することもできますが、複雑になります。

メディアクエリと画面密度

画面密度に基づいて画像を選択するには、メディアクエリで dpi または dppx 単位を使用する必要があります。dpi 単位は CSS インチあたりのドット数、dppx 単位は CSS ピクセルあたりのドット数を表します。

次の表に、dpidppx の関係を示します。

デバイスのピクセル比 一般的な画面密度 CSS インチあたりのドット数(dpi CSS ピクセルあたりのドット数(dppx
1x MDPI 96dpi 1 dppx
1.5 倍 HDPI 144dpi 1.5dppx
2 XHDPI 192dpi 2 dppx

一般化された画面密度バケットは Android によって定義され、他の場所で画面密度を表すために使用されます(https://screensiz.es など)。

背景画像

メディアクエリを使用すると、要素に背景画像を割り当てることができます。たとえば、ピクセル比が 1.0 のデバイスに 256 ピクセル x 256 ピクセルのロゴ画像がある場合は、次の CSS ルールを使用できます。

.welcome-header > h1 {
  flex: 1;

  width: 100%;

  max-height: 256px;
  max-width: 256px;

  background-image: url('../images/html5_256x256.png');
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

デバイスのピクセル比が 1.5(hdpi)と 2.0(xhdpi)のデバイスで、この画像をより大きな画像に置き換えるには、次のルールを追加します。

@media screen and (min-resolution: 1.5dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_384x384.png');
  }
}

@media screen and (min-resolution: 2dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_512x512.png');
  }
}

この手法は、min-width などの他のメディアクエリと統合できます。これは、さまざまなフォーム ファクタを考慮する場合に便利です。

@media screen and (min-resolution: 2dppx) {
  .welcome-header > h1{
    background-image: url('../images/html5_512x512.png');
  }
}

@media screen and (min-resolution: 2dppx) and (min-width: 1000px) {
  .welcome-header > h1{
    background-image: url('../images/html5_1024x1024.png');

    max-height: 512px;
    max-width: 512px;
  }
}

max-heightmax-width は、2ddpx 解像度で 512 ピクセルに設定されていますが、画像は 1,024 x 1,024 ピクセルです。これは、CSS の「ピクセル」が実際にはデバイスのピクセル比率(512 ピクセル × 2 = 1,024 ピクセル)を考慮しているためです。

<img/> はいかがですか?

現在のウェブには、この問題の解決策がありません。いくつかの提案がありますが、現在のブラウザや WebView では利用できません。

一方、JavaScript で DOM を生成する場合は、慎重にディレクトリ構造を設計して、複数の画像リソースを作成できます。

images/
  mdpi/
    imagename.png
  hdpi/
    imagename.png
  xhdpi/
    imagename.png

次に、ピクセル比を使用して、最も適切な画像を取得してみます。

function getDensityDirectoryName() {
  if(!window.devicePixelRatio) {
    return 'mdpi';
  }

  if(window.devicePixelRatio > 1.5) {
    return 'xhdpi';
  } else if(window.devicePixelRatio > 1.0) {
    return 'hdpi';
  }

  return 'mdpi';
}

または、ページのベース URL を変更して、画像の相対 URL を定義することもできます。

<!doctype html>
<html class="no-js">
<head>
  <script>
    function getDensityDirectoryName() {
      if(!window.devicePixelRatio) {
          return 'mdpi';
      }

      if(window.devicePixelRatio > 1.5) {
          return 'xhdpi';
      } else if(window.devicePixelRatio > 1.0) {
          return 'hdpi';
      }

      return 'mdpi';
    }

    var baseUrl =
        'file:///android_asset/www/img-js-diff/ratiores/'+getDensityDirectoryName()+'/';
    document.write('<base href="'+baseUrl+'">');
  </script>

    ...
</head>
<body>
    ...
</body>
</html>

このアプローチでは、ベース URL が解像度固有のディレクトリを参照するため、ページの読み込みがブロックされ、画像、スクリプト、CSS ファイルなど、すべてのリソースで絶対パスが強制的に使用されます。