問題の再定義
本記事で扱う最適化(アダプティブ)は、従来の@mediaメディアクエリを指すものではありません。
-
media queryはモバイルデバイス、PC、タブレットを区別するために使用され、それぞれのデバイスに対して3種類のスタイルを書く必要があります。一般的には、幅のパーセント指定や、小さな画面での一部コンテンツの非表示化などが行われます。 -
本記事で議論する最適化は、ページのレイアウトやコンテンツを変更せずに、各モバイルデバイス上での視覚的な効果をほぼ同じにすることを目的としています。例えば:
iPhone 6とiPhone 4でほぼ同じ効果を得ることを目指します。純粋なCSSだけでは不可能であり、多様なモバイルデバイスに適応させるにはJavaScriptとレイアウトの連携が必要です。モバイルデバイスの画面最適化には多くの難点があります:
- アスペクト比の違い
横に広く縦に短いスマホもあれば、縦に細長いスマホもあります。
- DPIの違い
画面は非常に小さいが、解像度が極めて高いものもあります。
- 高精細ディスプレイ(Retina)での画像のぼやけ
1つのピクセルを複数のセグメントに分割して表示するディスプレイがあります。
media queryはこれらの問題を解決するのには役立ちません。本記事で議論する手法も、あくまで妥協的な解決策(手間がかかる、あるいは副作用がある)に過ぎません。
1. scale/zoomによるページ全体のスケーリング
1. scaleとzoomの違い
-
zoomスケーリング:デフォルトで左上を起点とし、変更できません。周囲の要素を覆ってしまう問題は発生しません。
-
scaleスケーリング:デフォルトで中心を起点としますが、変更可能です。周囲の要素を覆ってしまう問題があります(拡大された部分が空間を占有しないため)。
-
zoomを子要素に適用すると、整列が崩れます。
-
scaleを子要素に適用すると整列が崩れ、インライン要素には無効です。
-
zoomを親要素に適用しても、相対的な位置関係には影響しません。
-
scaleを親要素に適用する場合、起点を左上に設定すれば相対的な位置関係に影響しません。
-
zoomはFirefox以外のすべてのブラウザ(IE5.5+)と互換性があります。
-
scaleはIE11+およびFirefoxと互換性があります。
DEMO: scaleとzoomの違い
2. scaleの副作用
- inputのカーソルが太くなる
scaleをページ全体に適用すると、iOSにおいてページ内のInputやTextareaなどの入力欄のカーソルが太くなり、非常に見栄えが悪くなります。Androidでは発生しないようです。
解決策:scaleによる最適化を諦め、別の手法を採用する。
- z-index
scaleがz-indexの効果に影響を与える可能性があります。確実ではありませんが、z-index、fixed、ソフトウェアキーボードといった要素が相互に影響し合い、解決が極めて困難な別の問題を引き起こすことがあります。
解決策:floatはzを無効にし、positionのデフォルト値もzを無効にします。詳細はdiv層調整zindex属性无效原因分析及解决方法を参照してください。
- 水平スクロールバー
ワイド画面では消えない水平スクロールバーが表示されることがあり、overflowをどのように設定しても無効な場合があります。
解決策:bodyにscaleを設定するのではなく、wrapperに設定してください。元々そうしている場合は逆に(bodyに設定)してみて、それでもダメなら、z-index、fixed、inputなどの他の要因を切り離して検討してください。
- fixedレイアウトの無効化
scale適用後、fixedレイアウトが無効になり、fixed設定した部分がページと一緒にスクロールされるようになります。ソフトウェアキーボードの表示もこの問題を引き起こします。
解決策:absolute + JSによる補助的な位置調整に変更してください。複雑なfixedレイアウト(fixedレイヤー上にinputがある場合など)であれば、scaleによる最適化は諦めた方が賢明です。バグが次々と発生します。
- ソフトウェアキーボードによるレイアウト崩れ
ソフトウェアキーボードが表示されるとfixedレイアウトが無効になります。現在のところ解決策はありません。
3. 結論
「シンプルな」ページであれば、安心してscaleスケーリングを使用できます。「シンプル」の定義は以下の通りです:
-
inputやtextareaなどの入力欄がなく、ソフトウェアキーボードが表示されないこと。
-
複雑なz-indexの階層構造がないこと。
-
fixed(固定配置)部分がないこと。
ページが上記のいずれか1つでも満たさない場合、scaleによるスケーリングは避けるべきです。バグの猛攻に遭うことになります。
P.S. 筆者はzoomによる最適化をあまり使いませんが、scaleとzoomのどちらを使うべきかについては以下の原則があります:
-
大前提:モバイルページでIEのサポートが不要ならscaleを使用できます。必要ならzoomを使いましょう。Firefoxとの互換性が重要ならハックを追加する必要があります。
-
画像のスケーリングにはzoomとscaleのどちらでも構いませんが、ページ全体のスケーリングにはscaleを推奨します。
4. 事例
高德地图_绿色出行活动:scaleスケーリングによるページ全体の最適化
5. フレームワーク
白樹氏のpageResponse、1.4Kの超軽量ライブラリ
2. font-size + em/rem 相対単位
1. emによるスケーリング
html(またはbody)にfont-size: 62.5%;を設定する必要があります(いわゆる62.5%ハック。計算を容易にするために1em=10pxにするため。原文ママ:65.5%)。その後、すべての長さの単位をemに統一します。もちろん、JSを使用してhtml(またはbody)のfont-sizeを動的に変更する必要があります。
DEMO: emによるスケーリング最適化(注意:現在の要素のfz値はtop/left/right/bottomの配置に影響するため、fz制御用にもう一層重ねる必要があります。外側を配置に使用します)
emの使用は推奨しません。理由は以下の通りです:
- 計算が困難
現在の要素のfz値はすべての祖先要素に依存します。
- 冗長なタグ
上記の注意点にある通りです。
- 柔軟性に欠け、メンテナンスが困難
現在の要素のfz値はすべての要素に影響します。
2. remによるスケーリング
最も重要なのは互換性です:[IE8以下]はremをサポートしていません。
計算を楽にするためにhtmlにfont-size: 10px;を必ず設定してください。その後、すべての単位をremに統一し、JSでhtmlのfz値を調整します。
DEMO:remによるスケーリング最適化
可能な限りremを使用することをお勧めします。remは継承の問題がなく、祖先のfz値を気にする必要がないため、非常に柔軟です。唯一の欠点は互換性の問題([IE8以下]で非対応)です。
3. 注意事項
em/remを使用する際、Chromeの一部のバージョンではfont-sizeが12未満になることをサポートしていない点に注意してください(fzを10に設定しても、実際のレンダリングは12になります)。この場合、62.5%ハックが無効になり、1em/1remは10pxではなく12pxになります。
新しいバージョンのChromeでは、-webkit-text-size-adjust: none;を設定しても効果がなく、モバイル端末での効果は不明です。
4. 事例
淘宝網モバイル版:シングルスクリーン + JSによる擬似スクロール(非常に強力です!)
5. em/remを使用するメリット
(余談ですが、本筋とはあまり関係ありません)
テキストにのみem/remをフォント単位として使い、他はpxを使うページがあるのはなぜでしょうか?
それは、pxは絶対単位であり、ユーザーがブラウザのデフォルトフォントサイズを設定しても、テキストの単位がpxであればユーザーの設定に応じて拡大・縮小されないのに対し、em/remであれば変化するためです。
3. img + div 幅パーセント指定、高さauto
これは古い手法で特に目新しくはありません。欠点はテキストがスケーリングに追従しないことで、2つの解決策があります:
- テキストをすべて画像に含める
欠点はページの読み込みが遅くなることです。
- JSで手動計算してfz値を変更し、フォントをスケーリングする(em/remとの併用)
画面の幅、高さ、DPIなどから特定の倍率を算出し、ベースとなるfzに乗じてフォントをスケーリングします。欠点は手間がかかることと、適切な倍率を算出するのが難しい(一部の機種にしか適合しない)ことです。
DEMO:省略します。事例を参考にしてください。
事例
-
高德地图_全明星导航语音活动:フォントのスケーリング処理は行われていません。要求レベルは高くありません。
-
京東モバイル版:フォントのスケーリング処理は行われていませんが、コンテンツが画像中心であるため、影響は限定的です。
4. モバイルページの表示最適化手法まとめ
-
第一候補はscale/zoom手法です。ただし、ページがシンプルであること(定義は前述)が前提です。
-
それが難しければrem/em手法を検討してください。互換性(remはIE8以下で非対応)に注意してください。
-
どうしてもダメなら画像(img)手法を使います。要求が高くなければフォントは無視できますが、そうでなければ、苦労することになります。
コメントはまだありません