O hirunewani blog

Q. iPhoneで見るとフォーム画面が崩れる

Created at

iPhoneで見るとフォーム画面が崩れる問題について調査した結果をまとめた。

Table of Contents

状況

ビューポートの幅が320pxの端末で、フォーム画面のレイアウト崩れが発生していました。

具体的には、見かけ上は何も要素が存在しないのに、右側で空間が生まれてしまっていました。

フォーム画面には、テキスト入力に加えてセレクトボックスなど複数の要素がありますが、いずれの要素も適切な範囲に表示されており、余分な余白なども定義されていませんでした。

次のような手順で調査を行いました。

  • Safariのレスポンシブ・デザイン・モードを利用する
  • 検証ツールを開く
  • 次のようなスタイルを挿入する
* {
  border: 1px solid rgba(0, 0, 0, 0.02) !important;
  background-color: rgba(0, 0, 0, 0.02) !important;
  opacity: 1 !important;
}
  • はみ出ている要素を探す

この調査を行ったところ、Safariでのみセレクトボックスのコンポーネント内にある隠しInput要素の幅が368pxになっていることが分かりました。

対処

隠しinput要素に明示的な幅を与えたり、親要素にoverflow: hiddenをかけるなどをすれば対処できます。そもそも置換要素に限らず、この辺りのスタイルを適切にかけるようにしていれば発生しない問題なので気をつけましょう。

調査2

置換要素であるinput要素は、特にスタイルをしなくても一定の領域を占有します。そのため幅があることはおかしくないですが、イメージとしておよそ100pxから200pxであり、368pxという値はあまりに大きすぎるような気がします。そこでなぜここまで大きくなっているのか調査しました。

隠しInput要素に適用されていたスタイルは、user agent stylesheetの除けば以下のような記述のみ行われていました。フォントによって置換要素の占有する領域が拡張されるのは直感的だと思います。

.hidden-input {
  position: absolute;
  pointer-events: none;
  font: inherit;
}

試しにfont: inheritを消すと、ChromeとSafari両方で横幅が147pxになりました。検証用のページを雑に作りChromeとSafariで比べてみました。結果は次の通りです。

Chrome 114Safari 16.1
user agent stylesheet147px147px
font: 16px;175px202px
font: “Noto Sans JP”162px230px
font: 16px “Noto Sans JP”192px331px
font: 16px “M Plus 1p”207px316px
font: 16px “Roboto”168px178px

Safariでは、日本語フォントを適用するとInput要素のデフォルトの幅がかなり大きくなることが分かりました。

置換要素の占有領域はそもそもブラウザ依存ですが、結果を見ると、ChromeとSafariではUA Stylesheetによるフォントの指定が異なるにも関わらずデフォルト147pxで共通してはいるものの、ChromeとSafariで逆転しているケースがあるなど、異なるアルゴリズムで組まれていそうな気がします。

あまりこのようなケースに当たることはないと思うので、これ以上調べる気はないですが、他のフォントのケースはどうなるのか、どのような実装がされているのか調べると面白いかもしれません。