ブラウザの「寛容さ」に甘えるな:レンダリングエンジンの裏側とHTMLパースの不都合な真実
現場でコードを書いていると、「Chromeでは綺麗に出るのに、Safariだと微妙にレイアウトが崩れる」とか「Firefoxでだけ謎の余白ができる」といった、いわゆる“ブラウザ間の挙動差異”に頭を抱えることはないだろうか?
多くのジュニアや中級エンジニアは、これを「ブラウザのバグ」と片付けがちだ。だが、シニアの視点から言わせてもらえば、それはバグではない。各ブラウザエンジンが、壊れたHTMLを「どうやって救い出すか」という設計思想の違いに過ぎないんだ。
今日は、Blink (Chrome/Edge), WebKit (Safari), Gecko (Firefox) が、裏側でどうやってHTMLを解釈し、その“寛容さ”がどう実務に牙を向くのか、その深淵を覗いていこう。
—
HTMLパースの「お節介」機能を知る
ブラウザは、HTMLが多少壊れていても画面を映し出そうとする。これを「エラー回復(Error Recovery)」と呼ぶ。HTML5仕様書にはこのアルゴリズムが詳細に定義されているが、歴史的経緯から、エンジンごとに微細な「お節介」の仕方が異なる。
1. タグの自動補完と欠損の修復
例えば、`
| セル |
このとき、ブラウザはDOMを構築する際、「親の期待値に合わせる」という強引な補完を行う。
- Blink/WebKit: `div`を`table`の外(直前)に追い出す。
- Gecko: `div`を`table`の内部に保持しつつ、無理やり`td`で囲うようなツリー構造を生成する。
結果、CSSのセレクタ(`table > div`など)がエンジンによって効いたり効かなかったりする惨劇が生まれるわけだ。
2. Quirksモード(後方互換モード)の地雷
ブラウザには「標準モード」と「Quirksモード」がある。HTMLの先頭に``がないだけで、エンジンは「昔の汚いWebページかもしれない」と判断し、独自のレガシーな解釈ルールを適用する。
特に、ボックスモデルの解釈(`box-sizing`)や、`img`タグの下部に発生する謎の隙間は、このQuirksモードの残滓によるものが多い。今どき`実践:ブラウザのパース挙動を検証する
百聞は一見にしかず。以下のコードをブラウザで動かして、`console`でDOMの構造を比較してみてほしい。エンジンの「性格」が如実に現れるはずだ。
// 検証用コード:ブラウザのDOM構築の「お節介」を可視化する
const container = document.createElement(‘div’);
// tableの中に不正に配置された要素
container.innerHTML = ‘
| セル |
‘;
// DOMツリーを解析して、ブラウザがどう「修復」したかを確認
const table = container.querySelector(‘table’);
console.log(‘tableの子供:’, table.children);
/
- ここで注目すべき点:
- 1. Chrome(Blink)では、pタグがtableの外に弾き出されているはず。
- 2. ブラウザによってpタグがどこに移動(または消失)したかを確認することで、
- CSSのセレクタがなぜ機能しなかったのかの答え合わせができる。
/
—
フロントエンドエンジニアが守るべき鉄則
ブラウザのパース能力に甘えるのは、自分の書くコードの寿命を縮めることと同義だ。以下のプラクティスを叩き込んでおいてほしい。
1. バリデーションを過信しない: HTMLの閉じタグ忘れや、ブロック要素の中にインライン要素を無理やり突っ込む構成は、エンジンごとの差異を最大限に引き出してしまう。リンター(`eslint-plugin-html`など)を導入し、CIで強制的に弾く仕組みを作れ。
2. DevToolsの「Elements」タブを信じるな: あれは「ブラウザが解釈した後のDOM」を表示している。ブラウザが勝手に補完した`

コメント