viewportのmetaタグは、モバイルブラウザに対して、ページのレイアウト領域の幅と最初の拡大率を指定するものです。ほぼすべてのWebサイトで、<head> に次の1行をそのまま書くべきです。
<meta name="viewport" content="width=device-width, initial-scale=1">
これがないと、スマホはページをPC向けのデザインとみなし、幅約980pxでレイアウトしてから画面に収まるよう縮小します。レスポンシブなCSSが効く機会がまったくありません。
viewport metaタグがないとどうなるか
スマホが登場した当時、ほとんどのWebサイトはPCの画面向けに作られていました。それを表示するために、モバイルブラウザはPCサイズの「レイアウトビューポート」(iOS版SafariとAndroid版Chromeでは980px)を持っているふりをし、ページ全体が画面に収まるよう縮小しました。ユーザーはピンチで拡大して読んでいたわけです。
この初期設定は、viewportタグのないページには今でも適用されます。画面幅390pxのスマホでは、そうしたページは次のようになります。
- CSSやJavaScriptに対して、表示領域の幅を約980pxと伝える
(max-width: 600px)のようなメディアクエリに決して一致しない- 文字が本来のサイズの約40%で表示される
スマホでサイトが小さなPC版ページのように見えるなら、まずこのタグを確認しましょう。サイトがスマホで崩れる原因で取り上げている中でも、最もよくある原因です。
各値の意味
| 値 | 意味 | 推奨 |
|---|---|---|
width=device-width |
レイアウトビューポートを端末のCSSピクセル幅に合わせる(多くのiPhoneでは390など) | はい |
initial-scale=1 |
拡大率100%で開始し、1 CSSピクセルを1デバイス非依存ピクセルに対応させる | はい |
minimum-scale |
許可する最小の拡大率 | ほとんど不要 |
maximum-scale |
許可する最大の拡大率 | 5未満の値は避ける |
user-scalable=no |
ピンチによる拡大を無効にする | 避ける |
width=1024(固定値) |
レイアウト幅を固定する | レスポンシブサイトでは避ける |
viewport-fit=cover |
ノッチや角丸の下までページを広げる | セーフエリアの余白とセットでのみ |
interactive-widget |
画面キーボードによるページのリサイズ方法を指定する | 任意 |
拡大を無効にすべきでない理由
user-scalable=no や maximum-scale=1 は、ユーザーが拡大できないようにします。弱視の人にとってはページが読みにくく、あるいは読めなくなり、文字を200%まで拡大できることというWCAGの要件にも反します。Lighthouseのアクセシビリティ監査でも指摘されます。
開発者がこれを入れるのは、iOS版Safariがフォーム欄で自動的に拡大するのを防ぐためであることが多いのですが、正しい対処法は入力欄の文字サイズを16px以上にすることです。
input, select, textarea { font-size: 1rem; }
そもそも最近のiOS版Safariは、ピンチ拡大については user-scalable=no を無視するので、このタグは主にほかのブラウザに悪影響を与えるだけです。
viewport-fit=coverとセーフエリア
ノッチ、Dynamic Island、角丸のあるスマホでは、ブラウザはデフォルトでページを安全な長方形の中に収めます。viewport-fit=cover を指定するとページが画面全体を使えるようになり、画面端まで使うデザインでは便利です。その場合は、ノッチやホームインジケーターにコンテンツがかからないよう、自分で調整する必要があります。
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">
.site-header {
padding-left: max(1rem, env(safe-area-inset-left));
padding-right: max(1rem, env(safe-area-inset-right));
}
.bottom-bar { padding-bottom: env(safe-area-inset-bottom); }
ノッチが横に来る横向きでもテストしましょう。
interactive-widgetと画面キーボード
キーボードが開くと、ブラウザは視覚ビューポートだけを縮める(ChromeとSafariのデフォルト)か、レイアウト全体をリサイズします。新しい interactive-widget の値で、どちらにするかを選べます。
resizes-visual:デフォルト。レイアウトのサイズは変わらず、キーボードが一部を覆うresizes-content:レイアウトビューポートが縮むので、100dvhの要素や固定フッターがキーボードの上に移動するoverlays-content:何もリサイズしない。VirtualKeyboard APIを使って自分で処理する
対応状況はブラウザによって異なります(Chromium系は対応。使う前に最新の対応状況を確認しましょう)。いずれにしても、フォームは実機でテストしてください。
削除してよい古い値
shrink-to-fit=noはiOS 9向けの回避策で、現在は効果がありません。target-densitydpiは古いAndroid向けの値で、無視されます。<meta name="HandheldFriendly">と<meta name="MobileOptimized">は、フィーチャーフォン時代のものです。
viewportタグの確認方法
- ページのソースを表示し、
name="viewport"を検索します。ちょうど1つだけあるべきです。 - モバイルモードでLighthouse監査を実行します(手順)。viewportタグがない場合や拡大を妨げている場合に報告されます。
- スマホ表示でページを開きます。DevToolsのデバイスモードや、実際のスマホのサイズでページを読み込む Mobile View Extension で開くと、タグのないページは縮小され、文字が小さく表示されます。
よくある質問
正しいviewport metaタグは?
<meta name="viewport" content="width=device-width, initial-scale=1"> です。全画面のレイアウトを作り、セーフエリアに対応する場合にだけ viewport-fit=cover を加えます。
レスポンシブデザインにviewport metaタグは必要ですか?
必要です。ないと、モバイルブラウザはページを幅約980pxでレイアウトするので、モバイル向けのメディアクエリが一切適用されません。
user-scalable=noを使うのはよくないですか?
アクセシビリティの面でよくありません。ユーザーが文字を拡大できなくなります。フォーム欄での不要な拡大は、入力欄の文字サイズを16pxにして防ぎましょう。