結論:入力欄のfont-sizeを16px以上にすれば止まる
- iOS Safariは「16px未満のフォーム部品」にフォーカスすると自動でズームする仕様=CSSの書き間違いではない
- Androidでは起きないのでPCとAndroid検証だけでは発見できない
- ルートを62.5%(10px)にしているテーマは1.5remが15pxになり、気づかないままズーム対象になる
- user-scalable=no や maximum-scale=1 はiOSに無視されるので対策にならない
- 見た目を小さく保ちたいときはfont-sizeを16pxのまま padding と高さで詰める
スマホ実機でお問い合わせフォームを触ったときに、入力欄をタップした瞬間に画面全体がぐっと拡大し、そのまま戻らない——制作の現場でいちばん報告が上がるスマホ不具合のひとつです。しかもPCブラウザの検証モードでは再現せず、Androidでも起きません。原因はレイアウト崩れではなく、iOS Safariのフォーム操作に関する仕様です。実案件で踏んだ順に、原因の見分け方と実務で使っている直し方をまとめます。
なぜiPhoneだけ入力欄で拡大するのか
iOS Safariは、input / select / textarea にフォーカスが当たったとき、その部品の実効font-sizeが16px未満だと「文字が小さすぎて読めない」と判断して自動的にページをズームします。ユーザーが操作したわけではないので、ズームは入力を終えても自動では戻りません。結果として「フォームを触ったらサイトが拡大されたまま崩れた」という見え方になります。
ポイントは3つあります。
- 判定されるのはフォーム部品自身のfont-sizeであって、body側の指定ではない
- 16pxちょうどはセーフ、15.5pxでもアウト(実機で境界を確認したところ、15.5pxではズームし、16pxでは発生しませんでした)
- Android ChromeとPCブラウザでは発生しない=iPhone実機を触らないと気づけない
ブラウザの開発者ツールのデバイスモードでも再現しないため、コードレビューでも見落とされます。iPhone実機かiOSシミュレータでフォームを1回タップする——これが唯一の確実な検出方法です。
いちばん多い原因:ルート62.5%のテーマで1.5remが15pxになっている
「フォームには何も指定していないのにズームする」という相談のほとんどが、これでした。html { font-size: 62.5%; } を敷いて1rem = 10pxとして扱う設計は日本語テーマでよく使われます(当サイトが使っているlionmedia系の子テーマもこの設計です)。この状態で、デザインカンプの「15px」を素直に 1.5rem と書くと、実効値は15px=16px未満なのでズーム対象になります。
厄介なのは、開発者ツール上の表示は意図どおり15pxで、CSSとしては何も間違っていないことです。「正しく書いたのに壊れる」ため原因にたどり着きにくい。まず現状を洗い出します。
// SCSSソースからフォーム系のfont-size指定を洗い出す
grep -rnE "(input|select|textarea|\.c-form|\.p-contact)" src/scss \
| grep -n "font-size"
// remで書かれた15px以下(62.5%環境で1.5rem未満)を機械的に拾う
grep -rnE "font-size:\s*(0\.[0-9]+|1\.[0-5])rem" src/scss
拾ったうち、フォーム部品にかかるものだけを1.6rem(=16px)以上に上げます。全部を上げる必要はありません。フォーカスを受ける要素だけが対象です。
直し方:フォーム部品にだけ16pxを保証する
実務では、個別のクラスを追いかけるより、要素セレクタで下限を敷いてしまうほうが事故が減ります。
/* 62.5%設計でも実寸16pxを保証する */
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select,
textarea {
font-size: 16px; /* remではなくpxで固定=ルート変更の影響を受けない */
}
/* PCだけ見た目を小さくしたい場合は hover/pointer で切り分ける */
@media (hover: hover) and (pointer: fine) {
input:not([type="checkbox"]):not([type="radio"]):not([type="range"]),
select,
textarea {
font-size: 1.4rem;
}
}
ここで px を使うのは意図的です。remで書くとルートのfont-sizeを後から変更したときに静かに16pxを割り込みます。この1箇所だけはpx固定にしておくほうが将来の事故を防げます。PC側の見た目を小さく保ちたい場合は、上の例のように「マウスがある環境」に限定して小さいサイズを当てれば両立します(max-widthのメディアクエリではなく hover: hover で分けるのは、タッチ対応ノートPCで取りこぼさないためです)。
チェックボックス・ラジオ・rangeを除外しているのは、これらがフォーカスしてもズーム判定の対象にならず、font-sizeを上げるとレイアウトが崩れる場合があるためです。
user-scalable=no や maximum-scale=1 は対策にならない
検索するとviewportメタタグでズーム自体を禁止する方法が上位に出てきますが、これは現在のiOSでは効きません。
<!-- iOS 10 以降のSafariはこの指定を無視する(=拡大は止まらない) -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
iOS 10以降のSafariは、アクセシビリティ上の理由から user-scalable=no と maximum-scale を意図的に無視します。実機で試すと分かりますが、この指定を入れてもフォーカス時の自動ズームは変わらず発生します。加えて、この指定はユーザー自身のピンチ操作まで禁じる意図を持つため、視力に配慮した実装としても外すべきものです。古い記事の情報がそのまま残っているケースなので、テンプレートに入っていたら削除して問題ありません。viewportは次の1行で十分です。
<meta name="viewport" content="width=device-width, initial-scale=1">
16pxのまま見た目を小さく見せたいとき
「デザイン上どうしても入力欄を小さく見せたい」という要件は現実にあります。font-sizeを下げる以外の手が3つあります。
- 高さとpaddingで詰める:
padding: 6px 10px; line-height: 1.2;にすれば、font-size 16pxでも入力欄の高さは十分に下げられます。実務ではこれで足りるケースが大半です - プレースホルダだけ小さくする:
::placeholder { font-size: 13px; }はズーム判定に影響しません。ラベル代わりの補足文だけ小さくしたいときに使えます - transform: scale() で見かけを縮める:
font-size: 16pxのままtransform: scale(0.875)で見た目だけ14px相当にする方法。ただし要素のクリック領域とレイアウト計算がズレるため、フォーム全体に使うのは避け、どうしても寸法が合わない1箇所に限って使います
逆に避けたいのが、「フォーカス時だけJSでfont-sizeを16pxに書き換える」というよく紹介されるトリックです。フォーカスの瞬間にはすでにズーム判定が走っているためタイミングによって効いたり効かなかったりするうえ、入力中にフォントサイズが変わって行が跳ねます。実案件で採用して、Androidでだけ入力欄がガタつくクレームになったことがあります。素直に常時16pxが正解です。
ズームが起きなくなった後に残る「キーボードでCTAがずれる」問題
自動ズームを止めると、次に見えてくるのがソフトウェアキーボード表示中のレイアウトずれです。画面下に固定した送信ボタンやCTAが、キーボードに押し上げられて消えたり、逆にキーボードの裏に隠れたりします。position: fixed はiOSでキーボード表示時の基準がずれるため、CSSだけでは安定しません。
実務では visualViewport で実際に見えている領域を取得して、固定要素の位置を合わせています。
const vv = window.visualViewport;
const bar = document.querySelector('.js-fixed-bar');
function fitBar() {
if (!vv || !bar) return;
// 見えているビューポートの下端に合わせる
const offset = window.innerHeight - (vv.height + vv.offsetTop);
bar.style.transform = 'translateY(' + (-offset) + 'px)';
}
if (vv) {
vv.addEventListener('resize', fitBar);
vv.addEventListener('scroll', fitBar);
fitBar();
}
visualViewport は現行のiOS Safari / Android Chromeの双方で使えます。未対応環境では何もしない実装にしておけば、従来どおりの見え方に戻るだけなので安全に入れられます。なお、キーボード表示で高さが変わる話は 100vh のずれとも地続きなので、ビューポート単位の使い分けと合わせて設計しておくと崩れにくくなります。
公開前チェックリスト
- iPhone実機ですべての入力欄(text / email / tel / select / textarea / date)を1回ずつタップして、拡大しないことを確認する
- selectとdateは別指定になっていることが多いので個別に確認する(漏れが一番多いのがこの2つ)
- viewportメタタグから
user-scalable=noとmaximum-scaleを削除する - キーボード表示中に送信ボタンが隠れていないか確認する
- ピンチ操作でページを拡大できることを確認する(アクセシビリティ要件)
お問い合わせフォームは、サイトの中で唯一「成果に直結する画面」です。ここで拡大が起きて操作しづらいと、そのまま離脱につながります。修正自体は1行ですが、効果の出る場所としては優先度の高い1行です。
関連記事
- 多言語サイトの作り方完全ガイド|WordPress多言語対応の手順・費用・外注の判断基準(多言語フォームの入力欄設計もこちら)
- Web制作者が選ぶレンタルサーバー比較(フォームのメール到達性はサーバー選びにも影響します)
- WordPressのサーバー移行完全ガイド(移行後にフォームが動かないケースの確認手順)
多言語・ベトナム語サイトの制作でお困りではありませんか?
フォント・文字化け・WordPress多言語化・サーバー選定まで、多言語サイト制作の実績を持つ制作会社が一括対応します。お見積り・ご相談は無料です。
多言語サイト制作の詳細を見る →すぐに相談したい方は お問い合わせフォームへ