【やらかし】word-breakの知識不足でUI崩れを起こした(本番環境)

技術

やらかした

本番環境でUI崩れを起こした。

スマートフォン(以下略: SP)でサービスを開くと、テキストが横にはみ出して画面全体の表示が崩れていた。多数のユーザーに影響が出て、夜遅い時間に複数名に対応してもらうことになった。


この記事の要約

  • 失敗を認める:自分の確認不足と知識不足が招いた結果
  • 謝罪:影響を受けたユーザー、夜遅くに対応してくれた複数名に迷惑をかけた
  • 原因分析:SP実機確認の習慣がなかった/CSSの理解不足/テストデータが甘かった
  • 得た学び:「なぜうまくいったのか」を検証しないまま、同じやり方を踏襲していた
  • 次に活かす:シミュレータ確認の習慣化/見慣れないプロパティは調べてから使う/複数ケースでテストする

原因を掘ったら3つ出てきた

最初は「SP確認が足りなかった」で終わらせようとしていた。でもそれだと再発する。なぜSP確認が足りなかったのか、もう一段掘ってみた。

1. 習慣:PCレスポンシブ確認=実機確認という思い込み

PCブラウザのレスポンシブモードで確認して問題なかったので、それで十分だと思っていた。

でも実際には、PCブラウザのレスポンシブ表示は「画面幅を縮めているだけ」だ。実機とは以下の点で異なる。

PCブラウザ実機
タッチ操作擬似的本物
フォントレンダリングPC基準OS基準
スクロール挙動異なる本物
画面解像度近似値実際の値

今回はChromeでもSafariでも再現する問題だったので、ブラウザの差異ではなく「レスポンシブモードと実機の根本的な違い」が原因だった。

2. 知識:word-breakを理解せず使っていた

問題となった原因箇所のソースコードが以下のCSSだ。

word-break: keep-all;
line-break: loose;

これを理解せずそのまま使っていた。

keep-all はCJK(日本語・中国語・韓国語)テキストで単語を区切らない設定だ。通常の日本語文章には問題ないが、長い日本語・英単語が含まれる場合、折り返し位置が見つからずはみ出す。

正しくはこうだった。

word-break: normal;
overflow-wrap: break-word;
line-break: loose;

この3つのプロパティ、ちゃんと理解しておくと便利なので後述する。

3. 確認設計:単一ケースのみで確認していた

PCで確認した時、自分のテストデータは短いタイトルだった。短いテキストは keep-all でも問題なく折り返せる。

単一ケースだけで確認して「問題ない」と判断してしまった。


根本の学び

3つの原因に共通することがある。

「なぜうまくいったのか」を検証していなかった

PCレスポンシブで問題なかった → なぜ問題なかったか考えない → 同じやり方を続ける。 テストデータで問題なかった → なぜ問題なかったか考えない → 本番で初めて気づく。

「うまくいった」を無批判に踏襲していた。条件が変わった時に初めて失敗する、という構造だった。


word-break / overflow-wrap / line-break を整理する

今回の反省として、ちゃんと理解したのでまとめておく。

word-break

改行しなければテキストがコンテンツボックスからあふれる場合に、ブラウザーが改行を挿入するかどうかを指定する。

word-break: normal | break-all | keep-all | auto-phrase(実験的) | break-word(非推奨)
挙動
normalデフォルト。言語のルールに従って折り返す
break-allCJK以外でも文字単位で折り返す。はみ出しを防ぐが英単語が途中で切れる
keep-allCJKテキストで単語を区切らない。長い英単語が連続するとはみ出す可能性がある
auto-phrase意味のある単位で折り返す(実験的、未サポート多い)
break-wordoverflow-wrap: break-word と同様の挙動。非推奨

overflow-wrap

単語が長くてコンテンツボックスからあふれる場合に、ブラウザーが強制的に改行を挿入するかどうかを指定する。

overflow-wrap: normal | break-word | anywhere
挙動
normalデフォルト。単語の境界(スペース等)でのみ折り返す
break-wordはみ出す場合のみ、単語の途中でも折り返す。自然な折り返しを優先しつつはみ出しを防ぐ
anywherebreak-word と似ているが、min-content サイズの計算にも影響する

line-break

CJK(日本語・中国語・韓国語)テキストの改行ルールの強さを指定する。句読点や記号をどう扱うかに影響する。

line-break: auto | loose | normal | strict | anywhere
挙動
autoデフォルト。ブラウザが判断
loose最も緩いルール。句読点前後で折り返しやすい
normal標準的なルール
strict最も厳しいルール。句読点前後での折り返しを抑制
anywhere禁則処理を無視してどこでも折り返す

3つの関係性

word-break    → 主に「単語をどこで切るか」
overflow-wrap → 主に「はみ出す時だけ切るか」
line-break    → 主に「CJKの句読点まわりをどう扱うか」

適用される順番はこうだ。

1. line-break  → CJKの句読点・禁則文字の折り返し候補を決める
2. word-break  → 単語をどこで切るかのルールを適用する
3. overflow-wrap → それでもはみ出す場合の最終手段

日英混在コンテンツへの推奨設定

単語途中では切らない・感嘆符等で折り返してOK・要素内に収めるという要件なら、

word-break: normal;
overflow-wrap: break-word;
line-break: loose;

keep-all は「日本語の単語を絶対に切りたくない」特殊なケース向けなので、日英混在コンテンツには不向きだ。


次に活かすこと

  1. 習慣:デプロイ前にiOS Xcodeシミュレータで確認する
  2. 知識:見慣れないCSSプロパティはコピペ・流用前に必ず挙動を調べてから使う
  3. 確認設計:テストデータは短い・長い・記号多い等、複数ケースで確認する

やらかしたのは事実だ。でも「なぜうまくいったのか検証しない」という自分の癖に気づけたのは収穫だった。同じ失敗はしない。


なお、即座にrevertを行い、関係各所に謝罪し、本記事でまとめたような失敗の振り返りをチームにも共有、根本対応のPull Requestを作成して対応した。