Q. iPhoneで見るとフォーム画面が崩れる
状況
ビューポートの幅が 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 114 | Safari 16.1 | |
---|---|---|
user agent stylesheet | 147px | 147px |
font: 16px; | 175px | 202px |
font: “Noto Sans JP” | 162px | 230px |
font: 16px “Noto Sans JP” | 192px | 331px |
font: 16px “M Plus 1p” | 207px | 316px |
font: 16px “Roboto” | 168px | 178px |
Safari では、日本語フォントを適用すると Input 要素のデフォルトの幅がかなり大きくなることが分かりました。
置換要素の占有領域はそもそもブラウザ依存ですが、結果を見ると、Chrome と Safari では UA Stylesheet によるフォントの指定が異なるにも関わらずデフォルト 147px で共通してはいるものの、Chrome と Safari で逆転しているケースがあるなど、異なるアルゴリズムで組まれていそうな気がします。
あまりこのようなケースに当たることはないと思うので、これ以上調べる気はないですが、他のフォントのケースはどうなるのか、どのような実装がされているのか調べると面白いかもしれません。