Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

はじめに

本書は、プログラミングスクール FjordBootCamp の教材として作成されたものです。FjordBootCamp では、単に文法や機能を暗記するのではなく、「なぜそうなっているのか」を理解し、自分で調べて判断できることを重視しています。本書も同じ方針で、HTML を表面的な書き方ではなく、その歴史、仕様、実装の背景から理解することを目指します。

この本は、HTML の書き方を学ぶ本ではありません。<div> の意味やフォームの作り方を最短で覚えたい人には、もっと適した入門書があります。本書が扱うのは、それより一段奥にある問いです。なぜ HTML はこういう形をしているのか。なぜブラウザはそこまで面倒を見るのか。なぜ「変」に見える仕様が、何十年も残り続けているのか。その理由を、歴史・仕様・実装の三つの面からたどります。

HTML はしばしば軽く見られます。プログラミング言語ではない。エラーを出さない。壊れたマークアップでも何となく表示される。そうした性質だけを拾うと、HTML は「適当な技術」に見えるかもしれません。しかし実際には、HTML は理想と現実の折衷を積み重ねながら、巨大な互換性の生態系を支えてきました。本書の目的は、その歴史を笑うことではなく、筋道を理解することです。

本書の想定読者は、HTML を一度は書いたことがある人です。Rails エンジニア、フロントエンド初中級者、Web 制作の経験者、教科書的な説明では物足りない人を主な読者として想定しています。厳密な仕様書を最初から読む必要はありませんが、仕様やブラウザ実装の話に踏み込むため、完全な初心者向けのやさしい導入書ではありません。

各章では、できるだけ次の順で話を進めます。まず短い具体例を置き、次にブラウザや仕様で何が起きているかを確認し、そのうえで「なぜそうなったのか」を説明します。最後に、よくある誤解や実務上の見方に触れます。知識を増やすより、HTML を見る解像度を上げることを目指します。

第1部 HTMLとは何だったのか

第1部の役割は、HTML を「タグの集まり」ではなく、文書共有の問題に対する解として見直すことです。ここで扱うのは、HTML の歴史的な出発点と、その設計対象です。ブラウザの補完やエラー回復の話はまだ扱いません。それらは第2部でまとめます。

第1章では、HTML がプログラミング言語ではないことを確認します。第2章では、HTML が何を解決したかったのかを CERN(欧州原子核研究機構)の文脈から見ます。第3章では、なぜ Web が PDF やワープロ文書ではなく HTML を中心に育ったのかを整理します。ここで土台を置いておくことで、後の章で出てくる「なぜそんなに寛容なのか」という疑問に答えやすくなります。

第1章 HTMLはプログラミング言語ではない

この章では、HTML を「処理を書く言語」ではなく「文書構造を記述する言語」として捉えます。ゴールは、HTML に iffor がないことを単なる不足ではなく、Web の基盤としての役割分担として説明できるようになることです。

前章にあたる前書きでは、「HTML は変な技術の寄せ集めではない」という本書全体の見方を示しました。この章は、その見方を最初に具体化する入口です。次章では HTML が何を解決したかったのかを CERN の情報共有という歴史から見ます。その前にまず、「HTML はそもそも何をする言語なのか」をはっきりさせておきます。

1.1 HTML は命令ではなく文書の役割を書く言語

プログラミング言語と聞くと、多くの人は条件分岐や繰り返しを思い浮かべます。if があり、for があり、値を保持する変数があり、処理の流れを自分で制御できる。JavaScript や Ruby はその意味で典型的なプログラミング言語です。

HTML は違います。HTML にあるのは、見出し、段落、リンク、画像、表、フォームのような文書の役割です。HTML が書いているのは「何を実行するか」ではなく、「この部分は何であるか」です。ここで言う「文書構造」とは、要素どうしの並びや階層だけではありません。見出し、段落、表といった意味上の役割まで含んだ構造です。

まず最小の例を見てください。

<h1>お知らせ</h1>
<p>会場が変更になりました。</p>

ここには命令がありません。あるのは「これは見出しです」「これは段落です」という構造だけです。しかもその構造は、単に箱が並んでいるという意味ではありません。「この部分は見出しとして読むべきだ」「この部分は段落として続けて読むべきだ」という意味の手がかりも含みます。HTML は画面の上で起きる処理を書くのではなく、そうした読み方まで含んだ文書の骨格を記述します。

この時点で、HTML は JavaScript や Ruby と別の種類の言語だと分かります。比較対象は「他のプログラミング言語」だけではありません。むしろ近いのは、文書に見出しや段落や脚注を付けるためのマークアップ言語です。マークアップ言語は、文章そのものに印を付けて「ここは見出し」「ここは段落」と役割を示す言語だと思えば十分です。HTML の M は Markup です。ここを見失うと、以後の章で出てくる多くの違和感が、「なぜこんな中途半端な言語なのか」という誤解に吸い込まれます。

1.2 だから HTML は CSS と JavaScript に役割を譲る

それでも実際の Web ページは、見出しや段落があるだけでは終わりません。色が付き、余白が付き、ボタンを押すと動きます。すると自然に、「結局いろいろやるなら、HTML が全部書けてもよかったのではないか」と思いたくなります。

しかし Web では、役割を分けたほうが都合がよい場面が多くありました。次の 3 つを見比べてください。

<h1 class="notice-title">お知らせ</h1>
<p id="notice-message">会場が変更になりました。</p>
.notice-title {
  color: #c00;
  margin-bottom: 0.5rem;
}
document.querySelector('#notice-message').hidden = false;

HTML が担当しているのは、「見出し」と「段落」という構造です。CSS は色や余白のような見た目を担当します。JavaScript は表示・非表示の切り替えのような振る舞いを担当します。

この分業は、ただ習慣でそうなったわけではありません。文書の構造、見た目、振る舞いは、変わる速さも、読む主体も、壊れたときの影響範囲も違います。見出しは検索エンジンや支援技術も読みますが、赤色かどうかはそうではありません。クリック時の動きは JavaScript が担いますが、見出しであること自体は JavaScript がなくても成立します。

つまり HTML が全部を抱えないのは、弱いからではありません。むしろ、何を自分の責務として持ち、何を他に任せるかをかなり明確に切り分けているからです。

1.3 iffor がないことは欠陥ではなく前提

ここで、よくある違和感を、逃げずに扱っておきます。HTML を初めて本格的に触ると、「どうして条件分岐も繰り返しも書けないのか」と感じます。テンプレートエンジンや JSX に慣れていると、この違和感はなおさら強くなります。

たとえば Rails の ERB では、次のように書けます。

<% if @articles.any? %>
  <ul>
    <% @articles.each do |article| %>
      <li><%= article.title %></li>
    <% end %>
  </ul>
<% end %>

この例で ifeach を担当しているのは Ruby です。HTML は、その結果として出力される ulli の構造だけを担当します。React の JSX でも事情は同じです。条件分岐や反復は JavaScript が書き、最終的にブラウザへ渡るときには HTML に相当する構造へ変換されます。

この事実は重要です。現代の開発者はしばしば、テンプレート言語やフレームワークの中で HTML を見ています。そのため、「HTML が条件分岐できている」ように見えることがあります。しかし本当は、条件分岐しているのは周辺の言語です。HTML 自体は最後まで、構造を表す役割に留まっています。

だから、HTML に iffor がないのは単なる未熟さではありません。HTML は最初から、処理系ではなく文書構造の共通表現として設計されていたからです。もし HTML 自体が複雑な処理を抱えていたら、ブラウザ以外の多くの読み手にとって扱いにくい形式になっていたはずです。

1.4 HTML が Web の基盤になれたのは読む主体が多かったから

「プログラミング言語ではないのに重要」という言い方には、まだ少し飛躍があります。そこで最後に、なぜ HTML が Web の基盤になれたのかを、読む主体の広さから押さえます。

ブラウザは HTML を読んで画面を作ります。これは直感的です。しかし HTML を読むのはブラウザだけではありません。検索エンジンは見出しやリンクの構造から文書の手がかりを拾います。スクリーンリーダーのような支援技術は、見出しやリストや表の構造を頼りに読み上げの順序を組み立てます。ここでいう支援技術は、画面を読み上げたり操作を助けたりして、情報へアクセスしやすくする道具です。アーカイブツールや変換ツールも、HTML を文書の骨格として読みます。

ここで大事なのは、これらの読み手が求めているのは「どう動くか」より先に「何であるか」だという点です。ある文字列が赤いかどうかより、それが見出しなのか、段落なのか、リンクなのかのほうが重要な場面が多くあります。HTML はまさにその情報を渡すための形式でした。

補足: もちろん現代の Web ページは JavaScript に強く依存することもあります。ただし、それでも最終的には多くの場合、ブラウザや他の利用者が読める HTML の構造へ落ちます。周辺技術が進化しても、HTML の役割が消えないのはこのためです。

誤解されやすいのは、「HTML は簡単だから基盤になった」という言い方です。正確には少し違います。HTML は文書構造に責務を絞っていたから、多くの主体が共有しやすい形式になりました。条件分岐や計算のような処理を抱え込まなかったからこそ、ブラウザ以外にも読まれやすい、長寿の土台になれたのです。

1.5 実務では「HTML だけで何でもやる」発想を疑う

この章の話は歴史や思想の説明に見えますが、実務上の判断にもつながります。HTML を構造記述の言語として見る癖が付くと、マークアップが崩れているときの違和感が変わります。

たとえば、見た目だけを合わせるために何でも div で囲っていないか、見出しにすべき箇所がただの太字テキストになっていないか、表として読むべき情報を無理に別の要素で並べていないか、という見方ができるようになります。言い換えると、「この書き方は見た目しか満たしていないのではないか」と疑う視点が持てます。逆に、HTML に本来ない責務を押しつけ始めると、後から CSS、JavaScript、検索、支援技術のどこかで痛みます。

この章の段階で「こう書けば正解」という細則を覚える必要はありません。ここで押さえておきたい判断基準は一つです。HTML は処理や見た目を全部抱える言語ではなく、文書構造を共有するための言語だということです。この前提を持つだけで、後の章で出てくる tabledivh1 の議論の見え方がかなり変わります。

1.6 構造記述という前提

HTML はプログラミング言語ではありません。iffor がないのは、能力不足だからではなく、文書構造を記述する役割に責務を絞っているからです。見出し、段落、リンク、表、フォームといった要素は、「どう処理するか」ではなく「それが何であるか」を表します。

この役割分担があるからこそ、見た目は CSS に、振る舞いは JavaScript に譲れます。そしてその結果、HTML はブラウザだけでなく、検索エンジン、支援技術、各種ツールが共有できる土台になりました。HTML に処理を書けないことは、Web の基盤として見ると欠陥ではなく前提です。

次章では、その前提の上で、HTML がそもそも何を解決したかったのかを見ます。文書構造を記述するという役割は、どこから必要になったのか。1980 年代末から 1990 年代初頭の CERN では、まさにその共有の問題が切実でした。そこから HTML の歴史に入ります。

参考資料

第2章 HTMLは何を解決したかったのか

この章では、HTML を単なるタグの集合ではなく、CERN(欧州原子核研究機構)における情報共有の問題への答えとして捉えます。ゴールは、HTML を URL や HTTP から切り離さずに説明し、「文書構造を記述する言語」という前章の整理が、どんな現実の困りごとから必要になったのかを説明できるようになることです。

前章では、HTML は処理を書く言語ではなく、文書構造を記述する言語だと見ました。しかし、それだけではまだ「なぜそんな言語が必要だったのか」は見えてきません。この章では、1980 年代末から 1990 年代初頭の CERN に戻り、HTML が何を解決したかったのかを確認します。CERN は、ヨーロッパにある大きな物理学の研究所です。次章では、その問題に対してなぜ PDF や Word ではなく HTML が Web の中心になったのかを比較します。

2.1 HTML が必要になったのは、情報がないからではなく、つながっていなかったから

1980 年代末の CERN には、研究者も文書も大量にありました。問題は、情報そのものが不足していたことではありません。むしろ逆で、情報はあるのに参照しづらく、つながっていないことが大きな痛みでした。

研究グループごとに使う計算機が違い、保存場所も違い、文書形式も違う。ある装置の説明書、別の研究チームのメモ、さらにその関連論文がそれぞれ別の場所にあり、誰が何を管理しているかも分かりにくい。新しく来た研究者にとっては、「必要な情報が存在すること」と「必要な情報へたどり着けること」が別問題でした。

Tim Berners-Lee(ティム・バーナーズ=リー)が 1989 年の提案書で問題にしたのは、まさにこの点です。提案書では、組織の中に人、装置、ソフトウェア、文書の関係が「mesh(網)」のように広がっているのに、それを横断してたどる道具が足りないと説明されています。人や装置や文書の関係が複雑に絡み合っているのに、それを横断して参照する共通の仕組みがない。だから必要だったのは、豪華な文書編集ソフトではなく、異なる環境の情報どうしを結びつけるための最小の共通基盤でした。

ここで重要なのは、出発点が「きれいなページを作りたい」ではなかったことです。必要だったのは、まず届くこと、参照できること、別の文書へ飛べることでした。HTML の性格を理解するとき、この出発点を忘れると、後の仕様の寛容さや単純さが見えなくなります。

2.2 ハイパーテキストは、文書を閉じた完成品ではなく参照の網に変えた

CERN の問題に対して、核になった発想はハイパーテキストでした。これは、文書の中から別の文書や別の項目へ飛べるようにする考え方です。紙の文書にも「参考: 第3章」や脚注はありますが、ハイパーテキストでは参照先へそのまま移動できます。要するに、文書を単体で閉じた読み物としてではなく、別の文書とつながる入り口つきの文書として扱う発想です。

最小の形で書けば、HTML のリンクはこうです。

<p>
  装置の仕様は
  <a href="detector-spec.html">こちらの文書</a>
  を参照してください。
</p>

この例で大事なのは、見た目ではありません。下線が付くか、青く表示されるかは本質ではない。重要なのは、「この文書のこの部分は、別の文書への参照である」と機械にも人間にも分かることです。

ここで前章の話がつながってきます。HTML が構造や役割を書く言語であることは、リンクにとって特に重要でした。リンクは単に文字列を飾る装飾ではなく、文書どうしを結びつける役割です。だから HTML に必要だったのは、複雑な計算より、見出し、段落、リスト、リンクのような文書の部品でした。

この時点で、HTML の「小ささ」は制約というより戦略だったと言えます。解こうとしていた問題が、最初からアプリケーションの UI 構築ではなく、文書を相互参照可能にすることだったからです。

2.3 Web は URL・HTTP・HTML の分業で成り立っている

ここまで読むと、HTML だけ見ていても全体像が分からない理由がはっきりしてきます。Web は最初から、ひとつの技術で完結するようには作られていませんでした。少なくとも次の 3 つが分業しています。

  1. URL は「何を取りに行くか」を示す
  2. HTTP は「どう取りに行くか」を示す
  3. HTML は「取りに行った文書がどんな構造か」を示す

同じ参照でも、役割を混ぜると理解が崩れます。まず URL だけを取り出すと、見えているのは参照先の識別子です。

https://example.org/reports/beam-status.html

この文字列だけでは、そこに何があるかは分かっても、「その中身がどういう構造か」は分かりません。次に HTTP を考えると、ここで扱っているのは取得のやり方です。たとえば概念的には、クライアントは「この場所の文書をください」と要求し、サーバーは本文を返します。

GET /reports/beam-status.html HTTP/1.1
Host: example.org

補足: ここでは現在よく見る形で示しています。Web 黎明期の HTTP はもっと素朴で、バージョン表記も Host: 行もなく、GET /... の一行だけでした(いわゆる HTTP/0.9)。役割を説明するために、ここでは現代的な書き方を借りています。

ここでも、まだ返ってきた本文が見出しなのか、リンクなのか、本文なのかは分かりません。そこで初めて HTML が必要になります。たとえば次のリンクを見てください。

<a href="https://example.org/reports/beam-status.html">
  現在の運転状況
</a>

この一行の中には、三つの役割が重なっています。https://example.org/reports/beam-status.html という識別先は URL の仕事です。そこへ取りに行く通信の取り決めは HTTP の仕事です。そして、「この文字列は別文書への参照である」という構造を表しているのが HTML の仕事です。

HTML 単体では Web になりません。しかし逆に、URL と HTTP だけでも Web になりません。取得した中身がただのバイト列のままでは、人も機械も「どこが見出しで、どこがリンクで、どこが本文か」を共有できないからです。HTML が解決したかったのは、まさにこの「取得した文書を、参照可能な構造として共有すること」でした。

この分業を押さえると、「HTML は何を解決したかったのか」という問いに、少し精密に答えられます。HTML は単独で全部を解決する技術ではなく、URL と HTTP と組み合わさって、リンク可能な文書空間を成立させる役割を引き受けていました。

URL は場所、HTTP は取得方法、HTML は中身の構造という 3 つの役割を並べた図
図 2-1 URL・HTTP・HTML は、それぞれ別の問いに答える。

2.4 初期の HTML が小さかったのは、問題設定が小さかったから

現代の HTML 仕様書は巨大です。フォーム、埋め込み、スクリプト、パーサー、エラー回復、アクセシビリティ関連まで含めると、とても「小さな文書形式」には見えません。すると、「そんなに大きい技術が、最初はなぜこんなに単純だったのか」という疑問が出ます。

答えは単純で、最初に解こうとしていた問題がもっと限定されていたからです。初期の HTML で中心だったのは、見出し、段落、リスト、リンクのような文書の基本部品でした。研究者どうしが文書を行き来し、読めればよい。そこでは、今日のような複雑なアプリケーション UI や高機能フォームまではまだ主眼ではありません。

ここで誤解を潰しておきます。初期の HTML が小さかったからといって、「あとから場当たり的に巨大化しただけだ」と片づけるのは雑です。もちろん歴史の積み重ねで仕様は膨らみました。しかし出発点を見ると、HTML は最初から万能環境を目指していたのではなく、共有文書のための最小基盤として始まっていたことが分かります。

この視点は、後の章でも役に立ちます。なぜブラウザが不完全な入力を読めるようにするのか。なぜ古い要素が簡単には消えないのか。なぜ仕様書の大半がパーサーの話になるのか。これらはどれも、「まず文書を読めるようにする」という原点から外れていません。

2.5 実務では、HTML を単独技術として理解しないほうが見通しがよくなる

この章の内容は歴史の話ですが、実務にもそのままつながります。HTML を単独の文法としてだけ見ると、リンク、フォーム送信、埋め込み、ルーティングの話がばらばらに見えます。しかし、URL・HTTP・HTML の分業として見ると、責務の境界がかなり整理されます。

たとえば Rails アプリでも、リンクを置く、フォームを送る、レスポンスとして HTML を返す、という流れは日常的です。link_to で URL を組み立て、コントローラが HTTP リクエストを受け、ビューが HTML を返す。このとき HTML がやっているのは、サーバー処理そのものではなく、「返ってきた文書のどこが何であるか」を示すことです。逆に、HTML に本来ない責務まで押しつけて理解しようとすると、ルーティング、通信、構造の境目が曖昧になります。

この章で押さえておきたい判断基準は、HTML を文書の側の技術として見ることです。単独の万能技術として見るのではなく、URL と HTTP と並ぶ 1 つの役割として見る。その見方を持つと、次章で HTML と PDF や Word を比べるときも、「何が高機能か」ではなく「何が問題設定に合っていたか」で比べられるようになります。

2.6 共有文書のための最小基盤

HTML が最初に解決したかったのは、見た目のよいページを作ることではありませんでした。CERN のような複雑な環境で、異なる文書や人や装置に関する情報を、環境差をまたいで参照できるようにすることでした。そこで必要だったのが、文書に見出しや段落やリンクの役割を与え、ハイパーテキストとして結びつけるための最小の言語でした。

その役割は、URL や HTTP と分業して初めて意味を持ちます。URL が参照先を示し、HTTP が取得手段を示し、HTML が中身の構造を示す。この三つがそろって、Web は単なるファイル置き場ではなく、リンク可能な文書空間になります。

次章では、この問題設定に対して、なぜ HTML が PDF や Word より適していたのかを見ます。HTML の小ささや単純さは、そこで初めて「弱さ」ではなく「条件への適合」として見えてきます。

参考資料

第3章 なぜWebはHTMLを選んだのか

この章では、Web がなぜ HTML を中心に育ったのかを、PDF や Word との比較から捉えます。ゴールは、HTML の弱さや貧しさに見える点を「なぜその問題設定には合っていたのか」という観点で説明できるようになることです。

前章では、HTML が解決したかったのは CERN における情報共有の問題であり、URL や HTTP と分業してリンク可能な文書空間を作る役割だったと見ました。この章では、その問題設定に対して、なぜ HTML が他の文書形式より適していたのかを比べます。次章からは第2部に入り、そうして選ばれた HTML をブラウザがどこまで補完しながら扱うのかを見ていきます。

3.1 PDF は完成した版面には強いが、接続された文書空間には向いていなかった

まず、比較対象として分かりやすいのが PDF です。PDF は、完成した見た目を崩さずに配るのに非常に強い形式です。送った相手の環境が違っても、ほぼ同じ版面で読ませたい。印刷もしたい。ページ番号、余白、段組み、図版配置を固定したい。そういう目的には今でもよく合っています。

たとえば、研究所の装置マニュアルを「この順番、この図版配置、この脚注位置で配りたい」とします。その場合、多少環境が違っても同じ見た目を保てる PDF はかなり自然です。読む側がどの端末でも同じ版面を見られること自体が価値になるからです。

この強さは、同時に Web 初期の目的とは少しずれていました。CERN で必要だったのは、「このページをこの版面のまま読ませたい」ということより、「別の計算機からでも読めて、別文書へ飛べて、更新された情報にたどりつける」ことでした。完成した紙面に近い文書より、参照し続けられる文書のほうが重要だったのです。

ここで必要だったのは、印刷前の完成原稿ではなく、更新され続けるノートや手順書や記録でした。昨日の測定結果から関連装置の説明へ飛び、そこから担当者のメモへ移れることのほうが、紙面の固定より価値がありました。つまり問題は「きれいに配ること」ではなく、「つながった状態で読めること」でした。

極端に言えば、PDF は閉じた完成品として優秀です。一方、Web が必要としていたのは開いた途中経過でもつながる文書でした。ここを逆に理解すると、「PDF のほうが高機能なのに、なぜ HTML が広がったのか」という見え方になります。しかし実際には、先にあったのは機能競争ではなく、問題設定の違いでした。

誤解しやすいのは、ここで PDF を「技術的に劣る形式」として扱うことです。そうではありません。固定レイアウトという設計目標に対しては、むしろ HTML よりはるかに筋が通っています。Web が別の方向を向いていたため、中心にならなかっただけです。

3.2 Word は編集には強いが、共有の土台としては重すぎた

次に Word のようなワープロ文書を考えます。Word は編集しやすさに強みがあります。文字を打ち、見出しを付け、表や画像を入れ、履歴を見ながら文書を育てていく。人間が一つの文書を作業対象として扱うには、とても便利です。

しかし、共有の基盤として見ると事情が変わります。ワープロ文書は、編集環境、ソフトウェア、バージョン差、レイアウト依存の影響を強く受けます。しかも、文書の一部から別の文書の一部へ軽く飛ぶという発想は、中心ではありません。Word は「今この文書をどう作るか」に強いのであって、「文書どうしをどう結びつけるか」を第一の目的にはしていません。

たとえば、ある部署の手順書を 1 本の Word 文書で管理していたとして、その途中に「この装置の仕様は別文書のここを参照」と大量に埋め込みたい場面を考えます。作業者が異なる環境でそれを開き、最新版へ迷わず移動し、さらに別の関連文書へ辿れることまで含めて標準化するのは、ワープロ文書の得意分野ではありません。

この差は、前章で見た URL・HTTP・HTML の分業とも関係しています。Word 文書を取得することはできます。しかし、取得した文書を環境差を越えて安定して読み、さらに別文書への参照を土台から組み込み、たくさんの利用者が同じ構造を共有する、という条件では重くなります。Word は編集ツールとして強いが、Web が必要としていた公開された文書空間の共通形式としては向いていませんでした。

ここで大事なのは、Word が劣っていたと言いたいのではないことです。PDF と同じく、向いている問題が違っただけです。「何が高機能か」より「何を解決したいのか」で評価しないと、技術選択の筋道を見誤ります。

ここまでの違いを雑に 1 行で縮めると、PDF は完成した配布物、Word は編集する作業物、HTML はつながる公開文書に強い、となります。もちろん現実には機能の重なりもありますが、最初にどこへ最適化された形式なのかを押さえると、比較を誤りにくくなります。

3.3 HTML は「リンクできる文書」であることを最優先した

では HTML は何を優先したのでしょうか。答えはかなりはっきりしています。HTML の強みは、文書をリンク可能な構造として扱えることです。見出し、段落、リスト、リンクという最小の部品を使って、別の文書へ参照を張り、その参照を受け手の環境差を越えて共有できる。ここに Web の核がありました。

最小の例で見ると、HTML のリンクはこうです。

<h1>運転記録</h1>
<p>
  今日のビーム状態は
  <a href="beam-status.html">こちらの記録</a>
  を参照してください。
</p>

この例の強みは、凝った見た目ではありません。重要なのは、文書の中に別文書への参照が自然に埋め込まれ、その意味が構造として共有されることです。PDF でもリンクは置けますし、Word でも参照は書けます。しかし HTML では、それが文書形式の中心にあります。リンクが脇役ではなく、文書を構成する基本動作になっているのです。

しかも、この参照はページ全体の見た目を固定しなくても成立します。見出しが多少違う幅で折り返されても、段落の行数が変わっても、リンクという機能自体は保たれます。ここでは版面の一致より、参照先へ確実に辿れることのほうが優先されています。

ここで前章の内容とつながります。HTML は URL や HTTP と分業することで、取得先、取得方法、文書構造をそれぞれ分けて持てました。そのため、文書を大きな一枚岩として閉じるのではなく、参照の網の中に置けます。Web に必要だったのは、まさにこの性質でした。

3.4 HTML は「見た目の厳密さ」より「環境差への強さ」を取った

HTML が PDF や Word より優れていたというとき、それは見た目の精密さの話ではありません。むしろそこでは HTML は不利です。フォント、余白、改ページ、紙面の完成度で見れば、PDF のほうがずっと強い場面があります。

それでも HTML が選ばれたのは、環境差に対して比較的強く、受け手に解釈を委ねながら読める形を保てたからです。送る側が完璧な完成版面を固定する代わりに、受け手のブラウザや環境でも読めることを優先する。その意味で HTML は、「完成品を配る形式」より「読めることを優先する形式」でした。

これは裏を返すと、送り手が細部の見た目を完全には支配できないということでもあります。HTML は、どの環境でもまったく同じ表示を保証するための形式ではありません。その代わり、受け手の装置やブラウザが違っても、文書構造とリンクを中心に内容へ辿りつきやすい。初期 Web では、この性質のほうが重要でした。

ここで誤解を潰しておきます。よく「HTML は貧弱だったから広まった」と言われます。しかし正確には、「当時の Web が解きたかった問題に対して必要十分だったから広まった」と言うべきです。貧弱さが偶然プラスに働いたのではありません。環境差を越えて読めること、リンクできること、更新された文書へ届きやすいことを優先した結果、HTML の単純さが強みになったのです。

この見方を持つと、HTML の後年の癖も少し見通しやすくなります。入力が多少壊れていても読めるようにする。古いページもなるべく壊さない。見た目の完璧さより閲覧可能性を優先する。これらはすべて、「まず届いて読めることを優先する」という初期の問題設定とつながっています。

この章ではまだ、ブラウザが具体的にどこまで補完するかまでは扱いません。その話を先取りすると第2部の重心が崩れるからです。ここでは、「なぜ HTML がそのような性格を持つ形式として選ばれたのか」までを押さえれば十分です。

3.5 実務では、形式の優劣ではなく問題設定との適合で考えたほうがよい

この章は歴史比較ですが、実務の判断にもかなり直結します。ある形式や技術を見るとき、「どれが高機能か」「どれが最新か」だけで比べると、用途とのずれを見落とします。

判断軸を表にすると、次のようになります。

形式強い対象優先するもの
PDF完成した配布物版面の固定、印刷、同一見た目
Word編集中の文書作成や修正のしやすさ
HTML公開される文書空間リンク、共有、環境差への強さ

たとえば、印刷用の完成資料なら PDF が自然な場面があります。共同編集が主目的ならワープロ文書や別の編集環境が向くこともあります。一方で、ブラウザで配信し、リンクでつなぎ、検索や支援技術にも読ませたいなら、HTML の役割はまだ非常に強い。つまり、重要なのは形式の上下ではなく、どの問題設定にいちばん合っているかです。

Rails アプリでも、この見方はそのまま使えます。HTML を返す画面、PDF を出力する帳票、CSV を返すエクスポートでは、それぞれ解いている問題が違います。たとえば申請一覧の画面は HTML が向いています。検索結果にリンクを張り、詳細画面へ移動し、ブラウザで読み直せるからです。逆に、押印前提の帳票を毎回同じ見た目で出したいなら PDF が自然です。HTML が選ばれるのは、単に慣れているからではなく、リンクや構造共有やブラウザ表示という条件に合っているからです。この判断軸を持てると、「なぜ最終的に HTML へ落とすのか」を説明しやすくなります。

3.6 問題設定に合っていた形式

Web が HTML を選んだのは、PDF や Word より「上等」だったからではありません。HTML が最もよく合っていたのは、リンク可能な文書を、環境差を越えて共有し続けるという問題設定でした。PDF は完成版面に強く、Word は編集に強い。しかし Web が最優先したのは、閉じた完成品ではなく、参照の網の中に置かれた文書でした。

HTML は見た目の厳密さを多少手放す代わりに、リンク、配信、環境差への強さを取りました。その単純さは、貧弱さの裏返しではなく、当時の条件への適合でした。この視点があると、後の章で出てくるブラウザの補完や互換性重視の設計も、かなり自然に見えてきます。

次章からは第2部に入り、そうして選ばれた HTML をブラウザがどこまで完成させているのかを見ます。ソースコードを書いた人だけで文書が完結しているわけではない、という話がそこから始まります。

参考資料

第1部 演習

  1. HTML を「プログラミング言語ではない」と言うとき、何を意味していて、何を意味していませんか。自分の言葉で説明してください。
  2. HTML が最初に解決したかった問題を、CERN の情報共有という文脈で 3 文以内にまとめてください。
  3. PDF や Word ではなく HTML が Web の中心になった理由を、「リンク可能性」と「環境差への強さ」の観点から比較してください。

第2部 ブラウザはなぜそこまで面倒を見るのか

第2部の役割は、HTML が「書かれた文字列のまま動く」のではなく、ブラウザによる補完と回復のうえで成立していることを示すことです。前の部で見た「HTML が文書共有のための技術だった」という前提を受けて、ここではブラウザ側の責任の重さを見ます。

この部では、html head body の補完、tbody の挿入、p 要素の暗黙の終了、パースエラーの扱い、そして View Source と DevTools の違いを扱います。仕様の細かい設計思想そのものは第3部で掘り下げるため、この部ではまず「何が起きるか」を中心に理解します。

第4章 ブラウザはHTMLを完成させる

この章では、HTML ソースがそのまま完成品ではなく、ブラウザが文書として成立する形へ組み立てた結果として DOM ができることを見ます。ゴールは、html head body を書かなかったのに DevTools には現れる、といった現象を「ブラウザの気まぐれ」ではなく、HTML の設計と仕様に基づく挙動として説明できるようになることです。

前章では、Web が必要としていたのは完成した版面より、環境差を越えて共有できる文書空間だったと見ました。この章では、そのような HTML をブラウザがどう受け取り、どこまで完成させるのかを扱います。次章では tbody という、より具体的で実務上も引っかかりやすい補完例へ進みます。

4.1 ソースコードと完成した文書の不一致

HTML を書いていると、つい「自分が書いた文字列がそのまま表示されている」と考えがちです。しかしブラウザが扱っているのは、受け取った文字列そのものではありません。ブラウザはその文字列を読み取り、規則に従って文書構造へ変換し、その結果として DOM を作ります。

この前提を外すと、あとで出てくる tbodyp の自動終了がすべて「謎の親切」に見えてしまいます。実際には、HTML は最初から、入力文字列を読みながら文書を組み立てる形式として設計されています。ソースは材料であり、ブラウザが扱う完成形そのものではありません。

ここでいう DOM は、ブラウザが内部で持つ文書構造です。英語では Document Object Model と呼ばれ、HTML を要素どうしの関係として扱うための形です。開発者ツールで見えているのは、受信した元の文字列ではなく、この構造化された結果です。つまり、HTML では「書いたもの」と「ブラウザが扱うもの」のあいだに、解釈の層が 1 枚入ります。 文字列が、そのままノードの木へ変換されているわけではなく、途中で「この要素は文書のどこに属するか」を判断する段階が入るのです。

4.2 titlep だけでも成立する文書外枠

最小の例で見てみます。

<title>sample</title>
<p>Hello</p>

このソースには、htmlheadbody も書かれていません。それでもブラウザは、これを壊れた断片として投げ捨てるのではなく、文書として読める形へ組み立てます。おおまかには、次のような構造として扱われます。

<html>
  <head>
    <title>sample</title>
  </head>
  <body>
    <p>Hello</p>
  </body>
</html>

ここで重要なのは、「ブラウザが親切で足してくれた」という理解で止めないことです。HTML では、title は文書メタデータ側、p は本文側に属します。ブラウザはその違いを踏まえて、どこに何を置くべきかを決めながら DOM を組み立てています。

木構造として言えば、titlehead の子に、pbody の子に置かなければ、文書として扱いにくくなります。ブラウザは単にタグを並べ替えているのではなく、文書モデルに沿う位置へ各要素を収めています。

つまり、入力が短いからといって、ブラウザ内部でも同じ短さのまま扱われるわけではありません。HTML ソースは断片的でも、ブラウザが必要とする文書構造は断片的なままでは済まないのです。

html/head/body を書いていないソースから、ブラウザがそれらを補完した DOM の木を組み立てる流れの図
図 4-1 ソースは材料。ブラウザが補って文書の木を組み立てる。

4.3 補完が文書の前提になる理由

この挙動を見ると、「ブラウザが開発者を甘やかしている」と言いたくなるかもしれません。たしかに、他のもっと厳格な形式に慣れていると、入力不足を埋めてくれる振る舞いは甘く見えます。

しかし HTML の文脈では、先にあったのは厳格さではなく、読めることを優先する問題設定でした。前章で見たように、Web が必要としていたのは、異なる環境にある人が同じ文書へ辿りつき、読めることです。その前提に立つと、文書の外枠が少し省略されていても、利用可能な文書として解釈するほうが自然です。

ここでのポイントは、「何でも好きに補ってよい」ではないことです。補完は仕様なしの裁量ではなく、どの要素がどこへ入るか、どの時点で文書の外枠を作るかといった規則に従って行われます。だからブラウザごとに気分で別々の木ができるのではなく、同じ HTML に対しておおむね同じ DOM を作れるのです。

この意味でブラウザは、著者の代わりに文章を書く共同著者ではありません。著者が渡した材料を、読める文書構造へ落とし込む実装です。過度に擬人化しないほうが、このあと出てくる仕様の話も理解しやすくなります。

4.4 DevTools が見ているもの

実務で混乱しやすいのは、ここからです。ソースに body を書いていないのに、DevTools を開くと body が見える。すると「ブラウザが勝手に書き換えた」と感じます。

ですが、DevTools が見せているのは、受信した元の文字列ではなく、解釈後の DOM です。つまり、見えている対象が最初から違います。元のソースと DevTools の内容が一致しないこと自体は、異常ではありません。むしろ HTML では、それが普通に起こります。

この違いを 1 度でも正しく掴むと、後の章でかなり楽になります。table の中に tbody が現れることも、閉じていない p が DOM 上では閉じていることも、「ブラウザが勝手に直した」の一言で片づけずに済むからです。見ているものが文字列なのか、補完後の文書構造なのかを分けて考えられるようになります。

手元で確かめる: 空のファイルに <title>sample</title><p>Hello</p> の 2 行だけを書いてブラウザで開き、DevTools の Elements パネルを見てください。書いていない html head body が現れ、titlehead の下、pbody の下に収まっているはずです。同じファイルを「ページのソースを表示(View Source)」で開くと、表示されるのは自分が書いた 2 行のままです。同じページでも、見ているものが違うことを 1 分で体験できます。

実務の調査でも、この切り分けは有効です。レスポンス本文を確認したいなら元の HTML を見るべきですし、CSS や JavaScript が相手にしている対象を確認したいなら DOM を見るべきです。同じ画面を見ていても、何を観察しているかで答えが変わります。

ここではまだ View Source と DevTools の違いを本格的には扱いません。その比較は第8章の役割です。この章ではまず、「ブラウザは受け取った文字列をそのまま見せているのではない」という土台だけ押さえれば十分です。

4.5 「ブラウザが勝手にやった」で終わる調査の危うさ

この章の話は、実務でもかなり役立ちます。Rails でテンプレートを書いていると、最終的にブラウザへ届くのは HTML 文字列です。そしてブラウザは、その文字列をそのまま画面へ貼り付けるのではなく、文書として解釈して DOM を組み立てます。

そのため、画面で起きたことを調べるときに、テンプレートの見た目だけで判断すると外しやすくなります。たとえば CSS セレクタが思ったように効かない、JavaScript で取れたノード構造が想定と違う、といった場面では、まず「ブラウザが最終的にどんな DOM を作ったか」を見る必要があります。

ここで重要なのは、ブラウザを責めることではありません。見るべき対象を切り分けることです。テンプレートの文字列を点検したいのか、補完後の DOM を点検したいのか。この区別ができるだけで、HTML まわりの調査はかなり整理されます。

4.6 ソースと文書構造のあいだ

ブラウザは HTML ソースをそのまま表示しているのではなく、文書として成立する形へ補完しながら DOM を作っています。html head body が省略されていても文書として読めるのは、その場しのぎの親切ではなく、HTML が最初から「読めること」を重視してきた形式だからです。

この章で大事なのは、ソースコードと完成した文書構造を同一視しないことです。HTML では、開発者が書いた文字列と、ブラウザが扱う文書のあいだに解釈の層があります。この見方を持つと、次章の tbody のような補完も、例外的な奇妙さではなく、同じ設計思想の延長として読めるようになります。

参考資料

第5章 tbody はなぜ生まれるのか

この章では、tbody が「ブラウザが気を利かせて足す飾り」ではなく、HTML の表モデルが最初から前提にしている本体側の階層であることを見ます。ゴールは、table > tr が効かない理由や、DevTools にだけ tbody が現れる理由を、単なる挙動の暗記ではなく、表の構造から説明できるようになることです。

前章では、ブラウザが html head body のような文書外枠を補いながら DOM を作ることを見ました。この章では、その補完が表の内部構造でどう現れるのかを扱います。次章では、同じ「内部は厳密・入力は寛容」という設計が p 要素の自動終了にどう現れるかを見ます。

5.1 表は tr の集まりではなく行グループの集まりである

表を書くとき、多くの人は「table の中に tr が並んでいる」と考えます。ソースコードの見た目だけを見ると、たしかにそう見えます。

しかし HTML の表モデルでは、table の直下に来る中心的な構造は行そのものではありません。theadtbodytfoot という行グループです。tr はその中に入る行であり、表の第一階層ではありません。

概念的には、表は次のような木構造を前提にしています。

table
├─ thead
│  └─ tr
├─ tbody
│  ├─ tr
│  └─ tr
└─ tfoot
   └─ tr

このとき tbody だけが特別扱いされているわけではありません。thead が見出し行のまとまり、tfoot が末尾側のまとまりなら、本体行にも対応するまとまりが必要です。その本体側のまとまりが tbody です。

短く言えば、thead は表の頭、tfoot は表の末尾、tbody は表の本体です。tbody だけが妙に増えるのではなく、もともと 3 種類ある行グループのうち、本体側が省略されやすいので目立っているだけです。つまり tbody は後から気まぐれに追加された要素ではなく、表を表らしく扱うための本体側の入れ物です。

5.2 tbody を書かなくても表の本体階層は立ち上がる

いちばん素朴な表を書いてみます。

<table>
  <tr><td>A</td></tr>
</table>

ソースには tbody がありません。ところが DevTools で見ると、たいてい次のような DOM になっています。

<table>
  <tbody>
    <tr><td>A</td></tr>
  </tbody>
</table>

ここで起きていることは、「本当は不要な要素をブラウザが親切で足した」ではありません。表の本体行は、表モデル上 tbody のような行グループの中に置かれる前提なので、その階層がソースに省略されていれば、ブラウザは DOM 側でその構造を立ち上げます。

逆に言えば、tbody が入るのはブラウザの気分ではなく、tr を表の本体として収める場所が必要だからです。見た目には 1 行しかなくても、表モデル上は「本体の 1 行」です。だから本体の入れ物も同時に必要になります。

tbody を書いていない表のソースから、ブラウザが table と tr のあいだに tbody を補完した DOM を作る流れの図
図 5-1 本体行は tbody の中。書かなくてもブラウザが立ち上げる。

前章とつながるのはここです。HTML は、著者が書いた文字列をそのまま画面に貼りつけているのではなく、文書モデルに沿った構造へ変換してから扱います。tbody の補完は、その典型例です。ソースの見た目とブラウザ内部の木構造が一致しないのは、例外ではなく表モデルの帰結です。

手元で確かめる: 上の <table><tr><td>A</td></tr></table> をそのまま書いてブラウザで開き、DevTools の Elements パネルで table を展開してください。書いていない tbodytabletr のあいだに現れているはずです。同じファイルを View Source で見ると tbody はありません。挿入はブラウザの気まぐれではなく、必ず起きることを目で確認できます。

5.3 実害は CSS セレクタで先に現れる

tbody が挿入されると聞いても、豆知識のように見えるかもしれません。ですが、CSS は DOM を相手にするので、すぐに実害として現れます。

たとえば次のように書くとします。

table > tr {
  background: #eee;
}

見た目だけなら、「table の直下にある tr に色を付けたい」と読めます。しかし DOM 上では tr の親は table ではなく tbody です。そのため、このセレクタは期待どおりには当たりません。

意図を DOM に合わせるなら、少なくとも次のどちらかになります。

table > tbody > tr {
  background: #eee;
}
table tr {
  background: #eee;
}

この違いが示しているのは、tbody が見た目だけの補助ではないことです。CSS が解釈している対象は、あなたのソースコードの見た目ではなく、ブラウザが構築したノードの関係です。だから tbody を理解していないと、表にだけセレクタが効かない、という不可解な症状に見えます。

5.4 JavaScript の API も表が階層構造であることを前提にしている

同じことは JavaScript でも起きます。table の子を直接たどれば tr が並んでいるはずだ、と思い込むと外します。CSS が「どのノード関係にスタイルを当てるか」でつまずくのに対して、JavaScript では「どの API で表を読むか」でつまずきます。ここでいう API は、プログラムからブラウザの機能へ触るための窓口だと思えば十分です。

const table = document.querySelector('table');

table.children;            // HTMLCollection [tbody]
table.children[0].tagName; // "TBODY"

ソースの見た目から受ける印象と、DOM API が返すものがずれるのは、ブラウザが DOM を表モデルに合わせて組み立てているからです。

一方で、表専用の API を使うと、この階層を意識せずに行へ辿れます。

const table = document.querySelector('table');

table.rows;            // すべての行
table.tBodies[0].rows; // 最初の tbody の行

ここで重要なのは、table.rows のような API が偶然あるわけではないことです。表が tbody を含む階層構造である以上、「行グループをまたいで行を集めたい」という需要が最初からあります。だから DOM API も、その構造を前提に設計されています。API の形そのものが、表は tr の平らな集合ではないと教えてくれます。

実務上の判断としては、表全体の行を扱いたいなら table.rows のような表専用 API を使い、どの行グループに属しているかまで区別したいなら tBodiesrows を組み合わせて辿る、と整理できます。DOM を木としてそのままたどるのか、表モデルを意識した API を使うのかを分けて考えると、コードの意図も整理しやすくなります。

5.5 「だったら最初から必須にすればよかったのではないか」

ここまで来ると、自然にこう思います。DOM では tbody が必要なのなら、ソースでも必ず書かせればよかったのではないか、と。

この疑問はもっともですが、HTML の考え方はそこでは厳格さを優先しませんでした。著者が毎回きれいに tbody まで書くとは限らない。それでもブラウザは、文書を読める形にしなければならない。そこで HTML は、入力としては省略を受け入れつつ、内部のモデルは厳密に保つ という折衷を選びました。

これは tbody だけの話ではありません。前章の html head body の補完もそうですし、次章で見る p 要素の自動終了も同じ方向にあります。HTML は「著者入力のゆらぎを受け止めながら、内部では整った構造を立てる」ことで Web を支えています。tbody はその設計思想が見えやすい場所です。

ここで誤解してほしくないのは、「では tbody は書かなくてよい」という雑な結論ではないことです。実務では、構造を明示したほうが読みやすい場面がありますし、見出し行や本体行のまとまりを区別したいなら、明示的に書いたほうが意図も伝わります。この章の主題は書き方の推奨ではなく、なぜ DOM に tbody が現れるのかという構造理解です。

5.6 行グループとしての表

tbody は、ブラウザが気を利かせて足す余計な要素ではありません。HTML の表が最初から行グループを前提にしていて、本体行を収める階層として必要だから、ソースに省略があっても DOM では立ち上がります。

この見方を持つと、table > tr が効かないこと、table.childrentr を返さないこと、table.rows という専用 API があることが 1 本につながります。どれも別々の小ネタではなく、「表は平らな行の集合ではない」という同じ事実の表れです。次章では、この「内部は厳密・入力は寛容」という性格が、p 要素の自動終了でどう見えるかを扱います。

参考資料

第6章 p タグはなぜ勝手に閉じるのか

この章では、p 要素の自動終了が「ブラウザの雑なごまかし」ではなく、壊れた入力から段落構造を救うための規則であることを見ます。ゴールは、<p> の中に div を入れたときに何が起きるかを、単なる挙動の暗記ではなく、「段落の中に置けないものが来たときにどこで区切るか」という構造の問題として説明できるようになることです。

前章では、tbody が内部モデルを保つために DOM 上で立ち上がることを見ました。この章では、同じ「内部は厳密・入力は寛容」という設計が、もっと身近な p 要素でどう現れるかを扱います。次章では個別の規則を離れて、HTML が壊れた入力全体をどう回復するのかへ進みます。

6.1 p は何でも包める箱ではない

p は見た目だけなら、ただの文章のまとまりに見えます。そのため、divsection のような他の要素も、中にそのまま入れられそうに感じるかもしれません。

しかし p は、何でも入る汎用コンテナではありません。p が表しているのは段落であり、1 つながりの文章として読まれる内容です。だから HTML では、段落の中に置けない要素が来たとき、そのまま入れ子にし続けるのではなく、どこかで段落を終わらせる必要があります。

ここで大事なのは、p の自動終了が「閉じタグを忘れても大丈夫」という甘い話ではないことです。先にあるのは「段落として成立する構造をどう保つか」という問題です。p は雑に広がる箱ではなく、段落という意味を持った要素だから、入れられないものが来た時点で境界を確定しなければなりません。

6.2 div が来たところで段落は閉じられる

いちばんよくある例を見ます。

<p>前置き
<div>本文</div>

ソースだけを見ると、divp の中に入っているように見えます。しかしブラウザが作る DOM は、その見た目どおりにはなりません。おおまかには次のように扱われます。

<p>前置き</p>
<div>本文</div>

つまり、div が現れたところで p は暗黙に閉じられます。div を段落の中に押し込んだまま読むのではなく、「ここで 1 つの文章のまとまりは終わっていたはずだ」と解釈し直しているわけです。

この規則を知らないと、「ソースと DOM が違う」「閉じタグを書いていないのに閉じている」という不可解な現象に見えます。しかし HTML から見ると、段落の中に置けない要素が来た以上、どこかで段落を終わらせないと文書構造の整合が取れません。そこで div の直前で p を閉じる、という規則が必要になります。

手元で確かめる: <p>前置き<div>本文</div> をそのまま書いてブラウザで開き、DevTools の Elements パネルを見てください。divp の子ではなく、p の外(兄弟)に並んでいるはずです。ソースでは入れ子に見えるのに、DOM では div の直前で p が閉じている——この食い違いを 1 度見ておくと、以降「閉じていないのに閉じている」現象に驚かなくなります。

6.3 自動終了は気分ではなく段落構造を守るための規則である

ここで誤解しやすいのは、「ブラウザがその場の雰囲気でいい感じに直している」という理解です。実際にはそうではありません。どの要素が p を閉じるかは、仕様の中で細かく決められています。

言い換えると、ブラウザは好き勝手に補っているのではなく、「この要素は段落の中に置けないので、ここで現在の p を終わらせる」という規則に従って処理しています。div が来たら必ずそうなるのは、偶然の実装ではなく、段落を段落として保つための決めごとだからです。

この視点を持つと、p の自動終了は tbody と同じ方向を向いていると分かります。tbody では表モデルを守るために本体階層を立ち上げ、p では段落モデルを守るために境界を確定する。どちらも、入力をそのまま信じるのではなく、内部の文書構造を整えているのです。

6.4 XML 的な厳格さとは違う方向を選んだ

この挙動は、厳格な文法処理に慣れていると不思議に見えます。もし XML 的な発想を強く持っていると、「入れられない要素が来たなら、その時点でエラーにして止めるべきではないか」と考えたくなります。

HTML はそこを別の方向に取りました。入力に問題があっても、できるかぎり読める文書構造へ回復するほうを優先します。だから divp の中に見えても、「不正だから中断する」ではなく、「段落はここで終わっていたと解釈する」に進みます。

これは HTML が甘いというより、Web が閲覧を止めないために選んだ方針です。古いページ、手書きのページ、完全ではない出力を含めて、とにかく読める形へ持っていく。その積み重ねの上に現在のブラウザ実装があります。この章では p だけを見ていますが、次章で扱うエラー回復全体の入口でもあります。

6.5 「閉じ忘れても平気」という意味ではない

p が勝手に閉じると聞くと、「では閉じタグを気にしなくてもいい」と受け取られがちです。これは実務でかなり危ない誤解です。

ブラウザが最終的に読める形へ回復してくれることと、著者が曖昧な入力を書いてよいことは別です。ソース上でどこまでが段落なのか分かりにくくなれば、テンプレートを読む人も保守する人も混乱します。しかも、意図と違う位置で p が閉じられると、CSS や JavaScript の対象範囲も想定からずれます。

たとえば、ある説明文全体を 1 つの段落だと思ってスタイルやスクリプトを書いていても、途中に置いた要素によってブラウザ側では段落が分断されているかもしれません。その状態で「なぜこの要素だけ段落の外に出ているのか」と悩み始めると、原因がソースではなく暗黙終了にあることに気づくまで時間を失います。

実務では、「ブラウザが回復してくれるから大丈夫」と考えるより、「なぜその回復が起きたのか」を理解して、曖昧なマークアップを減らすほうが重要です。この章の価値は、閉じ忘れを正当化することではなく、段落構造がどう守られているかを説明できるようになることにあります。

6.6 段落モデルを守る終了規則

p の自動終了は、ブラウザの雑なごまかしではありません。段落の中に置けない要素が現れたときに、どこで段落を終わらせれば文書構造を壊しすぎずに済むかを決めた規則です。

この見方を持つと、<p> の中に div を書いたときに DOM では段落が先に閉じている理由を、素直に説明できます。tbody が表モデルを守っていたのと同じように、p の暗黙終了は段落モデルを守っています。次章では、この個別規則の背後にある HTML 全体のエラー回復を、もう少し広い視点から見ます。

参考資料

第7章 壊れた HTML をどう扱うべきか

この章では、HTML が「エラーを出さない言語」なのではなく、「閲覧を止めないためにエラー回復を仕様化している言語」だと見直します。ゴールは、壊れた HTML がブラウザで何となく動く場面を見たときに、「エラーがない」のではなく「エラーはあるが、回復して読み続けている」と説明できるようになることです。

前章では、p 要素の暗黙終了という個別規則を見ました。この章ではそこから一段引いて、そうした規則を含む HTML 全体の回復方針を扱います。次章では、その結果として View Source と DevTools がなぜ違って見えるのかを扱います。

7.1 HTML は「エラーがない」のではなく「止まらない」方向を選んだ

HTML について、「多少壊れていても動く」「ブラウザはエラーを出さない」と言われることがあります。現象としては半分当たっていますが、説明としては雑です。

実際には、HTML にはパースエラーがあります。これは、ブラウザが HTML を読み解く途中で「仕様どおりではない入力だ」と判断する種類の問題です。タグの入れ子がおかしい、閉じタグが欠けている、置けない要素が置かれている。そうした入力は、仕様の観点では問題のある入力です。ただし HTML は、その問題が見つかった時点で閲覧を止めるのではなく、できるかぎり読める文書構造へ回復しながら処理を進めます。

つまり、HTML の特徴は「エラーが存在しない」ことではありません。エラーがあっても、利用者の閲覧を止めないことを優先した ところにあります。この違いを外すと、後の章で出てくる補完や DevTools の挙動が全部「適当に直している」ように見えてしまいます。

7.2 壊れた入力でもブラウザは読み進める

例として、段落の中に div を入れた前章のケースを思い出してください。

<p>前置き
<div>本文</div>

これは、文書構造として素直ではありません。それでもブラウザは処理を止めず、div の前で p を閉じる形へ回復して読み進めます。

同じことは tbody の補完でも起きています。

<table>
  <tr><td>A</td></tr>
</table>

ソースに tbody がなくても、ブラウザは表モデルに必要な階層を立てて DOM を作ります。ここで重要なのは、これらが別々の小技ではないことです。どちらも「入力は不完全でも、内部の文書構造はなるべく整えて処理を続ける」という同じ方針から出ています。

もう 1 つ、入れ子の崩れた例も見ておきます。

<ul>
  <li>項目 A
  <div>補足</div>
</ul>

この種の入力でも、ブラウザは「どこまでが li の内容か」「ul の子として何をぶら下げるか」を処理しながら、読み進められる形へ寄せていきます。ここで起きているのも、「不正だから停止する」ではなく、「いまのトークン列から、どの文書構造を組み立てるのがもっともましか」を選ぶ動きです。

見方を変えると、ここでブラウザがしているのは、著者の意図を推測して甘く採点することではありません。いま受け取っているトークン列を、既存のページをできるだけ壊さずに読める木構造へ落とし込むことです。第4章で見た補完も、第5章と第6章で見た挿入や暗黙終了も、この回復方針の具体的な現れとして並べて読むほうが実態に近いです。

HTML パーサーは、壊れた入力に出会うたびに「これはもう読めないので中断する」ではなく、「どの形に直せば、もっとも壊れにくく読み続けられるか」を選びます。ここでいうパーサーは、HTML の文字列を読んで文書構造へ変える読み取り器だと思えば十分です。Web が大量の既存ページを抱えたまま成り立つためには、この性質が必要でした。

7.3 XML のように停止しないのは Web の条件が違ったからである

ここで自然に出る疑問は、「不正な入力なら、その場でエラーにして止めたほうがきれいなのではないか」です。たしかに、厳格な形式ではその考え方が筋の通った場面があります。

しかし Web では、停止のコストが非常に高い。著者が 1 つタグを閉じ忘れただけで利用者がページ全体を読めなくなれば、公開文書空間としては脆すぎます。しかも現実の Web には、手書きのページ、古いツールが出力したページ、完全ではないテンプレートなどが大量に存在します。それらを全部「不正だから閲覧不可」としていたら、Web はここまで広がりませんでした。

だから HTML は、XML 的な厳格停止ではなく、回復しながら進む方向を選びました。これは「正しさを諦めた」というより、「公開された文書を読めるように保つ」という Web の責務を優先した結果です。第3章で見た「完成度よりも届いて読めることを優先する」という性格は、ここでも生きています。

7.4 エラー回復と「雑に書いてよい」はまったく別である

ここで最も危ない誤解を潰しておきます。ブラウザが回復してくれるからといって、壊れた HTML を気にしなくてよいわけではありません。

回復は、あくまで利用者の閲覧を守るための仕組みです。著者や開発者への免罪符ではありません。壊れた入力に依存すると、ブラウザが最終的にどう解釈したかを毎回追いかける必要があり、ソースの可読性も保守性も下がります。CSS や JavaScript の挙動が想定とずれたときに、原因が仕様どおりの回復にあるのか、単なる実装ミスにあるのかも見分けにくくなります。

第5章と第6章で見たように、tbody の挿入も p の暗黙終了も、最終的には DOM の形を変えます。つまり「壊れていても表示された」で済ませると、あとでスタイルやスクリプトの調査コストとして跳ね返ってきます。HTML が回復可能であることと、壊れた入力に寄りかかることは、はっきり分けて考える必要があります。

7.5 実務では validator と DevTools をどう使うか

では実務ではどう扱えばよいのでしょうか。基本は 2 つです。1 つは、HTML が回復することを前提にせず、まず入力自体を点検すること。もう 1 つは、すでに起きた現象については、ブラウザがどう回復したかを観察することです。

入力の点検には validator が向いています。validator は、HTML が仕様上おかしくないかを検査する道具です。たとえば Nu Html Checker のようなツールを使うと、仕様上問題のあるマークアップを機械的に拾えます。これは「ブラウザが表示できるか」ではなく、「仕様上どう問題があるか」を見る道具です。

たとえば、閉じタグの抜けや不適切な入れ子があったとき、validator は「この要素はここに置けない」「この終了タグは不要である」「この開始タグに対応する終了タグがない」といった種類の問題を指摘します。そこで初めて、「ブラウザでは見えているが、入力は壊れている」という状態を、感覚ではなく仕様の言葉で捉えられます。表示結果だけを見ていると正常に見えるページでも、入力としては修正すべき箇所があると切り分けられるわけです。

一方で、いま画面に何が起きているかを調べるには DevTools が向いています。なぜなら、ブラウザが実際に扱っているのは回復後の DOM だからです。つまり、validator は入力の問題を見つけるため、DevTools は回復後の現実を観察するために使います。両者の役割は重なっていません。

この切り分けができると、「壊れていても動いたから問題ない」という雑な判断を避けやすくなります。仕様上まずいのか、ブラウザがどう回復したのか、その結果 DOM がどうなったのかを分けて考えられるからです。

HTML はエラーを無視しているのではありません。壊れた入力に対しても、閲覧を止めないために回復しながら処理を続けるよう設計されています。この見方を持つと、tbody の補完や p の暗黙終了は、気まぐれな例外ではなく、同じ回復方針の一部として読めます。次章では、その回復後の現実をどこで見ているかという観点から、View Source と DevTools がなぜ一致しないのかを見ます。

参考資料

第8章 View Source と DevTools はなぜ違うのか

この章では、View Source と DevTools が同じ HTML を別の形で見せているのではなく、最初から別の対象を見せているのだと整理します。ゴールは、ソースと DOM が食い違って見えたときに、「どちらが正しいか」と迷うのではなく、「どの段階の結果を見ているのか」を切り分けて説明できるようになることです。

前章では、HTML が壊れた入力に出会っても、閲覧を止めずに回復しながら読み進めることを見ました。この章では、その回復の前と後を、私たちがどこで観察しているのかを扱います。次の第3部では、こうした差を生む HTML 自体の設計思想へ進みます。

8.1 同じ文書でも観察している層が違う

View Source が見せるのは、ネットワークから受け取った元の HTML 文字列です。いわば、著者やサーバーがブラウザへ渡した入力そのものです。

一方で DevTools の Elements パネルが見せるのは、ブラウザがその入力をパースし、必要な補完や回復を行ったあとに扱っている DOM です。Elements パネルは、ブラウザがいま相手にしている要素の木を表示する画面だと思えば十分です。ここで見えているのは、文字列そのものではなく、ブラウザ内部で組み立てられた文書構造です。

この 2 つは、同じページに由来していても観察対象が違います。だから一致しないこと自体は異常ではありません。むしろ、第4章から第7章までで見てきた補完や暗黙終了や回復がある以上、違いが見えるほうが自然です。

8.2 tbodyp が差を目に見える形へ変える

もっとも分かりやすいのは、第5章と第6章で扱った例です。

<table>
  <tr><td>A</td></tr>
</table>
<p>前置き
<div>本文</div>

View Source では、この入力はほぼそのまま見えます。tbody は書かれておらず、p も閉じられていません。

しかし DevTools では違います。表には tbody が立ち上がり、div の手前で p が閉じられた形の DOM が見えます。ここで起きているのは、ブラウザが勝手に別の文書を作っていることではありません。元の入力を、表モデルや段落構造を保ったまま扱える形へ変換した結果が、DOM として現れているのです。

この差を知らないと、「ソースを書き換えられた」「DevTools が嘘を表示している」といった誤解が起きます。実際には、View Source は入力を、DevTools は解釈結果を見せています。両者の不一致は、ブラウザが不安定だからではなく、役割が違うから起きます。

8.3 View Source は著者の入力を調べる道具である

では、View Source はいつ使うのでしょうか。役割は明快です。著者が何を書いたのか、サーバーが何を返したのか、元の入力を確認したいときに使います。

たとえば、テンプレートエンジンがどんな HTML を出力したのか、レスポンスに含まれていた属性や要素は何か、整形前の改行やコメントがどう入っていたのか、といったことは View Source のほうが向いています。これは「ブラウザがどう理解したか」ではなく、「そもそも何が渡されたか」を見るための道具です。

ここで 1 つ区別しておきたいのは、View Source が見せるのは ERB や JSX のようなテンプレート記述そのものではない、ということです。見えているのは、それらが評価されたあとにサーバーやビルド結果から渡された HTML です。Rails アプリで調べものをするときも、app/views のテンプレートと View Source と DevTools は、それぞれ別の段階を見ています。

第7章で触れた validator との相性がよいのもこちらです。validator が検査するのは入力としての HTML なので、確認したい対象は回復前の文字列です。著者の入力に問題があるのかを詰めるなら、まず見るべきなのは View Source 側です。

8.4 DevTools はブラウザの現実を調べる道具である

一方で、CSS が効かない、JavaScript のセレクタが当たらない、思っていた場所に要素がない、といった実務上の問題を調べるときは DevTools が必要です。なぜなら、ブラウザが実際に描画し、スクリプトから参照しているのは DOM だからです。

たとえば table > tr が当たらない理由は、ソースに tbody がないからではなく、DOM では tr の親が tbody だからです。p の途中までを 1 つの段落だと思っていたのにスタイルの適用範囲がずれるのも、DOM 上では途中で暗黙終了しているからです。こうした問題は、入力を見ても最後までは分かりません。ブラウザが最終的にどんな構造を扱っているかを見ないと解けません。

さらに、現代のページでは JavaScript が DOM を書き換えることも珍しくありません。すると DevTools に見えているのは、パースと回復の結果だけでなく、スクリプト実行後の状態でもあります。View Source は最初に受け取った HTML を見せ続けますが、DevTools は「いまブラウザが相手にしている文書構造」を見せます。この違いを押さえると、「ソースにはない要素が見える」「属性値が違って見える」といった現象も整理しやすくなります。

ここで大切なのは、DevTools が「より正しい」わけではないことです。DevTools が見せているのは、ブラウザにとっての現実です。著者の入力を検証したいのか、ブラウザの現実を調べたいのかで、使う道具が変わります。

8.5 「どちらを見るべきか」は問いで決まる

実務で混乱しやすいのは、ソースと DOM を同じものだと思って調査を始めることです。そうすると、「ソースにはあるのに見つからない」「ソースにはないのに DOM にはある」という現象に毎回ひっかかります。

判断基準は単純です。何が送られてきたのか を知りたいなら View Source、ブラウザはいま何を相手にしているのか を知りたいなら DevTools を見る。この切り分けができると、第2部で見てきた多くの現象が、単なるブラウザの癖ではなく、観察層の違いとして整理できます。

ここまでで、HTML ではソースと完成形が一致しないことが珍しくないと分かりました。次の第3部では、その差がどんな設計思想から生まれているのかを、空要素やコメントや属性の省略といった個別の論点から見ていきます。

参考資料

第2部 演習

  1. View Source と DevTools が違う情報を見せる理由を、tbodyp 要素を例に説明してください。
  2. HTML パーサーがエラー時に停止しない設計には、どんな利点と欠点がありますか。
  3. html head body の補完を、ブラウザの親切さではなく仕様設計として説明してください。

第3部 HTMLの設計思想

第3部の役割は、第2部で見たブラウザの挙動を、個別の仕様設計として読み解くことです。ここでは「空要素」「コメント」「属性値の省略」「仕様書の読者」という、地味ですが HTML の思想がよく表れる題材を選びます。

前の部との違いは、補完や回復の現象を見るだけでなく、その文法や文書設計の理由に踏み込む点です。次の第4部では、HTML が理想と現実のあいだでどのように変わってきたかを扱うため、この部はその前提となる「仕様そのものの考え方」を担います。

第9章 img はなぜ閉じタグを持たないのか

この章では、img に閉じタグがないのは書き忘れを許しているからではなく、最初から子を持たない要素として設計されているからだと見ます。ゴールは、<img> を見たときに「終わりが省略されている」のではなく、「内容を包む種類の要素ではない」と説明できるようになることです。

前章では、ソースと DOM が違って見えるのは、ブラウザがどの段階の結果を見せているかが違うからだと整理しました。この章ではそこから一歩進めて、その違いを生む HTML の文法そのものへ目を向けます。次章では、もっと目立たない存在であるコメントにも仕様上の制約があることを見ます。

9.1 img は内容を包む要素ではない

pdiv を見ると、開始タグと終了タグのあいだに内容が入るのが HTML の基本形に見えます。その感覚のまま img を見ると、「なぜここだけ閉じタグがないのか」と不思議に見えます。

しかし img は、文章や子要素を内側に抱える要素ではありません。文書の中に画像という外部資源を埋め込む場所を示す要素です。必要なのは、どの画像を参照するか、代替テキストをどう与えるかといった属性であって、開始タグと終了タグのあいだに入る本文ではありません。

ここで重要なのは、img が「中身を書かなくてもよい要素」なのではないことです。最初から子を持てない要素として定義されているので、閉じタグが省略されているのではなく、そもそも持たないのです。

9.2 空要素という区別

HTML には、img のほかにも br hr meta link input のように、子を持たない要素があります。これらは空要素として扱われます。

<p>前置き<br>補足</p>
<img src="photo.jpg" alt="港の写真">

この例で br は改行位置を、img は画像の埋め込み位置を表しています。どちらも、あいだに文章や別要素を抱えて意味を作る要素ではありません。だから </br></img> のような終わり方を期待するより先に、「この要素は内容を囲む型なのか、位置だけを示す型なのか」を見分ける必要があります。

第1章で、HTML は処理を書く言語ではなく文書構造を記述する言語だと見ました。その観点から読むと、空要素は「ここに何かがある」という構造上の印を置く要素です。文を開いて閉じる箱ではなく、文書の中に特定の役割を持つ点を打つ要素だと考えたほうが実態に近いです。

ここで見えてくるのは、HTML が「タグごとに見た目の書き方が違う言語」なのではなく、「要素ごとに持てる内容を分類している言語」だということです。閉じタグの有無は、その分類の結果として表に出ているにすぎません。

9.3 <img /> は HTML では何を意味するのか

ここでよく混乱するのが、<img /> という書き方です。XML や XHTML に慣れていると、自己終了記法に見えます。そのため、「HTML でも末尾の / が要素を閉じている」と理解したくなります。

しかし HTML では、本質はそこではありません。img が閉じタグを持たないのは、末尾の / があるからではなく、img 自体が空要素だからです。つまり img の終わりを決めているのは見た目の記号ではなく、要素の定義です。

この違いを見失うと、「では <div /> も同じように閉じられるのか」と考えてしまいます。HTML ではそうはなりません。

<div />
<p>本文</p>

これを「div がここで閉じた」と読むと分かりやすそうですが、HTML ではそうした自己終了にはなりません。div は空要素ではないので、/ が付いていても、通常要素として扱われます。子を持つ通常要素と、最初から子を持てない空要素は、見た目が少し似ていても文法上は別物です。/ が魔法の閉じ記号なのではなく、空要素にたまたま付いていても害が出にくいだけだ、と理解したほうが正確です。

補足: そもそも img という要素は、1993 年に Mosaic ブラウザの開発者マーク・アンドリーセン(Marc Andreessen)が当時の議論の場(www-talk メーリングリスト)で提案したものです。画像を別ウィンドウではなく文書の中へ直接埋め込む案で、<icon> という別名や、もっと一般的な仕組みを推す声もありました。結局、いちばん手軽な img が広まって今も残っています。最初の設計が「最良」だったからではなく、現実に広く使われたものが残る——という、いかにも Web らしい決まり方の一例です。

もう 1 つ: 「<div />/ は無視される」と書きましたが、これには例外があります。HTML の中に埋め込んだ SVG や MathML(外来要素) の中では、<rect /> のような自己終了が本当に効きます。これらは XML 由来の文法を持つためです。つまり / が無意味なのは「HTML の通常要素では」という条件付きで、同じ 1 文字が、文脈によって効いたり効かなかったりします。

9.4 終了タグがないことは「ゆるさ」ではない

img に閉じタグがないと聞くと、HTML のゆるさの例に見えがちです。しかし実際には逆です。何でもありだから閉じタグがないのではなく、子を持たない要素を最初から区別しているから、ここでは閉じタグが不要になります。

この視点は、第2部で見てきた HTML の挙動にもつながります。HTML は入力に寛容な場面がある一方で、内部では要素ごとの役割や置ける内容をかなりはっきり区別しています。img が閉じタグを持たないのも、その区別の一部です。ゆるい書式の偶然ではなく、コンテンツモデルを持つ文法の結果として読むべきです。

実務でも、この理解は無駄ではありません。たとえばテンプレートを読んでいるときに、imgpdiv と同じ感覚で眺めると、「なぜここは閉じていないのか」という枝葉に引っ張られます。先に「これは内容を包む要素ではない」と分かっていれば、見るべき関心は閉じ方ではなく、srcalt など、その要素に本当に必要な情報へ向きます。

ここまでで、閉じタグの有無は書き方の癖ではなく、要素がどんな内容を持てるかという設計の結果だと分かりました。次章では、その視点をさらに地味な題材へ移し、コメントでさえ好き勝手に書けるわけではないことを見ます。

参考資料

第10章 コメントにも仕様がある

この章では、HTML コメントが「ブラウザが読まない自由欄」ではなく、どこで始まりどこで終わるかを文法で決められた構文だと見ます。ゴールは、<!-- ... --> を単なるメモの囲みとしてではなく、パーサーがきちんと解釈しなければならない入力として説明できるようになることです。

前章では、img に閉じタグがないのは空要素という分類の結果だと見ました。この章では、もっと地味なコメントを題材にしても、HTML が見た目以上に文法を持っていることを確かめます。次章では、その文法意識が属性値の省略にどう現れるかを見ます。

10.1 コメントは無制限のメモ欄ではない

HTML コメントは <!-- で始まり --> で終わります。見た目だけを追うと、そのあいだは何を書いても無視される、ただのメモ欄に見えます。

しかしパーサーの立場では、話はそれほど気楽ではありません。どこからどこまでがコメントなのかを判断できなければ、その後ろに続く要素やテキストを正しく読み取れないからです。コメントもまた、HTML の入力の一部として処理される構文です。

ここで重要なのは、「表示されない」ことと「文法を持たない」ことは別だという点です。画面に出ないからといって、好き勝手に壊してよい領域にはなりません。コメントの境界が曖昧になれば、文書全体の解釈まで崩れます。

10.2 終端と衝突する並び

この性質は、コメントの中で使える文字列に制約があることを見ると分かりやすいです。

<!-- ここは通常のコメント -->
<!-- ここで -- を多用すると? -->

コメントは --> で終わるので、内部で -- のような並びをどう扱うかは、最初から無関心ではいられません。コメントの中身がどこで終端と衝突しうるかを決めておかないと、パーサーは「まだコメントの途中なのか」「ここで終わったのか」を安定して判断できません。

たとえば、開発中に要素を一時的に無効化したつもりで、長い HTML 断片を雑にコメントへ押し込む場面を想像してください。書き手は「どうせ表示されない」と思っていても、パーサーは依然として <!----> の境界を追い続けています。だからコメント内部の文字列しだいでは、「どこまでが無効化されたのか」を人間と同じ感覚では読んでくれません。

つまり HTML コメントは、「中に何でも流し込める箱」ではなく、「終端と衝突しないように扱う必要がある構文」です。見た目には目立ちませんが、ここでも HTML は文字列の境界をかなり真面目に扱っています。

余談: かつてコメントは、ただの無視欄どころか分岐の道具として使われていました。<!--[if IE]> ... <![endif]--> という書き方(条件付きコメント)で、「Internet Explorer のときだけ読み込むスタイルシート」などを切り替えていたのです。他のブラウザにはただのコメントに見えるのに、IE だけは中身を解釈しました。コメントという最も地味な構文が、ブラウザ差を吸収する抜け道になっていた——これは IE 全盛期を象徴する雑学です(IE10 以降は廃止されました)。

10.3 SGML の名残がいまも文法に影を落とす

では、なぜコメントにこうした細かな制約があるのでしょうか。理由の 1 つは、HTML が SGML の影響を受けて出発したからです。SGML は、文書の構造をどう記述するかを決める、HTML より前の世代の大きなマークアップの枠組みだと考えれば十分です。

初期の HTML は、いまの Living Standard だけで完結して生まれたわけではありません。文書構造を記述する仕組みとして、SGML の考え方を引き継いでいました。コメントの扱いにも、その時代の名残が残っています。現在の HTML は独自に整理され直されていますが、コメントを完全な自由欄にしなかった背景には、そうした歴史があります。

ここで大切なのは、「古い名残だから変だ」と切ってしまわないことです。むしろ、文書構造を壊さずに読み続けるためには、コメントのような脇役にさえ境界の規則が必要だった、と読むほうがこの本の筋に合います。前章の空要素と同じで、見た目が素朴でも、その裏には分類や制約があります。

10.4 実務ではコメントを文法の外に置かない

実務では、コメントを「どうせ表示されない領域」と見なして複雑な断片を詰め込みたくなることがあります。とくにテンプレートの途中で一時的に要素を消したり、長い説明を埋め込んだりすると、コメントは安全な退避場所に見えます。

しかし、ここまで見てきたように、コメントは文法の外側にあるわけではありません。HTML の中で処理される構文の 1 つです。だから、コメント内部の書き方しだいでは、パーサーや validator が気にする対象になります。画面がたまたま崩れなくても、入力としては parse error を含んでいることがあります。

この章で覚えるべきなのは、「コメントの細則一覧」ではありません。HTML は、見出しや段落や画像のような目立つ要素だけでなく、コメントのような地味な場所にも境界規則を持っている、という見方です。そう読むと、HTML は雑に許している言語ではなく、許すところと許さないところを選んで設計されている言語だと分かります。

ここまでで、表示されないコメントでさえ文法の一部だと分かりました。次章では、その延長として、属性値を省略できる場面があるのも無秩序な近道ではなく、条件つきの設計だということを見ます。

参考資料

第11章 属性値はなぜ省略できるのか

この章では、HTML の属性値省略が「雑でも通るから」ではなく、属性の種類と文脈に応じて条件つきで許された設計だと見ます。ゴールは、disabledchecked のような書き方を見たときに、「短く書ける便利な癖」と受け取るのではなく、「何が省略され、何が省略されていないのか」を区別して説明できるようになることです。

前章では、コメントのような地味な構文にも境界規則があることを見ました。この章では逆に、HTML がどこを意図的に省略可能にしているかを扱います。次章では、こうした細かな規則を含む HTML 仕様書が誰のために書かれているのかへ進みます。

11.1 省略できる属性と、できない属性は同じではない

HTML の属性を見ると、すべてが name="value" の形で厳密に並んでいるように見えます。しかし実際には、属性にはいくつか種類があります。その違いが、省略の可否にそのまま現れます。

もっとも分かりやすいのはブール属性です。

<input disabled>
<input disabled="disabled">
<input checked>

disabledchecked では、問われているのは「どんな値か」よりも「その状態があるかどうか」です。ブール属性では、属性が存在すること自体が true を表します。だから属性名だけで意味が成立します。ここで省略されているのは属性そのものではなく、値を書き下す形です。

ここに有名な落とし穴があります。disabled="false" と書いても、要素は無効化されたままです。 ブール属性では「存在するかどうか」だけが意味を持つので、false という値を入れても「属性が存在する」事実は変わらないからです。無効化をやめたいなら、属性ごと取り除くしかありません。値で真偽を切り替える、という直感がここでは通用しないわけです。

一方で、srchref のように、何を指すかが値そのものに依存する属性はそうはいきません。<img src> だけでは、どの画像を参照するのか決まりません。つまり、HTML は何でも短くしてよいのではなく、意味が保てる場面だけを選んで省略可能にしています。

11.2 引用符の省略にもかなり狭い条件がある

省略という話で、もう 1 つよく挙がるのが引用符です。HTML では、属性値のまわりの "' を省略できる場面があります。

<input type=text>
<a href=/about>

ただし、ここでも「いつでも省ける」わけではありません。空白や特定の記号を含むと、値の境界が分からなくなります。つまり引用符の省略は、HTML が雑に許している近道ではなく、「この文字列なら境界を見失わない」という条件つきの短縮記法です。

たとえば、次のような値では同じ感覚では書けません。

<a title=会社概要ページ>

この場合、空白を含む時点で値の切れ目が曖昧になります。人間には 1 つの題名に見えても、パーサーにとってはそうではありません。だから引用符が必要になります。

この条件を外してしまうと、第10章で見たコメントの境界規則と同じ問題が起きます。パーサーが「どこまでが値なのか」を安定して判断できなければ、後ろに続く属性や要素の解釈まで崩れます。ここでも HTML が守っているのは、見た目の簡便さより先に、境界を読み取れることです。

11.3 書きやすさを残しながら、境界は壊さない

では、なぜ HTML はこうした省略を残したのでしょうか。背景には、HTML が長く手書きの文書として使われてきた事情があります。毎回すべてを冗長に書かなくても済むようにして、著者の負担を減らしたい。その意図はたしかにあります。

その出自も関係しています。HTML はもともと SGML(1986 年に ISO 規格になった、文書をマークアップするための言語)をベースに作られました。タグや引用符を省略できる仕組みの多くは、この SGML から受け継いだものです。つまり HTML の省略可能性は、その場の思いつきではなく、文書記述言語の系譜を引いた性質でした。

しかし同時に、HTML は好き勝手な省略を許してはいません。ブール属性にはブール属性の、省引用には省引用の条件があります。つまり HTML がしているのは、「短く書けるようにすること」そのものではなく、「意味と境界を壊さない範囲で短く書けるようにすること」です。

この見方を持つと、第9章と第10章とのつながりも見えます。空要素では、要素が持てる内容を分類していました。コメントでは、終端と衝突しないよう境界を守っていました。属性値の省略でも同じで、先にあるのは文法上の条件です。省略可能性は、その条件の内側でだけ成立しています。

11.4 実務では「省略可能」と「省略すべき」を分ける

実務で重要なのは、仕様上省略できることと、普段のコードで省略したほうがよいことを分けることです。たとえば formatter やチーム規約が常に引用符を付けるなら、それは仕様に反しているのではなく、読みやすさと保守性を優先しているだけです。

同じことはブール属性にも言えます。disabled とだけ書いてもよいし、テンプレートや生成規則の都合で別の書き方が出てくることもあります。そこで大事なのは、表記ゆれそのものより、「なぜこの属性では値を省略できるのか」「なぜこの属性ではできないのか」を説明できることです。

この章で言いたいのは、「引用符はいつでも省ける」「HTML は適当でも通る」といった雑な印象の逆です。HTML は著者の負担を減らすための近道を用意しつつ、その近道が文法の条件の内側に収まるよう設計しています。次章では、こうした規則を細かく書き連ねている HTML 仕様書が、そもそも誰のための文書なのかを見ます。

参考資料

第12章 HTML 仕様書は誰のためにあるのか

この章では、HTML 仕様書を「著者向けの正しい書き方集」とだけ見るのではなく、ブラウザ実装者、著者、標準化に関わる人たちがそれぞれ別の目的で読む文書だと整理します。ゴールは、HTML Living Standard が長く細かい理由を、「説明が下手だから」ではなく、「複数の読者に対して異なる役割を背負っているから」と説明できるようになることです。

前章では、属性値の省略にも条件つきの文法があることを見ました。この章では、そのような細かな規則がなぜ仕様書へ書き込まれているのかを扱います。次の第4部では、その仕様と現実が歴史の中でどう折り合ってきたのかへ進みます。

12.1 仕様書の中心読者はブラウザ実装者である

HTML 仕様書を初めて開くと、多くの人はまず長さに驚きます。要素一覧や属性一覧だけなら、あそこまで巨大になる必要はなさそうに見えるからです。実際、1 ページにまとめた版はブラウザで開くだけでも重く感じるほどの分量で、読みやすさのために章ごとに分割した複数ページ版がわざわざ別に用意されているほどです。

しかし仕様書の中心には、著者への助言だけでなく、ブラウザが同じ入力をどう処理するかをそろえるための規則があります。パーサーがどのトークンをどう読むか、壊れた入力をどう回復するか、どの DOM を組み立てるか。第2部で見てきた細かな挙動の多くは、まさにそのために書かれています。

たとえば、tbody をいつ立ち上げるのか、p をどこで暗黙に閉じるのか、コメントや属性値の境界をどこで切るのかは、どれも「雰囲気でだいたい同じ」にして済む話ではありません。1 文字ぶん解釈がずれるだけで、DOM も CSS も JavaScript もずれていきます。だから仕様書は、そうした細部を実装者どうしでそろえるために長くなります。

つまり HTML 仕様書は、「人間が HTML を学ぶための本」より先に、「実装がばらつかないようにするための規約書」です。長いのは、話が回りくどいからではなく、ブラウザ同士で結果をそろえるために細部まで決める必要があるからです。

12.2 著者にとっての仕様書は最終根拠である

では、著者にとって仕様書は不要なのでしょうか。そうではありません。ただし、使いどころが違います。

著者が日常的に読む入口としては、MDN のような整理された解説のほうが向いています。どの要素をいつ使うか、どういう属性があるか、まずはそちらのほうが読みやすいからです。仕様書は最初から学習教材として最適化されているわけではありません。

それでも仕様書が重要なのは、通説やブログ記事が食い違ったときに、最後の根拠へ戻れるからです。h1 は 1 個だけなのか、tbody はなぜ DOM に現れるのか、コメントや属性の省略はどこまで許されるのか。そうした問いに対して、「誰かがそう言っていた」ではなく、一次情報へ戻るための場所が仕様書です。

たとえば、要素の基本的な用途を知りたいだけなら MDN で十分なことが多い。MDN は、Web 技術を開発者向けに整理して解説している資料集だと思えば十分です。一方で、「この終了タグは本当に省略できるのか」「この入力でパーサーはどの DOM を作るのか」といった境界の話になると、最終的には仕様書の定義へ戻る必要があります。入口と根拠を分けて考えるほうが、仕様書との付き合い方として現実的です。

この意味で、著者にとっての仕様書は毎日通読する本ではなく、判断が割れたときに戻る基準点だと言えます。

12.3 標準化する側にとっての仕様書は合意の文書である

仕様書には、実装者向けの規則と著者向けの根拠だけでなく、標準化の合意を残す役割もあります。どの要素をどう定義するか、どこまで後方互換性を守るか、何を obsolete と見なすか。そうした判断は、単なる豆知識ではなく、Web 全体の振る舞いを左右します。

ここで仕様書は、「理想的な文法を書く紙」では終わりません。すでに広く使われている実装や既存ページとの整合も背負います。だから仕様書は、美しい理論だけでなく、現実の Web を壊さないための条件まで書き込んでいきます。HTML 仕様書が大きくなりがちなのは、そのためでもあります。

この視点を持つと、第2部で見たエラー回復や、第3部で見てきた細かな文法が、単なる技術仕様ではなく「実装と互換性の合意」でもあると分かります。仕様書は、ブラウザと著者と既存の Web のあいだで、どこまでを守るかを書いた文書でもあるのです。

12.4 「読みにくい仕様書」には役割の違いが混ざっている

HTML 仕様書が読みにくく感じられるのは自然です。1 つの文書に、実装規則、著者向けの定義、標準化の判断材料が同居しているからです。読み手が自分の目的を決めずに開くと、必要な部分より先に大量の細則へぶつかります。

だから実務では、最初から仕様書だけで学ぼうとしないほうがよい。日常の理解には整理された解説を使い、判断が割れたら仕様書へ戻る。仕様書を読むときは、「自分はいま著者として確認したいのか、実装の根拠を知りたいのか」を意識する。そのほうが、仕様書の長さに飲まれにくくなります。

ここまでで、HTML 仕様書は誰か 1 種類の読者だけのためにあるのではなく、複数の立場を同時に相手にする文書だと分かりました。次の第4部では、その仕様が理想だけでは進めず、既存の Web とどう折り合ってきたのかを、消えたタグや XHTML の挫折から見ていきます。

参考資料

第3部 演習

  1. 空要素とは何かを、img を例に 2 つの観点から説明してください。
  2. 属性値の省略可能性は、なぜ「いつでも短く書いてよい」という意味ではありませんか。
  3. HTML 仕様書が実装者向けの性格を強く持つ理由を、ブラウザ間互換性と結びつけて説明してください。

第4部 理想と現実のあいだ

第4部の役割は、HTML の歴史を「きれいな進化」ではなく、現実との折衝として捉えることです。ここでは消えたタグ、XHTML、互換性、残り続けるバグを通して、Web がどれだけ壊せない基盤になっているかを見ます。

第3部で見た設計思想は、現実の Web ではいつもそのまま通るわけではありません。そこでこの部では、理想が押し切れなかった例を集めます。次の第5部では HTML を巡る議論を扱うため、この部は「単純な善悪で語れない」という感覚を育てる位置づけです。

第13章 消えたタグたちは何を残したのか

この章では、blink marquee center font のような消えた要素を、単なる黒歴史として笑うのではなく、当時の Web が何を欲していて、標準が何を学んだのかの痕跡として見ます。ゴールは、obsolete になった要素を見たときに、「昔は雑だった」で終わらせず、「どんな需要に応え、どんな代償を残したのか」を説明できるようになることです。

前章では、仕様書が実装者や著者や標準化側の合意を背負う文書だと見ました。この章では、その合意がまだ固まりきっていなかった時代の試行錯誤へ進みます。次章では、その逆側にある「理想を厳密に貫こうとした XHTML」が、なぜ広がりきらなかったのかを見ます。

13.1 fontcenter は著者の即時需要に応えた

いまの感覚で見ると、fontcenter は「見た目を HTML に埋め込んだ悪い例」に見えます。たしかに、文書構造と見た目の分離という観点からは後退でした。

しかし当時の著者にとって重要だったのは、理念より先に「文字を大きくしたい」「中央寄せしたい」をすぐ実現できることでした。CSS がまだ十分に普及していない時代に、見た目を制御する需要だけが先に消えるわけではありません。fontcenter は、その即時需要にまっすぐ応えた要素でした。

当時は、見た目を分離する理想よりも、ページをいま見栄えよくしたい圧力のほうが直接的でした。しかも、著者ごとに別々の回避策へ流れるくらいなら、要素として用意されている近道のほうが使われやすい。fontcenter は、そうした現場の圧力を吸収する役目も果たしていました。

ここで見えてくるのは、要素がまずかったというだけではありません。標準が、著者の需要に対して十分な手段をまだ提供し切れていなかった、という事情です。だからこそ、見た目を直接いじる近道が広まりました。

blinkmarquee は、さらに分かりやすい例です。文字を点滅させたい、流したい。その要求自体は、いま見ると派手で落ち着きがないかもしれませんが、当時の Web では「目立たせたい」という切実な需要でもありました。

<blink>新着情報</blink>
<marquee>セール開催中</marquee>

問題は、こうした要素が文書の意味を深めるより先に、表示効果そのものを要素化してしまったことです。しかも blinkmarquee は、標準化された文書構造の一部というより、ブラウザや実装都合の強い拡張として広まりました。ここでは「需要があったこと」と「その解決が長持ちする設計だったこと」は別です。

それでも重要なのは、こうした要素を笑って終わらないことです。標準の外で広まる拡張は、「そんな需要はない」の証拠ではなく、「標準がまだ受け止めきれていない需要がある」の証拠でもあります。

13.3 消えた要素が残したのは、需要を無視しないという教訓である

消えたタグたちが残した教訓は 2 つあります。1 つは、見た目や効果をそのまま要素へ閉じ込めると、文書構造が濁り、長期的な保守や再利用が難しくなること。もう 1 つは、著者の需要を「低レベルだから」と切り捨てても、その需要自体は消えず、独自拡張や回避策として別の場所から噴き出すことです。

この 2 つを同時に見ないと、歴史を後知恵で裁いてしまいます。fontcenter を deprecated にする判断は筋が通っていますが、それは「最初から不要だった」ことを意味しません。むしろ、「その需要をもっと持続可能な形で受け止める必要があった」と読むほうが、現在の標準化にもつながります。

この意味で、消えた要素は失敗の残骸というより、標準がどこで著者の需要と衝突したかを示す痕跡です。

13.4 古い要素を笑わないことが第4部の入口になる

実務で古い HTML を見ると、fontcenter を見つけて反射的に「時代遅れだ」と言いたくなります。その判断自体は現在の推奨として間違っていません。ただし、この章で大切なのは、現在の推奨と、当時その要素が広まった理由を分けて考えることです。

ここで分けたいのは、「便利だったこと」と「長持ちする設計だったこと」です。fontmarquee は前者としては機能しましたが、後者としては問題を残しました。この区別を入れないと、過去を必要以上に擁護するか、逆に必要以上に嘲笑するかのどちらかに傾きます。

古い要素を笑うだけでは、Web がどうやって現在の設計へ寄ってきたのかは見えません。重要なのは、「なぜそれが必要とされたのか」「なぜ長続きしなかったのか」の両方を見ることです。そうすると、HTML の歴史は単純な進歩史ではなく、理想と現場の要求を何度もすり合わせてきた歴史だと分かります。

ここまでで、消えた要素たちは単なる恥ずかしい過去ではなく、標準が著者の需要をどう受け止めるべきかを残したと見えてきました。次章では、その逆側で「もっと厳密に、もっときれいに」を押し進めた XHTML が、なぜ Web 全体の現実とは噛み合いきらなかったのかを見ます。

参考資料

第14章 XHTML はなぜ広まらなかったのか

この章では、XHTML を「失敗した厳格主義」と雑に片づけるのではなく、筋の通った理想がなぜ公開 Web の条件と噛み合いにくかったのかを見ます。ゴールは、XHTML の挫折を「正しさが負けた」と読むのではなく、「どの環境では筋が通り、どの環境では重すぎたのか」を説明できるようになることです。

前章では、消えた要素たちを、著者の需要と標準の学習の痕跡として見ました。この章では逆に、理想をもっと厳密に押し進めた側の試みを扱います。次章では、その衝突から浮かび上がる後方互換性の重さを見ます。

14.1 XHTML の理想自体は筋が通っていた

XHTML は、HTML を XML の流儀で書き直し、文法を厳密にそろえようとする試みでした。XML は、文書やデータを厳密なルールで記述するための形式です。開始タグも終了タグもきちんと閉じる。入れ子も厳密に守る。曖昧な省略に頼らない。考え方としてはかなり筋が通っています。

この理想が魅力的だったのは、文書を機械的に扱いやすくなるからです。著者にとっても、実装者にとっても、「正しい入力だけを相手にする」世界は分かりやすい。第2部で見てきたような回復規則や暗黙補完に悩まされにくいからです。

つまり XHTML の問題は、理想が雑だったことではありません。むしろ逆で、理想は整っていました。問題は、その理想を公開 Web 全体へそのまま持ち込めるかどうかでした。

14.2 XML 的な停止は公開 Web ではコストが高かった

違いがもっともよく見えるのは、壊れた入力をどう扱うかです。HTML は少し壊れていても回復しながら読み進めますが、XML では不正な入力をそのまま処理し続けることはできません。

<p>前置き
<div>本文</div>

HTML なら、第6章で見たように、div の手前で p を閉じる形へ回復して読み進められます。しかし XHTML を本当に XML として扱うなら、この種の崩れは「何となく読めるから続行」で済みません。入力が正しくなければ、その時点で文書全体を機械的に止めるほうが筋です。

この厳密さは、閉じたシステムや入力を厳密に管理できる環境では力になります。けれど公開 Web は、古い文書、手書きの文書、完全ではない出力、雑多なツールが混ざる空間です。そこでは、著者の小さなミス 1 つでページ全体が読めなくなるコストが高すぎました。実際、XML として配信された XHTML では、たった 1 つの閉じ忘れでページが表示されず、ブラウザが黄色いエラー画面を出すことがありました。これは当時、俗に "yellow screen of death(黄色い死の画面)" と呼ばれたほどです。

14.3 text/html のままでは理想も現実も変わらなかった

ここで XHTML の難しさがもう 1 つ出ます。XHTML 風の書き方をしていても、text/html として配信されれば、多くの場面ではブラウザは HTML として処理します。つまり、見た目だけ XHTML らしくしても、処理系の根本が XML に切り替わるわけではありません。

これは実務ではかなり重要です。末尾に / を付ける、属性をきれいに閉じる、といった書き方だけを取り入れても、配信形式が text/html のままなら、ブラウザは第2部で見た HTML パーサーとして動き続けます。理想の文法へ寄せたつもりでも、運用上の前提が変わらなければ、根本の挙動は変わりません。

一方で、本当に XML として扱わせるために application/xhtml+xml で配信すると、今度はわずかな不正で文書全体が止まりやすくなります。結果として、多くの現場では「書き方だけは厳密に寄せるが、配信と処理は HTML のまま」という折衷に落ちやすかった。これは理想を中途半端に裏切ったというより、公開 Web の条件がそれを求めたと見るほうが正確です。

言い換えると、text/html のままでは理想の処理系へ届かず、application/xhtml+xml へ振り切ると公開 Web には厳しすぎた、という二重の難しさがありました。XHTML が広がりきらなかったのは、この板挟みを解く現実的な道が細かったからでもあります。

ここで見えてくるのは、XHTML の広がらなさが、思想の弱さではなく、導入コストの高さにも由来していたことです。理想を通すなら、Web 全体に「壊れたら止まる」を受け入れてもらう必要がある。しかし公開文書空間としての Web は、その方向へは動きにくかったのです。

14.4 HTML5 は理想を捨てたのではなく、現実を仕様化した

この流れの先で重要なのが、HTML5 以降の方向転換です。XML の理想をさらに推し進めようとした XHTML 2.0 は、結局 2009 年に開発が打ち切られ、現実路線の HTML5 が後継として選ばれました。ここで起きたのは、「もう正しさは不要だ」と開き直ったことではありません。現実のブラウザがすでにしていた回復や補完を、曖昧な慣習のままではなく仕様として書き下ろす方向へ進んだのです。

つまり XHTML の経験が残した教訓は、厳密さそのものの否定ではありません。公開 Web では、厳密さを入力側だけに押しつけると利用可能性が壊れる。だから、入力は現実に合わせて寛容に受け止めつつ、内部処理は仕様として厳密にそろえる必要がある。この考え方は、第2部で見たエラー回復ともつながっています。

ここまでで、XHTML が広まらなかった理由は「正しいことを言っていたのに理解されなかった」でも、「厳密さが悪だった」でもないと分かりました。公開 Web という壊れやすいが止められない空間では、XML の理想をそのまま持ち込むにはコストが高すぎたのです。次章では、その結論がなぜ「昔のページを壊さないこと」へつながるのかを見ます。

参考資料

第15章 互換性はなぜ重要なのか

この章では、後方互換性を「古いものを切れない保守性」とだけ見るのではなく、公開済みの文書を読めるまま保つための Web の責務として見ます。後方互換性は、新しい実装になっても古いページや古い書き方をなるべく読めるままにする性質だと思えば十分です。ゴールは、互換性を単なる技術的惰性ではなく、「昔のページが今日も読める」ことを支える設計判断だと説明できるようになることです。

前章では、XHTML の厳密さが公開 Web には重すぎたことを見ました。この章では、その帰結として、なぜ Web が「壊さないこと」を強く優先するのかを扱います。次章では、その責務がバグの温存にまで及ぶ例を見ます。

15.1 公開されたページは作者の手を離れて生き続ける

多くのソフトウェアでは、新しい版に合わせて古い利用者が移行することがある程度前提になります。アプリケーションなら、提供者が更新のタイミングをある程度コントロールできます。

しかし Web ページは違います。いったん公開された文書は、作者が更新を止めても、リンクされ、検索され、保存され、あとからも読まれ続けます。しかも、そのページの作者にもう連絡できないことも珍しくありません。

この条件では、ブラウザの新しい版が「古い書き方は切り捨てる」と決めた瞬間に、誰にも直せないページが壊れます。だから Web における互換性は、古い実装への情けではなく、公開された文書空間を維持するための責務になります。

しかも失われるのは、個人の趣味ページだけではありません。昔の技術記事、研究資料、企業の告知、行政情報のように、あとから参照され続ける文書も含まれます。互換性の問題は、開発者の都合だけではなく、社会に残った記録をどこまで読み続けられるかという問題でもあります。

15.2 Quirks Mode は不格好でも必要だった

この責務がよく見えるのが Quirks Mode です。これは、古いページを当時に近い癖で読むための互換モードだと思えば十分です。理想だけを言えば、すべてのページを同じ標準モードで処理したほうが単純です。けれど現実には、過去のブラウザ依存の挙動を前提に作られたページが大量にありました。

そこでブラウザは、条件によって標準モードと互換モードを切り替え、古いページでは過去の挙動へ寄せる道を残しました。標準モードは現在の標準に沿って読むモード、互換モードは古い挙動へ寄せて読むモードです。Quirks Mode は、美しい設計の勝利ではありません。むしろ、理想だけでは既存ページを守れなかったからこそ生まれた緩衝材です。

ここで重要なのは、Quirks Mode を単なる恥ずかしい互換レイヤーとして笑わないことです。あれは「標準に従わなかったページを甘やかした」だけではなく、「すでに公開され、現に読まれている文書を急に壊さない」ための現実的な責任の取り方でもありました。

15.3 互換性は実装の負債ではあるが、Web の価値も支えている

もちろん互換性にはコストがあります。実装は複雑になり、仕様書も長くなり、設計をきれいに保ちにくくなります。第12章で見た仕様書の巨大さの一部も、この負債と無関係ではありません。

それでも Web が長く使える基盤でいられたのは、その負債を引き受けてきたからです。昔のリンクが急に全部無効にならない。古い記事が、数年後もだいたい読める。企業サイトも個人ブログも研究ページも、完全ではなくても残り続ける。この性質は、単なる技術選好ではなく、Web の価値そのものです。

XHTML が広がりにくかったのも、ここにつながります。入力の厳密さを優先して古いページが壊れやすくなるなら、公開文書空間としての Web の価値が下がってしまう。だから Web は、きれいさだけではなく、壊さない責任を優先する方向へ寄りました。

15.4 「古いものを残す」と「何も変えられない」は別である

ここで誤解しやすいのは、互換性を重視するなら何も改善できないのではないか、という見方です。実際にはそうではありません。Web は、新しい要素や API を足しながら、古いページもなるべく壊さないよう進んできました。

大事なのは、変更のしかたです。既存ページの意味を壊す形で一気に切り替えるのではなく、新しい仕組みを足し、古い仕組みは読めるまま残す。この慎重さが、Web を遅く見せることもあります。しかしその遅さは、公開済みの文書と利用者を置き去りにしないための遅さでもあります。

ここまでで、互換性は古いものへの未練ではなく、公開された文書を基盤として引き受ける責務だと分かりました。次章では、その責務がさらに進んで、仕様上あまり好ましくないバグさえ簡単には消せなくなる理由を見ます。

参考資料

第16章 バグはなぜ残るのか

この章では、Web に残るバグを単なる怠慢や技術不足としてではなく、互換性が正しさの条件に入り込んだ結果として見ます。ゴールは、「直したほうが正しいはずの挙動」がなぜ簡単には直せないのかを、実装の甘さではなく、公開済みの Web を壊さない責務から説明できるようになることです。

前章では、互換性が公開文書空間を維持する責務だと見ました。この章では、その責務がどこまで重くなるかを、バグの残存という形で見ます。次の第5部では、この複雑さを前提に、HTML を巡る有名な議論を整理していきます。

16.1 「直せばよい」が通らない世界

普通の感覚では、バグは見つけたら直すべきものです。その判断自体は間違っていません。実際、ブラウザ実装者も好んで不具合を残したいわけではありません。

しかし Web では、ある挙動が長く存在すると、既存サイトの HTML、CSS、JavaScript がその挙動を前提に組まれてしまうことがあります。すると、実装上は望ましくないふるまいでも、急に正してしまうと現実のページが壊れます。

ここで難しいのは、「仕様どおりに直す」ことと「現に動いている Web を壊さない」ことが一致しない場面があることです。第15章で見た互換性の責務は、ここで単なる保守性ではなく、実装判断そのものを縛る条件になります。

16.2 互換性が正しさの一部になってしまう

この問題が厄介なのは、バグと正しさの境界が固定されていないことです。実装者が「これはおかしい」と思っていても、その挙動に依存するページが大量にあるなら、修正による破壊コストが無視できません。

その結果、Web では「現実に壊さないこと」が、正しさの条件の一部へ入り込んできます。仕様が既存実装を吸い上げる形で整理されることがあるのも、そのためです。理屈だけなら不要な挙動でも、広く使われているなら、単純に消すより先に「どう整合させるか」を考えなければなりません。

第12章で見たように、仕様書は理想の定義集であると同時に、実装をそろえるための文書でもあります。そこに第15章の互換性責務が重なると、「既存実装ではこう動き、しかも多くのページがそれを前提にしている」という事実そのものが、仕様整理の条件へ入ってきます。ここでは、仕様、実装、既存ページが互いに切り離せなくなっています。

これは、バグを正当化する話ではありません。むしろ逆で、Web では何を正しいと呼ぶか自体が、実装、仕様、既存ページの三者関係の中で重くなる、という話です。

16.3 バグが残るのは、ブラウザが公共基盤だからである

ここで第3章まで戻ると、Web は最初から閉じたアプリケーション配布基盤ではなく、公開された文書空間でした。誰かのサーバーにあるページを、別の誰かのブラウザが読み続ける。この前提がある限り、ブラウザは単なる1社の製品では済みません。

公共基盤に近いものほど、「理屈では正しい更新」がそのまま許されにくい。道路標識のルールを一夜で変えにくいのと少し似ています。もちろん完全に同じではありませんが、変化のコストを利用者全体が負う点では近いものがあります。ブラウザのバグが簡単に消せないのも、個別製品の品質問題というより、基盤としての責任が重いからです。

この重さを理解すると、HTML やブラウザの変化が遅く見える理由も変わってきます。遅いのは、怠けているからではなく、壊したときの影響範囲があまりにも広いからです。

16.4 「バグが残る」ことと「改善を諦める」ことは別である

ここで誤解したくないのは、では Web は何も改善できないのか、という点です。実際には、実装者も標準化側も、壊れにくい形で修正や整理を進めています。問題は、正しさだけを基準に一気に切り替えにくいことです。

だから Web の改善は、追加、段階的移行、警告、互換レイヤーの維持といった慎重な手順を取りがちです。見た目には回りくどくても、それは既存の文書と利用者をまとめて崩さないための回り道でもあります。

ここでのポイントは、「直せない」のではなく「どう直すかが厳しく制約される」ことです。修正そのものを諦めるのではなく、破壊コストを下げながら移す道を探す。その慎重さまで含めて、Web の改善は設計されています。

ここまでで、バグが残るのは不完全さの証拠であると同時に、壊せない基盤であることの裏返しでもあると分かりました。第4部を通して見えてきたのは、HTML の歴史が理想と現実のどちらか一方ではなく、そのあいだで責任を引き受け続けてきた歴史だということです。次の第5部では、その前提の上で、h1tabledivb を巡る有名な議論を整理していきます。

参考資料

第4部 演習

  1. blinkfont のような要素が生まれた背景を、当時の著者の需要から説明してください。
  2. XHTML の理想はどこにあり、なぜ公開 Web では広く定着しませんでしたか。
  3. 互換性を守ることが、なぜバグや複雑さの温存にもつながるのか説明してください。

第5部 HTMLを巡る議論

第5部の役割は、HTML にまつわる有名な言説を、歴史と仕様の両方から整理することです。h1、table、div、b のように、実務で何度も蒸し返される話題を取り上げます。

ここで重要なのは、単に「都市伝説は間違いです」と言って終わらないことです。なぜその言説が広まり、どの条件では部分的に正しかったのかを見ます。そうすることで、次の第6部で扱う標準化や実装者の意思決定も理解しやすくなります。

第17章 h1 は 1 個だけなのか

この章では、「ページに h1 は 1 個だけ」という有名な言い方を、そのまま正誤で裁くのではなく、編集上の助言、仕様上の事実、HTML5 時代の議論に分けて整理します。ゴールは、この標語を見聞きしたときに、「完全に間違い」と切るのでも「絶対ルール」と信じるのでもなく、どの文脈で出てきた言い方なのかを説明できるようになることです。

前章までで、HTML の歴史は単純な善悪で割れないと見てきました。この章からは、その複雑さが実務の言説としてどう現れるかを見ます。次章では、同じく強い善悪で語られがちな table の話を扱います。

17.1 「1 個だけ」は仕様の絶対規則ではない

まず事実から押さえると、HTML では h1 が複数あるだけでただちに不正になるわけではありません。見出し要素は文書の構造を示すものであり、ページ全体に 1 個だけという単純な個数制限で定義されているわけではないからです。

この点を外すと、h1 を 2 個書いた瞬間に仕様違反だ、という雑な理解になります。しかし仕様上の話としては、問題は個数そのものより、見出しの構造がどうなっているかです。

つまり「h1 は 1 個だけ」は、少なくとも仕様の絶対規則として読むと粗い。ここを最初に切り分けておかないと、あとの議論が全部ずれます。

17.2 それでも「1 個だけ」が広まった理由

では、なぜこの言い方がここまで広まったのでしょうか。理由の 1 つは、編集や執筆の感覚としては、それなりに筋が通っていたからです。

1 本の文書に大見出しが 1 つあり、その下に h2 h3 と階層が続く、という構成は分かりやすい。教える側にとっても、「まず h1 はページの主題」と言ったほうが説明しやすい。だから h1 を 1 個にしておく実務上の助言は、一定の整理として長く使われました。

しかもこの助言は、人間の読者だけでなく、テンプレート設計やレビューでも扱いやすい既定値になりやすい。ページの主題はここ という合意を 1 つ置くほうが、チーム内でも説明しやすいからです。だから標語としては生き残りやすかった。

ここで大事なのは、それが仕様の強制と同じではないことです。編集上の助言としては有効でも、HTML の絶対規則だと言い切ると雑になる。h1 を 1 個にするのが常に悪いわけでも、複数あるのが常に悪いわけでもありません。

17.3 HTML5 とアウトラインアルゴリズムが混乱を増やした

話をややこしくしたのが、HTML5 時代のアウトラインアルゴリズムをめぐる議論です。一時期は、各 sectioning content の中で h1 を使ってもよい、という説明が広まりました。

<article>
  <h1>記事タイトル</h1>
  <section>
    <h1>節タイトル</h1>
  </section>
</article>

この発想では、文書全体で 1 個の h1 を守るより、セクションごとに見出しを立てるほうが自然に見えます。理屈としても一貫しています。しかし実務では、このモデルが期待されたほど単純には定着しませんでした。支援技術、既存の解説、開発者の理解、検索やツールの現場が、必ずしもその説明にきれいには揃わなかったからです。

つまり問題は、「理論として破綻していた」ことより、「現場の道具と理解がその理論を前提に揃わなかった」ことでした。仕様の中にある説明と、実際に人が書き、ツールが読み、支援技術が伝える文書構造が、きれいに一体化しなかったのです。

決定的だったのは、このアウトラインアルゴリズムが どのブラウザにも支援技術にも実装されなかった ことです。仕様の中だけに存在する理想で、実際の見出しレベルを組み替えてくれる実物はどこにもありませんでした。そのため後に、この仕組みは WHATWG の仕様からも削除されました。いま現実的な結論は単純で、「セクションごとに h1 を置けば自動でレベルが調整される」とは考えず、h1 から h6 までを自分で明示することです。

その結果、「h1 は 1 個だけ」と「各セクションに h1 でよい」が、時代によって別々に広まり、現場には混乱だけが残りやすくなりました。

17.4 実務では個数より見出し構造を見る

では、いま実務ではどう考えるべきでしょうか。いちばん重要なのは、h1 の個数だけで良し悪しを決めないことです。見るべきなのは、ページの主題が伝わるか、見出し階層が読者にとって自然か、その構造が支援技術や人間の読解にとって分かりやすいかです。

多くのページでは、結果として h1 が 1 個に落ち着くことはあります。それは自然な設計であることが多い。しかしそれを「絶対にそうしなければならない」という都市伝説へ変えると、判断基準が逆に貧しくなります。

この章の要点は、h1 を何個置けるかというクイズの答えではありません。編集上の助言、仕様上の事実、HTML5 時代の議論を分けて読む視点です。そうすれば、「h1 は 1 個だけ」という短い標語が、なぜ部分的には便利で、同時にそのままでは雑なのかを説明できます。次章では、同じように強い標語で語られがちな table の善悪を見直します。

参考資料

第18章 table は悪者だったのか

この章では、「table は悪」という有名な言い方を、そのまま要素の善悪として受け取るのではなく、レイアウト用途での乱用と、データ表としての本来の役割に分けて整理します。ゴールは、table を見たときに「使った時点で古い」と反射するのではなく、「この用途で何を伝えようとしているか」で評価できるようになることです。

前章では、h1 を巡る標語が、仕様と助言と実務を混ぜて広まりやすいと見ました。この章でも同じく、強い標語の背後にある文脈差を扱います。次章では、div がなぜ悪者にされやすいのかを見ます。

18.1 批判されたのは table そのものよりレイアウト用途だった

table が嫌われた背景には、ページ全体を表の入れ子で組む時代がありました。ヘッダー、サイドバー、本文、余白まで、全部を tabletrtd で配置する。そうした書き方は、たしかに長く、読みづらく、保守しにくいものでした。

ただし、そうした書き方が広まったのは、単に書き手が意味を軽視していたからではありません。当時はページを安定して並べる手段が限られ、複数のブラウザで似た見た目を確保する必要も強かった。table は、その条件の中では実用的な選択肢でもありました。この時代を象徴するのが、spacer.gif と呼ばれた 1×1 ピクセルの透明画像です。表のセルにこれを置いて幅や高さを指定し、余白を作る——いまから見れば驚くような手法が、レイアウトを安定させるために広く使われていました。

このとき批判されていたのは、「表という要素が存在すること」ではありません。データの行列関係を持たないものまで、レイアウト都合で表へ押し込んでいたことです。CSS レイアウトが普及してくると、その不自然さが一気に見えるようになり、「table は悪」という反動の強い言い方が広まりました。

つまり最初に切り分けたいのは、悪かったのが要素そのものではなく、用途とのずれだったという点です。

18.2 データ表にとっては table がいまも自然である

一方で、行と列の関係を持つ情報には、いまでも table が最も自然です。売上一覧、料金表、比較表、時刻表のように、見出しと値の対応が二次元に並ぶ情報では、表として読むこと自体が内容の一部だからです。

<table>
  <tr><th>商品</th><th>価格</th></tr>
  <tr><td>ノート</td><td>500円</td></tr>
</table>

この種の情報を div だけで組み直して見た目を似せても、文書が伝える意味は同じにはなりません。表としての関係が薄れ、支援技術や機械処理にとっても読み取りにくくなります。つまりデータ表の文脈では、table は古い要素ではなく、意味をはっきり渡せる要素です。

たとえば、どの見出しがどの値に対応するのか、行と列の交点が何を意味するのか、といった情報は、見た目だけではなく構造として渡る必要があります。そこを div の並びへ崩すと、人間には何となく表に見えても、読む側にとっての関係が弱くなります。

ここで見えてくるのは、第5章で見た tbody の話ともつながります。table は単なる箱ではなく、表モデルという内部構造を持った要素です。だからレイアウトの汎用コンテナとして乱用すると無理が出る一方、表として使うと強い意味が出ます。

18.3 「禁止」ではなく、何を表すかで判断する

table 論争が長引くのは、「レイアウト用途での乱用」と「データ表としての正当な利用」が、短い標語の中でまとめて潰されやすいからです。table を禁止すると言ったほうが教えやすい。しかしそれでは、本来の役割まで巻き添えにします。

ここで必要なのは、要素を見る視点を「新しいか古いか」から「何を表すか」へ戻すことです。レイアウトのために行列関係のないものを表へ押し込むなら不自然です。逆に、行と列の関係が内容の核心にあるなら、table を避けるほうが不自然になります。

この判断は、HTML の他の話題とも同じです。h1 の個数だけでは決められないように、table も要素名だけで善悪を決められません。文脈を落とした標語は、部分的な真実を乱暴に広げただけのものになりやすいのです。

18.4 実務では「表らしさ」を先に問う

実務で迷ったときに先に問うべきなのは、「これは見た目が表っぽいか」ではなく、「利用者にとって表として読むべき情報か」です。列見出しと行見出しの関係があり、その交点に値が入るなら、table は有力です。逆に、ページの骨組みを並べたいだけなら、table ではなく別のレイアウト手段を選ぶべきです。

ここで押さえたいのは、「table を使ってよいか悪いか」という単純な答えではありません。批判された文脈と、いまでも正しい文脈を分けて考える視点です。そうすれば、「table は悪」という標語が、どこまで本当で、どこから雑になるのかを説明できます。次章では、同じように悪者扱いされやすい div を見直します。

参考資料

第19章 div は本当に悪なのか

この章では、「div は悪」という言い方を、そのまま要素の価値判断としてではなく、意味を持たせられる場所まで汎用コンテナへ崩してしまう問題として整理します。ゴールは、div を見たときに「使った時点で負け」と反応するのではなく、「ここに本当に固有の意味要素が必要だったのか」を考えられるようになることです。

前章では、table を巡る善悪が、用途の違いを落とした標語だと見ました。この章でも同じく、要素名だけでは決められない話を扱います。次章では、見た目の要素として語られがちな b がなぜ残ったのかを見ます。

19.1 div soup が批判される理由

div は、ほとんど意味を持たない汎用コンテナです。だからこそ便利で、どこにでも置けます。しかしその便利さが行きすぎると、見出し、ナビゲーション、主要領域、補足領域まで全部が div だらけになり、文書構造の手がかりが薄くなります。

<div class="header">...</div>
<div class="nav">...</div>
<div class="main">...</div>

この種の書き方が div soup と呼ばれて嫌われるのは、見た目が冗長だからだけではありません。そこに何があるのかを、要素自体があまり伝えなくなるからです。headernavmain のような要素で渡せる意味まで、全部を無地の箱へ押し込んでしまうと、HTML が持てる構造上の情報が減ります。

しかも現代では、テンプレートやコンポーネントの都合で div が増えやすい。だから div soup は、手書き HTML の古い癖というより、いまの実装でも油断すると起きる問題です。便利な箱が増えるほど、「本当にここは無地の箱でよいのか」を意識しないと、意味はすぐ薄くなります。

19.2 それでも div が必要な場面は多い

ただし、ここで div 自体を悪者にすると、話は逆に雑になります。現実の UI は、意味要素だけですべて組み切れるほど単純ではありません。

スタイリングのためのまとまり、レイアウト上の包み、JavaScript のフック、再利用部品の外枠。そうした場面では、div が最も自然です。意味を足すべきではない箱にまで、無理に意味要素を当てはめるほうが不自然になることもあります。

たとえば、カード部品の内側で余白や境界線をまとめてかけたい、複数要素をまとめて並べたい、スクリプトがまとめてつかむ外枠が欲しい。こうした場面では、「ここに新しい文書上の役割がある」とまでは言えません。だから div のほうが素直です。

つまり問題は、div を使うことそのものではありません。固有の意味を持つべき場所を、何となく全部 div で済ませてしまうことです。汎用コンテナが悪いのではなく、意味の切り分けを放棄したまま使うことが問題になります。

19.3 セマンティクスは「固有要素があれば使う」から始まる

ここで必要なのは、div を禁止することではなく、順番を逆にしないことです。まず「ここに意味のある要素があるか」を考える。header nav main section article などで表せるなら、そちらを使う。そのうえで、意味を増やす必要がないまとまりには div を使う。この順番なら、div は敵ではなく、汎用要素として適切な位置に収まります。

この考え方は、第18章の table とよく似ています。table も要素名だけで善悪を決められなかったように、div も要素名だけで良し悪しは決まりません。何を伝えたいかに対して、固有要素で足りるのか、汎用コンテナが自然なのかを見分ける必要があります。

だから div への批判が妥当になるのは、「この場所にはもっと意味のある要素があったのに、全部を無地の箱へ落としてしまった」ときです。逆に、意味を持たせる必要のないラッパーまで責めると、セマンティクスを誤解した議論になります。

19.4 実務では「何を伝えたい箱か」を問う

実務で div を見るときは、「div がある」という事実より先に、「この箱は何を伝えるためにあるのか」を見るほうが有効です。文書構造の役割を持つなら固有要素を検討する。役割ではなく単なるレイアウトや包みなら div でよい。この判断ができれば、div soup への違和感も、単なる美意識ではなく説明可能なものになります。

この章で言いたいのは、「div は使うな」という標語ではありません。汎用要素が悪いのではなく、意味を持つ場所まで汎用化してしまうことが問題です。そうすれば、「div は悪」という言い方が、どこまで本当で、どこから雑になるのかを整理できます。次章では、見た目だけの要素だと思われがちな b が、なぜ今も仕様の中に残っているのかを見ます。

参考資料

第20章 b タグはなぜ生き残ったのか

この章では、b を「見た目だけの古い要素」と切り捨てるのではなく、なぜ削除ではなく再定義という道が選ばれたのかを見ます。ゴールは、b を見たときに「CSS があるなら不要」と即断するのではなく、「どの意味は strong に任せ、どの役割なら b が残るのか」を説明できるようになることです。

前章では、div を悪者にしすぎると、汎用要素の必要性まで見失うと見ました。この章でも同じく、見た目だけで要素の価値を決めない話を扱います。次の第6部では、こうした仕様判断を支えてきた人々と標準化の流れへ進みます。

20.1 b は「太字にするタグ」だけでは終わらなかった

かつて b は、ほとんど見た目のための要素として使われました。その文脈だけを見ると、CSS で太字を指定できる現在では、役目を終えたように見えます。

しかし HTML は、古い要素を何でも単純に消すわけではありません。互換性の問題もあるし、実際の文章の中には「強い重要性ではないが、周囲から視覚的に区別したい」テキストが残ります。そこで b は、単なる太字指定ではなく、実用的な都合で読み手の注意を向けたいテキストを、周囲からスタイル上ずらして示すための要素として再定義されました。

ここで重要なのは、b が「見た目のための古い要素」から「重要性ではなく区別を担う要素」へ置き直されたことです。削除ではなく、役割の調整が選ばれたわけです。

20.2 strongb は似て見えて同じではない

この違いは、strong と並べると見えやすくなります。

<p><strong>重要:</strong> 申込期限は明日です。</p>
<p>検索結果: <b>HTML</b></p>

strong は、内容の重要性や強い強調を表します。読み手に「ここは重い」と伝える要素です。一方 b は、重要性そのものではなく、視覚的に区別したい語句へ向いています。キーワード、製品名、導入ラベル、要約中で目を引かせたい語など、周囲より少し目立たせたいが、警告や強調として読むべきではない場面です。

この差を無視すると、「太字なら全部 strong」「見た目なら全部 CSS」で二分したくなります。しかし現実の文章には、そのどちらにもきれいに収まらない区別があります。b が残ったのは、その隙間を埋める必要があったからです。

20.3 HTML は古い要素を再定義して残すことがある

ここで見えてくるのは、HTML が古い要素を扱うときの流儀です。第13章では、消えた要素たちが需要の痕跡を残したことを見ました。一方 b では、完全に消すより、現代の文脈に合わせて意味を調整して残す道が選ばれました。

これは後方互換性だけの問題ではありません。もし b を単に obsolete にして、「以後は使うな」で済ませていたら、現実に存在する弱い視覚的区別のニーズを、全部 CSS や別の要素へ押し込むことになります。そこには、それはそれで別の不自然さが出ます。

つまり b の生存は、古いものへの未練というより、「現実の文章で必要な区別を、どの要素が引き受けるか」という再配置です。HTML がしているのは、過去の遺物をただ温存することではなく、役割の棚卸しでもあります。

20.4 実務では「重要なのか、区別したいだけなのか」を問う

実務で bstrong を迷ったときは、見た目ではなく、何を伝えたいかで切るほうがよい。重要性や警告の重みを伝えたいなら strong。文章の流れの中で、その語句だけを周囲から区別したいなら b。意味を持たせず見た目だけ変えたいなら CSS も選択肢に入ります。

この切り分けを入れると、b が CSS に完全に置き換わるわけではないことも見えてきます。CSS は見た目を変えますが、その語句を「周囲から少し区別したい」という文章上の意図までは表しません。逆に、その意図すらないなら、b を使わず CSS だけで済ませたほうが素直です。

この章の要点は、「b は古いから使うな」という標語の逆です。b が生き残ったのは、単なる慣性ではなく、HTML が古い要素を再定義しながら現代の役割へ置き直すことがあるからです。そう読むと、b は仕様の中で何となく生き残ったのではなく、調整された居場所を与えられたと分かります。次の第6部では、こうした居場所の調整を誰がどのように決めてきたのかを見ます。

参考資料

第5部 演習

  1. 「h1 は 1 個だけ」「table は悪」「div は悪」のうち 2 つを選び、どこまで本当でどこから雑かを説明してください。
  2. bstrong の違いを、見た目ではなく意味の観点から説明してください。
  3. HTML の議論で短い標語が広まりやすい理由を考えてください。

第6部 HTMLを作り続ける人たち

第6部の役割は、HTML を抽象的な仕様ではなく、人が作り、人が争い、人が維持してきた技術として描くことです。ティム・バーナーズ=リー(Tim Berners-Lee)、ブラウザ戦争、WHATWG を通して、HTML の背後にいる主体を見ます。

ここでは英雄譚に寄せすぎず、制度と衝突の話として整理します。次の第7部では「それでも HTML が生き残った理由」を扱うため、この部はその歴史的な基盤を作る位置づけです。

第21章 ティム・バーナーズ=リーが残したもの

この章では、ティム・バーナーズ=リー(Tim Berners-Lee)を「HTML を作った人」とだけ覚えるのではなく、なぜ Web が公開された文書の網として出発したのかを、その初期設計から見ます。ゴールは、HTML・URL・HTTP を別々の発明として暗記するのではなく、それらが一緒にそろって初めて Web になったと理解することです。

前章では、b が削除ではなく再定義で生き残ったと見ました。そこには、古いものを雑に捨てず、現実の利用に合わせて役割を調整する Web の流儀がありました。この章から第6部では、そうした流儀を形作ってきた人々と歴史を見ます。次章では、その初期条件の上で起きたブラウザ戦争が何を残したかを扱います。

21.1 HTML だけでは Web にならない

ティム・バーナーズ=リーの名前は、しばしば HTML の発明者として紹介されます。それは間違いではありません。しかし、この本の流れで重要なのは、HTML だけを取り出しても Web は成立しないことです。文書の中にリンクを書けても、そのリンク先をどの名前で指し、どう取りに行くかが決まっていなければ、世界に散らばる文書はつながりません。

そこで初期の Web では、文書の構造を記す HTML、場所を指し示す URL、文書をやり取りする HTTP が一体の仕組みとして設計されました。残されたものは単独のタグ集合ではなく、「どこにある何を、どう参照し、どう受け取るか」という公開文書の最低限の約束です。

もちろん、後の Web を育てたのは一人ではありません。ブラウザ実装者、標準化団体、著者、サーバー側の開発者がそれぞれに形を作ってきました。それでも出発点として、この三つを公開された組として置いたことは、後の発展方向を強く縛る初期条件になりました。

この一体性を先に見ておくと、HTML が最初から単なるマークアップ言語の話ではなかったことも分かります。HTML は、リンクされる文書という前提の中で生まれた。だから後の章で見る互換性や標準化の議論も、文書の記法だけでなく、公開された網を保つ話として読めるようになります。

この第6部から第7部にかけて扱う歴史は、ざっと次のように流れます。細部はこれからの章で見ていきますが、先に全体像を持っておくと迷いません。

1989 年の提案から公開、img 登場と無償化、ブラウザ戦争、XHTML の挫折、HTML5、2019 年の標準一本化、現在の Living Standard までを並べた年表
図 21-1 HTML は完成したのではなく、調整され続けてきた。

21.2 解決したかったのは閉じた文書管理ではなかった

第2章では、CERN(欧州原子核研究機構)の情報共有問題から Web が始まったことを見ました。ここで改めて重要なのは、解決策が巨大で複雑な文書管理システムではなく、比較的単純な公開と参照の仕組みとして組み立てられたことです。

このあたりには、語りたくなる逸話がいくつも残っています。バーナーズ=リーが 1989 年に書いた提案書には、上司のマイク・センドール(Mike Sendall)が「Vague but exciting...(曖昧だが、わくわくする)」と走り書きしたと伝えられます。最初の Web サーバーは彼の NeXT コンピュータ 1 台で、本体には「This machine is a server. DO NOT POWER IT DOWN!!(これはサーバーです。電源を切らないこと)」という貼り紙がしてあったといいます。世界初の Web サイト(info.cern.ch)も、その素朴な 1 台から公開されました。豪華な基盤ではありません。大事なのは、その仕組みが最初から公開された約束として設計されていたことです。

たとえば、ある研究資料を読み、その中の別文書への参照をたどり、その先へ移る。初期の Web が目指したのは、その動作を特別な契約や専用端末に依存せずに成立させることでした。そのためには、文書はある程度単純で、場所は共有できる形で表され、通信方法も公開されている必要があります。

ここでティム・バーナーズ=リーが残したものは、「最初の Web サイトを作った」という出来事より、公開された約束で回る仕組みを最初から選んだことです。もしここで、特定ソフトウェアの中だけで通じる文書形式や、閉じた識別子や、独自の通信方式が選ばれていたら、後の Web はかなり違う形になっていたはずです。

21.3 公開性はあとから付け足された性格ではない

Web が公開的な技術になったのは、普及したあとで理念が加わったからではありません。出発点から、リンク先を外へ向けて張れること、誰かの文書を参照できること、その参照方法が閉じた組織の内規に依存しないことが重視されていました。

もちろん現実の Web は、その後ずっと理想どおりだったわけではありません。商用化も起きたし、ブラウザ間の競争も起きたし、独自拡張も大量に生まれました。それでも「公開された文書の網」という出発点があったからこそ、Web は完全に誰か一社の製品にはなりませんでした。

この意味で、ティム・バーナーズ=リーが残したものは発明品の数ではありません。HTML、URL、HTTP を通して、文書公開の仕組みを閉じた製品ではなく、共有された土台として始めたことです。後の標準化団体や仕様策定者が何を守ろうとしたのかも、この初期条件を踏まえると見えやすくなります。

21.4 人物伝ではなく、初期条件として読む

この章で人物を大きく扱うのは、英雄譚を書きたいからではありません。本書の主題は、HTML がなぜ今の形になったのかです。その答えの一部は、最初にどんな条件で Web が始まったかにあります。

ティム・バーナーズ=リーを「偉人」として消費してしまうと、話は豆知識で終わります。しかし「HTML は公開された文書の網の一部として設計された」と読むと、その後の互換性重視、標準化、実装の苦労まで一本の線でつながります。各社のブラウザが競い合えたのも、そもそも同じ Web を読むという共有土台があったからです。第22章では、その土台の上で起きたブラウザ戦争が、なぜ混乱であると同時に標準化の必要性を浮かび上がらせたのかを見ます。

参考資料

第22章 ブラウザ戦争が残したもの

「Best viewed in Netscape」——かつての Web には、こんなバッジが堂々と貼られていました。同じ Web のはずなのに、どのブラウザで見るかで表示が変わる。なぜ、そんな時代があったのでしょうか。

この章では、ブラウザ戦争を「昔は大変だった」で終えるのではなく、なぜ HTML とブラウザ実装が互換性にそこまで神経質になったのかを、その歴史的な理由から見ます。ゴールは、独自拡張が増えた時代を懐古的に眺めるのではなく、競争が Web に何をもたらし、何を壊しかけたのかを説明できるようになることです。

前章では、ティム・バーナーズ=リーが Web を公開された土台として始めたことを見ました。この章では、その共有土台の上で Netscape と Internet Explorer が競争した結果、何が起きたかを扱います。Netscape も Internet Explorer も、当時の代表的な Web ブラウザです。次章では、その反省の先で、HTML が誰によってどう決められているかを見ます。

22.1 競争は Web を速く広げたが、同時に割った

1990 年代後半のブラウザ戦争では、Netscape と Internet Explorer が新機能を激しく競い合いました。短期的には、画像、スクリプト、レイアウト、埋め込み表現など、Web でできることが一気に増えました。その意味で、競争は Web を広げる推進力でもありました。

しかし同時に、その競争は「同じ Web を見る」という前提を壊しかけました。あるブラウザで動くページが別のブラウザでは崩れる。あるタグや API が片方にしかない。著者は、文書を書くというより、どのブラウザへ合わせるかを選ぶ作業へ引き寄せられていきます。

ここで問題だったのは、競争そのものではありません。共有された土台の上で、互換性より囲い込みが優先されやすくなったことです。Web は本来、別々の組織が公開した文書を相互に読めることに強みがありました。その基盤が、実装ごとの差で揺らぎ始めたわけです。

22.2 独自拡張は便利さと引き換えに分断を生んだ

この時代には、各社が独自タグや独自 API を打ち出しました。象徴的なのが、テキストを点滅させる Netscape の <blink> と、文字を横へ流す Microsoft Internet Explorer の <marquee> です。<blink> は開発者が酒場での雑談をきっかけに一晩で実装した、という逸話で知られ、どちらも標準には採用されず、<blink> はのちに各ブラウザから削除されました。著者から見れば、こうした独自機能は魅力的でもあります。新しい見た目や振る舞いをすぐ使えるからです。しかし、その便利さはしばしば「このブラウザで見てください」という条件とセットでした。当時のページに『Best viewed in Netscape』『Internet Explorer 推奨』といったバッジが当たり前のように貼られていたのは、文書が閲覧ソフトに縛られていたことの裏返しです。

たとえば、ブラウザごとに使える機能が違えば、著者は分岐を書いたり、場合によっては片方のブラウザを切り捨てたりします。文書を公開するはずの Web が、実際には閲覧ソフトごとの別世界へ分かれ始めるわけです。

あるページが Internet Explorer 向けの機能に依存して作られていれば、Netscape では意図どおりに読めません。逆も同じです。すると Web 文書は、公開された文書でありながら、実質的には特定の閲覧ソフトに縛られます。これは、第21章で見た出発点とかなり緊張します。

さらに厄介なのは、いったん広く使われた独自挙動は、あとで簡単に消せないことです。互換性のために残され、他社も追随せざるを得なくなる。第16章で見た「壊せない Web」は、こういう歴史ともつながっています。ブラウザ戦争が残したのは一時的な混乱だけではなく、長く尾を引く互換性負債でもありました。

22.3 標準化は理想論ではなく、疲弊への対策だった

この時代が残した最大の教訓は、互換性を市場競争だけに任せると、Web 全体が疲弊するということでした。著者は分岐だらけのコードを書くことになり、利用者はブラウザごとの差に振り回され、実装者は他社の独自挙動まで無視できなくなります。

だから標準化は、きれいごとのために強調されたのではありません。共有された仕様がなければ、同じ文書を相互に読めるという Web の基盤が持たないからです。今の HTML 仕様が、理想的な文法だけでなく、実際のパースやエラー回復、既存実装の挙動まで深く書くのは、この反省抜きには理解しにくい。

現在でもブラウザ間の競争は続いています。新機能の実装順、実験機能、開発者体験では差が出ます。ただし、少なくとも「各社が好き勝手に別々の HTML を作る」方向は、過去の失敗として共有されるようになりました。競争を否定したのではなく、競争を共有土台の上へ戻そうとしたのです。

22.4 ブラウザ戦争は現在の仕様の書き方を説明する

この章で伝えたいのは、ブラウザ戦争を懐かしい逸話として覚えることではありません。HTML 仕様がなぜそこまで実装寄りで、互換性にうるさく、既存の挙動を無視できないのか。その理由の一部は、この時代の混乱にあります。

つまりブラウザ戦争が残したものは、独自機能の一覧ではなく、「共有された Web を保つには、共有されたルールが要る」という教訓です。第23章では、その教訓を受けて、いま HTML を誰がどのように決めているのかを見ます。

参考資料

第23章 HTMLは誰が決めているのか

この章では、HTML を「どこかの偉い組織が完成版を配る仕様」としてではなく、実装者・編集者・標準化団体のあいだで継続的に運用される仕様として見ます。ゴールは、WHATWG や W3C という名前を覚えることではなく、なぜ HTML が版で止まらず、Living Standard という形を取っているのかを説明できるようになることです。

前章では、ブラウザ戦争の混乱が、共有ルールの必要性を露出させたと見ました。この章では、その反省の先で、いま HTML が誰によってどう決められているかを扱います。次の第7部では、そうして運用され続ける HTML が、なぜ今も生き残っているのかを見ます。

23.1 HTML は一度決めて終わる仕様ではない

現在の HTML では、WHATWG の HTML Living Standard が中心的な参照点になっています。WHATWG は、ブラウザベンダーや関係者が Web 標準を継続的に整備するためのコミュニティです。名前の通り、この仕様は版で固定されず、継続的に更新されます。ここでまず重要なのは、「最新版が出たら古い Web を捨てる」という発想ではないことです。既存の Web を壊さずに、新しい現実を少しずつ取り込むために、仕様そのものが動き続けています。

この形が必要になったのは、第22章で見たように、実装と仕様がずれたまま放置されると Web 全体が疲弊するからです。逆に言えば、仕様は理想だけを書いてもだめで、実際に動いているブラウザ、著者が書いている HTML、既存ページの互換性を引き受けなければなりません。HTML が「生きている仕様」になったのは、気分の問題ではなく、運用上の必要でした。

23.2 組織名より、誰が何を持ち寄るかが大事

ここで WHATWG や W3C の名前が出てきますが、本書で伝えたいのは組織図そのものではありません。W3C は Web 標準を公開・議論してきた標準化団体です。かつては W3C と WHATWG がそれぞれ別に HTML の仕様を出していた時期もありましたが、2019 年に両者は合意し、HTML と DOM の標準を WHATWG の Living Standard へ一本化しました。いま単に「HTML 仕様」と言えば、この WHATWG 版を指します。大事なのは、ブラウザベンダー、仕様編集者、実装者、著者コミュニティ、標準化団体が、それぞれ別の制約を持ち寄っていることです。少なくとも現在の読者にとって重要なのは、「別々の HTML が並立している」と考えるより、HTML が継続的な標準化と実装の往復の中で保たれていると捉えることです。

ブラウザベンダーは実装と互換性を気にします。仕様編集者は曖昧さを減らし、実装可能な形へ落とし込みます。著者側の需要も無視できません。標準化団体は、それらを公開された形で議論し、文書化し、合意形成の場を整えます。提案、議論、実装、フィードバックの往復を経て仕様が更新されるのであって、会議室の中だけで完結するわけではありません。つまり HTML は、誰か一人が決めるのでも、投票だけで決まるのでもなく、現実に動いている Web の制約をすり合わせながら決まっていきます。

だから HTML は誰が決めているのか という問いに、単一の固有名詞だけで答えると少し外します。正確には、「どの組織の下で、どの編集者が、どの実装と互換性を見ながら、どの議論を経て決めているのか」を見る必要があるわけです。

23.3 仕様は法律集ではなく、合意形成の痕跡でもある

この制度の理解が役立つのは、HTML 仕様を固定された法律集として見なくてよくなるからです。仕様書には、理想の設計だけでなく、過去との互換性、実装上の判断、失敗を繰り返さないための細かな規定が折り重なっています。第4章から第8章で見たようなパーサーやエラー回復の細かさも、まさにその産物です。

この視点に立つと、「仕様にそう書いてあるから従う」というだけでは足りません。なぜそこまで細かく書かれているのか、なぜ版で止めずに更新し続けるのか、なぜ実装者の現実が強く反映されるのかまで見えてきます。HTML は、合意形成の過程そのものを内部に抱えた技術です。

23.4 HTML を決める仕組みも、HTML の性格を映している

ここで押さえたいのは、WHATWG と W3C の関係を制度豆知識として覚えることではありません。HTML を決める仕組み自体が、HTML という技術の性格をよく表しているということです。つまり、閉じた場で完成品を決めて配るのではなく、壊せない既存 Web と、新しく出てくる要求のあいだを調整し続ける。その運用の形が、Living Standard です。

そう考えると、HTML が今も生きている理由も見えやすくなります。完成して終わる技術ではなく、公開されたまま調整され続ける技術だからです。第7部では、その HTML がなぜ長生きし、誰に読まれ、どこへ向かうのかを見ます。

参考資料

第6部 演習

  1. Tim Berners-Lee(ティム・バーナーズ=リー)が残したものを HTML 以外も含めて説明してください。
  2. ブラウザ戦争が標準化の必要性を強めた理由を 3 点に分けて書いてください。
  3. WHATWG の Living Standard という仕組みは、なぜ HTML に向いていますか。

第7部 なぜHTMLは今も生きているのか

第7部の役割は、本書全体の締めくくりとして、HTML が今も使われ続けている理由と、これからの変化の仕方を考えることです。前の各部で見てきた歴史、実装、標準化、議論を一つに束ねます。

第24章では HTML を読む主体の広さを確認します。第25章では長寿の理由を、後方互換性・公開性・単純さから整理します。第26章では HTML が「完成する技術」ではなく、更新され続ける技術であることを示して閉じます。

第24章 HTMLは誰に読まれているのか

この章では、HTML を「ブラウザに表示させるための記述」とだけ見るのではなく、複数の読み手に向けた共通の文書形式として見ます。ゴールは、HTML の相手が人間の目だけではないことを理解し、なぜ見た目が合っているだけでは不十分なのかを説明できるようになることです。

前章では、HTML が実装者や標準化団体によって運用され続ける仕様だと見ました。この章では、その仕様がなぜ細かく整えられ続けるのかを、HTML を読む側の広さから見ます。次章では、その広さが HTML の長寿にどうつながるかを扱います。

24.1 ブラウザは代表的な読み手にすぎない

HTML を最初に思い浮かべるとき、多くの人はブラウザ画面を想像します。それは自然です。実際、ブラウザは HTML の主要な読み手です。しかし HTML を受け取るのはブラウザだけではありません。検索エンジンは文書構造から内容を推定し、スクリーンリーダーは見出しやランドマークを頼りに移動経路を作り、SNS やチャットツールはメタデータを読んでカード表示を組み立てます。スクリーンリーダーは、画面の内容を音声などで読み上げる支援技術です。ランドマークは、navmain のようにページの大きな領域を示す手がかりだと思えば十分です。メタデータは、ページの題名や概要のような補助情報です。

さらに、翻訳システム、保存サービス、アーカイブツール、リーダーモードのような機能も HTML を読みます。リーダーモードは、記事本文を読みやすく抜き出して表示する機能です。ここで共通しているのは、どの相手も見た目そのものではなく、文書の構造や意味の手がかりを受け取っていることです。つまり HTML は、ひとつの画面を出すための材料である前に、多数の相手が解釈する共通文書です。第1章で HTML をプログラミング言語ではなく文書構造の記述だと見た意味も、ここで活きてきます。

1 つの HTML 文書を、ブラウザ・検索エンジン・スクリーンリーダー・SNS のカード生成・翻訳や保存ツールがそれぞれ構造から読む様子の図
図 24-1 HTML を読むのはブラウザだけではない。

24.2 見た目だけ合っていても、同じ文書にはならない

この事実は、HTML を単なる見た目の足場として扱う危うさを示します。たとえば、ブラウザ画面ではそれらしく見えていても、見出し構造が崩れていたり、表に見えるものが実際には div の並びだったりすると、別の読み手には同じ文書として届きません。

検索エンジンは文書の主題や階層を読み取りにくくなり、スクリーンリーダー利用者はどこへ飛べばよいかを掴みにくくなります。SNS のカード生成もうまく要約できないかもしれません。つまり「画面として見える」ことと、「文書として伝わる」ことは同じではありません。

ここで問われているのは、HTML が正しいかどうかをテストの正誤で裁くことではありません。どの読み手に、どの構造が渡るのかという問題です。HTML の意味づけは、ブラウザの装飾前にある土台として、多数の利用者へ共有されています。

24.3 HTML は人間の目の裏側にある共通言語である

本書のここまでの議論が「なぜ HTML に意味が必要なのか」へ収束してきたのはそのためです。table div b strong のような議論も、単に好みの問題ではなく、どの読み手に何を渡すのかという問題でした。

HTML は、人間が見る画面の裏側で、多数の読み手に向けて意味を配る共通言語です。だからこそ、古く見える文法や、仕様書の細かな規定が今も役割を持ち続けます。見た目だけで完結する技術なら、ここまで長く互換性や意味づけが議論される理由はありません。

24.4 読み手の多さが、HTML のしぶとさを支えている

この章で言いたいのは、「HTML は検索エンジンにも読まれる」といった雑学ではありません。HTML が長く生きているのは、多数の読み手が同じ文書をそれぞれの目的で使っているからでもあります。ブラウザのためだけの技術なら、もっと別の形式へ置き換わっていたかもしれません。

しかし実際には、表示、検索、読み上げ、引用、保存、要約といった多くの処理が HTML を土台にしています。だから HTML は、古いのに消えないのではなく、多数の読み手のあいだで今も役に立っているから残っているのです。第25章では、そのしぶとさを、後方互換性、オープン性、シンプルさの観点から見ます。

参考資料

第25章 HTMLはなぜ長生きなのか

この章では、HTML が単に古いのに残っているのではなく、なぜ今も基盤として生き残っているのかを見ます。ゴールは、「昔からあるから残った」という説明で済ませず、後方互換性、オープン性、シンプルさがどう噛み合って長寿を支えたのかを説明できるようになることです。

前章では、HTML がブラウザだけでなく多数の読み手に解釈される文書形式だと見ました。この章では、その共通文書がなぜ置き換えられずに残ってきたのかを扱います。次の最終章では、そうした長寿のうえで HTML がどこへ向かうのかを見ます。

25.1 古い文書を捨てないことが Web の資産になった

第一の理由は、後方互換性です。昔の文書をいまもある程度読めることが、Web を単なる配信手段ではなく、巨大な公共アーカイブにしました。数年前のページだけでなく、もっと古い文書まで参照し続けられることは、利用者にとっても、著者にとっても、実装者にとっても大きな価値です。

もちろん、その代償としてブラウザは古い挙動まで面倒を見る必要を負います。本書の前半で見たエラー回復や互換性重視の姿勢は、まさにその表れでした。それでも Web がここまで巨大になれたのは、昨日のページも十年前のページも、なるべく捨てずにつなぎ止めてきたからです。

ここで重要なのは、後方互換性が単なる保守性ではないことです。古いものを守ること自体が、新しい利用者を呼び込み、引用や参照を積み上げ、Web 全体の価値を増やしてきました。HTML の長寿は、過去を切り捨てなかったことの結果でもあります。

25.2 開かれていたから、誰か一社の都合で終わらなかった

第二の理由は、オープン性です。HTML は特定企業だけが実装できる閉じた形式ではありませんでした。仕様が公開され、複数のブラウザやツールが実装し、周辺の開発者も参加できる。この条件があったからこそ、たとえ一社が失速しても、Web 全体までは止まりません。

第21章から第23章で見たように、Web は最初から公開された土台として始まり、競争の混乱を経て、継続的な標準化の形を整えてきました。この公開性は、きれいな理念というだけでなく、長期的に見たときの生存条件でもありました。複数の実装者が参加できたからこそ、古い文書を読み続ける責任も一社に閉じずに持ちこたえられました。閉じた形式なら、製品の寿命と一緒に消えていたかもしれません。

25.3 中心が比較的単純だったから、周辺の変化を吸収できた

第三の理由は、シンプルさです。もちろん、現在の HTML 仕様書はまったく単純ではありません。パーサー、互換性、詳細な規則まで含めれば巨大です。それでも中心にあるのは、文書構造を記述するという比較的単純な役割です。

この中心が保たれていたからこそ、周辺の技術が大きく変わっても HTML は残れました。CSS が伸び、JavaScript が伸び、フレームワークが入れ替わっても、最終的に多くの UI は HTML に落ちます。HTML が長生きするということは、周辺の技術変化を吸収する共通基盤が残り続けるということでもあります。

25.4 長寿は美しさではなく、使われ続ける条件の積み重ねだった

HTML は完璧だから生き残ったのではありません。むしろ不格好な部分を抱えたまま、壊さず、開き続け、中心を保ち、利用者を増やしてきたから生き残りました。この長寿は、美しい設計だけでは得られない種類の強さです。

つまり HTML の長寿は、後方互換性、オープン性、シンプルさがばらばらに働いたのではなく、互いに支え合ってきた結果です。古い文書を捨てず、誰でも実装でき、周辺の変化を吸収できる。だから HTML は、古い技術なのに残ったのではなく、残る条件を備えていた技術だと言えます。最終章では、その HTML がこれからも完成せず、どこへ向かっていくのかを見ます。

参考資料

第26章 HTMLはどこへ向かうのか

この章では、HTML の未来を新機能予想の一覧としてではなく、完成しない仕様がどのように進み続けるのかという形で見ます。ゴールは、HTML を「古いが残っている技術」から、「今も調整され続ける公共基盤」として見直すことです。

前章では、HTML がなぜ長生きしたのかを、後方互換性、オープン性、シンプルさの観点から見ました。この最終章では、その長寿がどのような未来の持ち方を可能にしているのかを扱います。ここで説明するのは個別機能の予想ではなく、変化の様式です。

26.1 HTML は完成を目指すより、調整を続ける

HTML は Living Standard として少しずつ更新され続けます。大きく一気に作り直されるのではなく、実装と利用実態に合わせて手当てされる。この進み方は派手ではありませんが、壊せない基盤としてはかなり合理的です。完成を宣言するより、継続的な保守と調整を前提にしたほうが Web の現実に合っています。

この本で見てきた補完、エラー回復、互換性、再定義、標準化の仕組みは、どれも「完成した仕様を守る」というより、「壊さずに調整し続ける」という性格の表れでした。HTML は、ある日きれいに作り直されるより、現実に合わせて少しずつ直され続けるほうが自然な技術です。

26.2 未来は革命より、接続と手当ての積み重ねになる

今後も HTML は、アクセシビリティ、フォーム、埋め込み、周辺 API との接続といった領域で変わり続けるでしょう。ただし、その変化の多くは「新しい HTML を別に作る」ことではなく、既存の基盤へどう接続し、どこを手当てし、何を明確化するかという形で起きます。

これは目立たない変化に見えますが、Web の規模を考えれば必然です。世界中の文書、ツール、ブラウザ、利用者が同じ基盤の上に乗っている以上、劇的な断絶より、小さな調整の積み重ねのほうが現実的です。HTML の未来が派手な革命に見えにくいのは、停滞しているからではなく、壊せないものを変えているからです。

26.3 変わり続けること自体が、HTML の一貫した性格である

本書で見てきた奇妙さの多くは、場当たり的な混乱の跡であると同時に、適応の痕跡でもありました。tbody の自動挿入も、p の自動終了も、古い要素の再定義も、Living Standard も、全部ばらばらの話ではありません。壊せない過去と、変わり続ける現在のあいだで折り合いをつける方法でした。

だから HTML の未来を考えるとき、次に何のタグが増えるか よりも、これからもどう折り合いをつけ続けるのか を見るほうが本質に近い。HTML は完成したから生きているのではなく、完成しないまま調整され続けることで生きています。

26.4 HTML は変な技術ではなく、筋の通った公共基盤だった

この本の出発点は、HTML の不思議を「変だから面白い」で終えないことでした。ここまで読んできて、もし HTML が偶然の寄せ集めではなく、公開性、互換性、実装、利用者の現実のあいだで折り合いをつけてきた技術だと見えたなら、本書の役割は果たせています。

HTML は変な技術だった、ではなく、変わり続ける公共基盤だった。しかも、その変化には一応の筋があった。そう捉え直せるなら、これから HTML を見るとき、何が追加されたかだけでなく、なぜその変化がその形で起きたのかも一緒に見えるはずです。

参考資料

第7部 演習

  1. HTML を読む主体を 4 つ挙げ、それぞれが何を読み取るか説明してください。
  2. HTML が長生きしている理由を、後方互換性・公開性・単純さの 3 点からまとめてください。
  3. HTML の未来を「革命」より「継続的な調整」として捉えるべき理由を述べてください。

付録

付録では、本編を読み終えたあとに振り返りやすい形で情報を再構成します。本編の代わりになる要約ではなく、本編の理解を助ける補助線として使ってください。

  • 付録A は会話の種になる短い雑学集です。
  • 付録B は人名の一覧ではなく、HTML の歴史のどこで何を担ったかを短くまとめます。
  • 付録C は広まりやすい言説を、どこまで本当でどこから雑かという観点で整理します。
  • 付録D は、本編の筋からは外れるけれど知ると面白い「深掘り雑学」を集めた番外編です。

付録A 明日話したくなるHTML雑学50

ただ並べても面白くないので、テーマごとにまとめました。気になった番号から、本編のどの章につながるかを探してみてください。どれも「へぇ」と言われる側になれるネタです。

ブラウザの中で起きていること

書いたものと、ブラウザが実際に扱うものは違う、という話。

  1. tbody は書かなくても DOM に現れる。
  2. html head body は省略しても補完される。
  3. p は文脈しだいで勝手に閉じる。
  4. <table> の直下に書いたテキストは、表の中ではなく表の前へ飛ばされる(foster parenting)。
  5. View Source と DevTools は、同じページの違う段階を見ている。
  6. だから table > tr という CSS は、たいてい空振りする。
  7. HTML 仕様書のかなりの部分は、人間向けの説明ではなくパーサーの規則。

HTML という言語の正体

そもそも HTML は何をする言語なのか。

  1. HTML はプログラミング言語ではない(iffor もない)。
  2. それでも Web の基盤になれたのは、読み手が多かったから。
  3. HTML は URL・HTTP と分業して、はじめて Web になる。
  4. HTML が重視したのは、完成した紙面より「接続された文書」。
  5. ブラウザは壊れた入力でも止まらず、回復して読み進める。
  6. それは甘さではなく、閲覧を止めないための設計。

省略と空要素のからくり

短く書けるのには、ちゃんと理由と条件がある。

  1. img は最初から子を持たない「空要素」。閉じ忘れではない。
  2. brhr も空要素。
  3. <img />/ は HTML では無視される。でも SVG / MathML では本当に効く。
  4. ブール属性(disabled など)は値を書かなくても成立する。
  5. しかし disabled="false" と書いても、無効化は解除されない。
  6. 引用符の省略には、かなり狭い条件がある。
  7. 属性やタグの省略可能性は、HTML の祖先 SGML の名残。
  8. コメントの中にも、書いてはいけない並びがある。

歴史のひとこま

いまの HTML は、たくさんの偶然と現場の都合でできている。

  1. 世界初の Web サイト info.cern.ch は、今も見られる。
  2. 1989 年の Web 提案書に、上司は「Vague but exciting」と書き込んだ。
  3. 最初の Web サーバーになった NeXT には「電源を切るな」の貼り紙があった。
  4. img タグは 1993 年にマーク・アンドリーセンが提案した。
  5. Netscape の <blink> は一晩で実装され、のちに削除された。
  6. 文字を流す <marquee> は Internet Explorer の独自タグだった。
  7. かつてはコメント <!--[if IE]> が、IE 専用の分岐に使われていた。
  8. spacer.gif(1×1 の透明画像)でレイアウトを整えた時代があった。
  9. fontcenter は obsolete だが、当時の需要は本物だった。
  10. obsolete は「なかったこと」ではなく、歴史の層として残る。

標準化のドラマ

HTML は、誰かが一度決めて終わり、ではない。

  1. XHTML は厳格さを目指したが、Web の現実と衝突した。
  2. XML の「壊れたら止める」は、公開 Web には重すぎた。
  3. XHTML 2.0 は打ち切られ、現実路線の HTML5 が後継になった。
  4. <!DOCTYPE html> の唯一の仕事は、Quirks Mode を切ること。
  5. Quirks Mode は、古いページを壊さないために今も残っている。
  6. WHATWG の HTML は、版で止まらない Living Standard。
  7. W3C と WHATWG は 2019 年に HTML 標準を一本化した。
  8. ブラウザ戦争の混乱が、標準化の必要性を強くした。

HTML を読むのは誰か

HTML は、人間の目だけのためにあるのではない。

  1. HTML の読者は、ブラウザだけではない。
  2. 検索エンジンも HTML の構造を読む。
  3. スクリーンリーダーも HTML の意味づけに依存する。
  4. alt は飾りではなく、目で見ない読み手にとっての画像の本体。
  5. <details><summary> だけで、JavaScript なしに開閉する UI が作れる。
  6. <script> の中に </script> と書くと、文字列の途中でも壊れる。
  7. & をそのまま書くと、&amp; の始まりと誤解されることがある。
  8. フレームワークが変わっても、最終的に HTML へ落ちることは多い。
  9. HTML は「古い」のではなく「古くても読める」技術。
  10. HTML は完成しない仕様。これからも調整され続ける。
  11. HTML の奇妙さの多くには、ちゃんと歴史的な理由がある。

付録B HTML 人物列伝

HTML は、一人の天才が完成させたものではありません。ここでは形を決めた数人を、肩書きではなく「結局、何をした人なのか」で短く紹介します。

Tim Berners-Lee(ティム・バーナーズ=リー) — Web を「無料の公共物」にした人

1989 年、CERN の研究者だったバーナーズ=リーは、組織内の情報がつながらない不便さを解こうと、一枚の提案書を書きました。上司のマイク・センドールは、その表紙に「Vague but exciting...(曖昧だが、わくわくする)」と走り書きしました。却下ではなく、ゴーサインです。

最初の Web サーバーは、彼の NeXT コンピュータ 1 台でした。本体には「This machine is a server. DO NOT POWER IT DOWN!!(これはサーバーです。電源を切らないこと)」という貼り紙。誰かがうっかり電源を切れば、世界にひとつしかない Web が止まったのです。

ただ、本書の文脈で何より大きいのは、彼が Web を特定企業の製品にしなかったことです。HTML・URL・HTTP は公開された約束として設計され、のちに CERN はこの技術を誰でも自由に使える形で手放しました。Web が一社の所有物にならなかった出発点は、ここにあります。

Ian Hickson(イアン・ヒクソン) — 「現実」を仕様に書き写した人

通称 Hixie。HTML5、そして版で止まらない HTML Living Standard の編集を長く担いました。彼の仕事を一言でいえば、理想の文法を空想で書くのではなく、実際のブラウザがどう振る舞っているかを徹底的に調べ、それを仕様の言葉へ書き写したことです。本書で繰り返し出てきた「壊れた入力をどう回復するか」の細かな規則は、この姿勢の産物です。

彼はまた、ブラウザの表示が仕様どおりかを試す有名なテストページ Acid2・Acid3 を作ったことでも知られます。仕様を書くだけでなく、実装が仕様に追いついているかを測る物差しまで用意した人でした。

Håkon Wium Lie(ホーコン・ウィウム・リー) — 見た目を HTML から追い出した人

1994 年、やはり CERN にいたリーは、文書の見た目を HTML 本体から切り離す仕組み——CSS を提案しました。fontcenter のように見た目を要素へ埋め込む流れに対して、「構造は HTML、見た目は別の言語」という分担を現実の仕組みにした人です。本書では主役ではありませんが、彼の提案がなければ、HTML はもっと見た目の都合で濁った言語になっていたはずです。のちに Web ブラウザ Opera の CTO も務めました。


3 人に共通するのは、HTML を「自分の作品」として囲い込まなかったことです。公開し、現実に合わせ、役割を分ける。本書で見てきた HTML の性格は、こうした人たちの選択の積み重ねでもあります。

付録C HTML 都市伝説

広く言われているけれど、そのままだと雑——という HTML の「言い伝え」を、判定つきで並べます。多くは半分ホントです。なぜ半分なのかが分かると、HTML の見え方が変わります。

h1 はページに 1 個だけ」 — 判定: 半分ホント

大見出しを 1 つに保つ設計は自然で、編集上の助言としては有効です。でも仕様の絶対規則ではありません。本当に問うべきは個数ではなく、見出し階層が論理的かどうか。「2 個書いたら違反」は言いすぎです。(→ 第17章)

table は使うな」 — 判定: ウソ

批判されたのは、ページ全体を表で組むレイアウト用途の乱用です。料金表や比較表のようなデータの表には、table がいまも最適。要素そのものに罪はなく、用途を取り違えていただけです。(→ 第18章)

div は悪」 — 判定: ウソ

意味のある要素で置けるところまで div にするのは問題ですが、汎用コンテナとしての div は必要です。悪いのは要素名ではなく、意味を渡せる場所まで全部ただの箱にしてしまうこと。(→ 第19章)

b タグはもう使うな」 — 判定: 単純すぎ

b は削除されず、HTML5 で意味を持つ要素として再定義されました。強い重要性を表す strong とは役割が違い、使いどころもあります。標語だけでは足りません。(→ 第20章)

alt は画像のおまけ」 — 判定: ウソ

alt は「画像が出ないときの代わりの文字」だけではありません。目で見ない読み手(スクリーンリーダーや検索エンジン)にとっては、それが画像の本体です。おまけどころか、画像の意味そのものを運んでいます。(→ 第24章)

<!DOCTYPE html> は書式の宣言」 — 判定: ほぼウソ

いまの DOCTYPE は、文書型を宣言する仕事をほとんど失っています。唯一の役目は、ブラウザを Quirks Mode(互換モード)に入れないこと。実体はスイッチであって、宣言ではありません。(→ 付録D)

「HTML は簡単」 — 判定: 入口だけホント

書き始めるのは簡単です。でも互換性、パース、エラー回復、仕様、支援技術まで含めると、背後はかなり深い。本書で見てきた「変な仕様」の数々は、その深さが表に出たものです。簡単に書けることと、単純な技術であることは別です。

付録D 番外編 もっと深い HTML 雑学

本編に入れると話の筋から外れてしまうけれど、知ると HTML がもっと面白くなる「深掘り雑学」を集めました。どれも、現在のブラウザで実際に確かめられます。

なぜ <!DOCTYPE html> と書くのか

HTML ファイルの先頭にある <!DOCTYPE html>。多くの人は「おまじない」として書いていますが、これにはちゃんと理由があります。しかも、見た目より変な事情を抱えています。

まず、この行はもう「文書型の宣言」としてはほとんど意味を持っていません。HTML5 では、<!DOCTYPE html> の唯一の仕事は、ブラウザを Quirks Mode(互換モード)に入れないことです。

昔の DOCTYPE は、こんなに長いものでした。

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">

誰も覚えられないので、みんなコピペしていました。HTML5 はこれを <!DOCTYPE html> まで短くしました。中身を理解させることをあきらめ、「Quirks Mode を切るスイッチ」と割り切ったのです。

では、DOCTYPE を書き忘れるとどうなるのか。ブラウザは Quirks Mode に入り、1990 年代の挙動をわざと再現します。とくに有名なのが箱モデルの違いで、Quirks Mode では width に指定した値の中に padding と border が含まれてしまいます。同じ CSS なのに、DOCTYPE の有無だけでレイアウトが静かにずれる——これが昔の Web 制作者を苦しめました。

ちなみにモードは 2 つではなく、<!DOCTYPE html> の「標準モード」、何もない「Quirks Mode」、その中間の「Limited-Quirks(ほぼ標準)モード」の 3 つがあります。<!DOCTYPE html> という短い呪文は、スキーマの宣言ではなく、互換性のスイッチだったわけです。

</script> は文字列の中でも効いてしまう

script 要素の中身は、HTML パーサーにとって「生テキスト」です。パーサーは JavaScript の文法を理解しているわけではなく、最初に現れた </script> を見つけた瞬間にスクリプトの終わりだと判断します。

だから、次のコードは壊れます。

<script>
  document.write("</script>");
</script>

人間には「</script> は文字列の中身」だと分かりますが、パーサーは文字列の途中でもおかまいなしに、最初の </script> でスクリプトを閉じてしまいます。回避するには、終了タグに見えないように書きます。

<script>
  document.write("<\/script>");
</script>

<\/script>\/ は JavaScript では / と同じ意味なので、動作は変わりません。それでいて、HTML パーサーには </script> として見えなくなります。

& を書くだけでは & と表示されないことがある

HTML で & は、特別な文字です。&文字参照の始まりとして扱われるため、&amp; と書いてはじめて画面に & が出ます。同じように <&lt;>&gt;、改行しない空白は &nbsp;、著作権マークは &copy;(©)で表します。

面白いのは、一部の古い文字参照はセミコロンを付け忘れても表示されることです。たとえば &copy とだけ書いても、多くのブラウザは © を出します。ただしこれは互換性のための救済で、仕様上は parse error(問題のある入力)です。&copy; と正しく書くのが本筋です。

URL を書くときも要注意です。?a=1&b=2 をそのまま属性値に書くと、&b が文字参照と解釈されかねません。HTML としては ?a=1&amp;b=2 と書くのが正確です。

<table> の直下に書いたテキストは表の外へ飛ぶ

第5章で、表は行グループの入れ子構造だと見ました。では、その構造を無視して、table の直下にいきなりテキストを書いたらどうなるでしょうか。

<table>おっと<tr><td>A</td></tr></table>

直感的には「table の中に "おっと" がある」と思いたくなります。ところが DevTools で DOM を見ると、こうなります。

おっと
<table>
  <tbody>
    <tr><td>A</td></tr>
  </tbody>
</table>

"おっと" は表の中ではなく、表の前へ追い出されます。 これは foster parenting(里親付け) と呼ばれる、HTML パーサーの正式な動作です。表の中に置けないものが来たとき、パーサーはそれを捨てず、表の直前へ「里子に出す」のです。

table の直下に書いたテキストが、DOM では table の中ではなく table の直前へ移動する様子の図
図 D-1 表の中に置けないテキストは、表の前へ追い出される。

第4章から第7章で見た補完やエラー回復は、ふわっとした「親切」ではなく、こうした名前の付いた規則(パーサーの挿入モードという状態機械)の集まりでした。foster parenting は、その機械じかけがいちばん見えやすい瞬間です。手元のブラウザで、ぜひ DevTools を開いて確かめてみてください。

文字コードを間違えると、文字が化ける

ブラウザは、HTML を読み始める時点では「この文書が何の文字コードで書かれているか」を完全には知りません。だから <meta charset="utf-8"> で教えてあげます。これは飾りではなく、<head> のなるべく早い位置に置く必要があります。指定が遅れると、ブラウザはいったん読んだ分を別の文字コードで読み直すことになるからです。

この指定を忘れたり間違えたりすると、日本語が「譁・喧縺・」のように化けます。かつての Web では、この文字化けは日常の風景でした。charset は、その地獄を防ぐための短い一行です。

半角スペースをいくら並べても、1 個にまとめられる

HTML の本文では、連続した空白(スペース・タブ・改行)は、表示されるときに1 個の空白へ畳み込まれます

<p>あ        い</p>

これを開いても、「あ」と「い」のあいだは 1 文字分しか空きません。スペースを並べて余白を作ろうとしても効かないのは、このためです(<pre> 要素や CSS の white-space を使えば別です)。HTML は、ソースの見た目の空白と、表示上の空白を、わざと切り離しています。

<template> の中身は、DOM にいるのにいない

<template> 要素は、変わり種です。中に書いた HTML はパースはされるのに、画面には出ず、通常の DOM ツリーにも入りません。中の img は読み込まれず、script も動きません。JavaScript から template.content を取り出して複製したときに、はじめて本物の DOM として動き出します。「書いてあるのに、まだ存在していない」——UI の雛形を安全に持っておくための、静かな仕掛けです。

どんな要素も、その場で編集可能にできる

要素に contenteditable を付けると、その部分はブラウザ上で直接書き換えられるようになります。

<p contenteditable>ここをクリックして書き換えてみてください。</p>

メモアプリのような編集欄を、textarea を使わずに作れます。ちなみに、開発者ツールのコンソールで document.designMode = "on" と打つと、いま開いているどんなサイトでもその場で文字を書き換えられます(リロードで元に戻ります)。HTML が「読む専用」ではないことを、いちばん手軽に体験できる小ネタです。

参考資料

あとがき

HTML は、学び始めると簡単に見え、深く見ようとすると急に歴史と実装の重さが現れる技術です。本書では、その奇妙さを笑うのではなく、理由を追いかけることを目指しました。

もし読み終えたあとに、ブラウザの補完や古い要素や仕様書の長さを見て「雑だから」ではなく「そうせざるをえなかった歴史がある」と思えるなら、この本の役目は果たせています。HTML は地味ですが、Web 全体の前提を今も支えている技術です。

FjordBootCamp について

FjordBootCamp は、現役エンジニアが運営するオンラインのプログラミングスクールです。Rails エンジニアコースとフロントエンドエンジニアコースがあり、文法や答えを暗記するより、調べながら理解し、自分で考えて学び続ける力を重視しています。

本書で扱った HTML の見方も、その姿勢とつながっています。特定のタグや通説を覚えて終わるのではなく、背景、仕様、実装を踏まえて「なぜそうなったのか」を考える。その習慣は、HTML 以外の技術を学ぶときにも役立ちます。

FjordBootCamp について詳しくは、公式サイトを参照してください。