last update

初期状態で指定の幅にズームさせたスマホサイトが作れないか検討してみた

大昔にモバイルサイトの配信を中止して以来、久しぶりに、スマホ向けの軽量ページを試験導入しました。

とりあえずは、PCとスマホにそれぞれ違うページを出せる基盤を作っただけ。って事で、PC版の機能を一部取り除いたものを仮にスマホ版としています。

現時点ではスマホ版・PC版間の遷移機能は設けていないので、 必要なら Android 標準ブラウザや Chrome の「PC版サイトのリクエスト」機能を使ってもらうと、フルページにアクセスできますし、また、サイトのトップはPC・スマホ共通にしていますので、人気記事などの一覧も変わらず見れます。

ちょっとづつ色々変えていく予定ですので、よろしくおねがいします。です。

で、さて、スマホ向けサイトと言えば避けて通れないのが「Viewport」ですが、色々触っているうちに、「スマホの場合はPCサイトの本文部分の幅に最初からズーム表示させておく。なんて事ができるんじゃ?」と思って色々試してみたのでその時のメモを(自分のために)書いておきます。

※この記事は自分用メモなので、今後も更新する可能性があります。

※2013/2/28 Android版Chromeのアップデートでviewport周りが素直になったので、それに合わせて記事を修正

initial-scaleを算出するのに必要なパラメータ

Android 向けの viewport はメタタグにこんな感じで書くわけですが、

<meta name="viewport" content="target-densitydpi=medium-dpi, width=device-width, initial-scale=1, minimum-scale=0.3, maximum-scale=3.0, user-scalable=yes" />

任意の幅に合わせてズームする initial-scale を求めるには、機種ごとの初期表示領域の幅を知る必要があります。

色々試した結果、Android 4.0 版の Chrome ならこんな感じで取れそうじゃん。と。

var scWidth = screen.width; // Yields width of the Viewport. 
var dvPixelRatio = window.devicePixelRatio; 
var innerWidth = scWidth; // Yields default width of the Display area. 
var scaleTo = 540; 
var iniScale = Math.round((innerWidth/scaleTo)*10000)/10000;

※2013年2月末のChromeアップデート以前、および、2013年2月に確認した Android 4.0 標準ブラウザでは innerWidth = scWidth / dvPixelRatio; だったような。

で、こんな感じでMETAタグをセットしてやります。

var meta = document.createElement('meta'); 
meta.setAttribute('content', 'target-densitydpi=medium-dpi, initial-scale=' + iniScale + ', minimum-scale=0.3, maximum-scale=3.0, user-scalable=yes'); 
document.getElementsByTagName('head')[0].appendChild(meta);

※これらは Chrome for Android 向けのコードなので、 UserAgent 毎に調査のして書き分ける必要があるでしょう。Viewport に width は設定した方が都合が良い場合もあったような…。

OS・機種・ブラウザ・状況で異なるViewportの幅と、devicePixelRatio、innerWidth

※2013年2月末のChromeアップデートにより、以下の情報は役に立たなくなりました。screen.width がそのまま Viewport の Width になったと思います。

とりあえず、重要なのは以下の3つ。

  • screen.width
    → Viewportの幅
  • window.devicePixelRatio
  • window.innerWidth
    → 表示領域のサイズ、ただし、レンダリング後はサイズが変わる

この内、問題なのが、innerWidth で、Android では initial-scale = 1 のプレーンな状態の数値がどうも確実には取れないような。

で、調べて見ると、こんな感じで相関関係が見いだせまして、

Viewportの幅/innerWidth/devicePixelRatio

***Chrome for Android***
某Android 4.0 480/320/1.5
某Android 4.1 800/400/2
某Android 4.2 800/600/1.33124

***Safari(iOS 6.1・参考用)***
iPhone 5 320/320/2

じゃあ、initial-scale=1 の時の window.innerWidth …というか初期表示幅は、

Viewportの幅/devicePixelRatio

で求められそうじゃん。という感じ。

とりあえず Chrome for Android 限定で Viewport のメタタグを出力しようかと思ったんですが、先にも書いたとおり、Chrome の UserAgentを騙るブラウザが結構あったり、Android標準ブラウザとChromeですら、このあたりの実装が違う。って事で、混乱を招くだけかなぁ。と思い結局お蔵入りに。がっくり。

コリコリに Javascript で書きまくってやればなんとかなりそうな予感もするんですが、そこまでするのもねー。という事で。

ちなみに Android での Viewport の設定については、公式サイトが非常に良い資料と思います。

その他参考サイト

コメントを記入