HTML5のアウトラインを理解する方法

## はじめに

何年前に読んだか記憶にないくらい昔「[HTMLのアウトライン意識してますか？ - QiitaのSEO事情](https://qiita.com/yuku_t/items/726a67d8ae74eea2540a)」を読みましたが「[HTMLのアウトライン 何もわからない](https://qiita.com/Andhy/items/9bcbbb6426a227f4c132)」でした。

分からないことが何年も気になっていました。最近になってHTMLが分かるようになってきました。HTMLのアウトラインが分かるのではないかと思ってHTML仕様書などを見て学習しました。学習を通して多くのことを学べました。

## アウトラインを理解する方法

アウトラインを理解する方法は、支援ツールを使ってHTML Living Standardにあるアウトラインのサンプルを確認し、[アウトラインの構造を決める要素](#アウトラインの構造を決める要素)の位置を見て学習することです。

[7つのサンプルを動かした感想](#7つのサンプルを動かした感想)や[HTML5の廃止について調べよう](#html5の廃止について調べよう)も学習に役立つと思います。

ここまでやれば基本が分かると思います。基本が分かればアウトラインの理解が自然と進んでいくと思います。

### 支援ツールを使おう

HTML5のアウトラインは直感的な結果になりません。

> Mixing both the `h1`–`h6` model and the `section`/`h1` model can lead to some unintuitive results.
>
> `h1`-`h6` モデルと `section`/`h1` モデルの混在は直感的でない結果になることがあります。
>
> [HTML Living StandardのSample outlines](https://html.spec.whatwg.org/multipage/sections.html#sample-outlines)

支援ツールの助けを借りなければHTML5のアウトラインを理解できないと思います。

3つの支援ツールを見つけました。

#### 拡張機能のHeadingsMap

最もおすすめしたいのが[Chrome拡張機能のHeadingsMap](https://chrome.google.com/webstore/detail/headingsmap/flbjommegcjonpdmenkdiocclhjacmbi)です。

アイコンをクリックすると左側に2つのタブが表示されます。

HTML5 Outlineのタブをクリックしましょう。



HTML文書の構造は2通りの方法で解釈できます。表示される2つのタブはHTML5 OutlineとHeaders Structureです。

HTML5 Outlineとは[アウトラインの構造を決める要素](#アウトラインの構造を決める要素)によって決められたアウトラインです。

Headers Structureは見出し要素だけによって決められた文書構造です。

#### 拡張機能のHTML5 Outliner

もう一つに[Chrome拡張機能のHTML5 Outliner](https://chrome.google.com/webstore/detail/html5-outliner/afoibpobokebhgfnknfndkgemglggomo)があります。

この拡張機能はHTML5 Outlineを表示します。2つの文書構造を表示できるHeadingsMapのほうが高機能です。

HTML5 Outlinerは[アウトラインのアルゴリズムのソースコード](https://github.com/h5o/h5o-js)を公開しています。

#### W3Cの検証サービス

Webで提供されている[W3Cの検証サービス](https://validator.w3.org/)があります。

Show Outlineにチェックを付けましょう。



> 403 Forbidden
> Request forbidden by administrative rules.

W3Cは仕様を決める側の組織です。アウトラインの結果を最も信頼できますが、現在エラーが出てほとんどアクセスできませんでした。

### アウトラインの構造を決める要素

[HTML Living StandardのCreating an outline](https://html.spec.whatwg.org/multipage/sections.html#outlines)やHTML5 Outlinerのソースコードでアウトラインのアルゴリズムを確認できますが、見ても分かりませんでした。

大事なことはアウトラインのアルゴリズムが、次の3種類の要素だけを見て構造を決めていることです。これだけ分かれば十分だと思います。

- Sectioning content (article, aside, nav, section)
- Sectioning root (blockquote, body, details, dialog, fieldset, figure, td)
- Heading content (h1, h2, h3, h4, h5, h6, hgroup)

3種類の要素の位置と支援ツールの結果を見比べてHTML5のアウトラインを理解しましょう。



> Sectioning content is content that defines the scope of headings and footers.
>
> [HTML Living StandardのSectioning content](https://html.spec.whatwg.org/multipage/dom.html#sectioning-content-2)

Sectioning contentは見出しの範囲を定義するコンテンツです。



> Certain elements are said to be sectioning roots, including blockquote and td elements. These elements can have their own outlines, but the sections and headings inside these elements do not contribute to the outlines of their ancestors.
>
> [HTML Living StandardのSectioning root](https://html.spec.whatwg.org/multipage/sections.html#sectioning-root)

Sectioning rootは独自のアウトラインを持ちます。Sectioning rootの中のセクションと見出しは、そのSectioning rootの祖先のアウトラインに寄与しません。



最上階層のディレクトリやフォルダのことをルートと呼びますが、Sectioning rootのrootは最上階層のことだと思います。

### アウトラインのサンプルを確認しよう

[HTML Living Standardのアウトラインのサンプル](https://html.spec.whatwg.org/multipage/sections.html#sample-outlines)を動かして支援ツールの結果を見ましょう。実際に手を動かしたほうが理解しやすいです。

#### 7つのサンプルを動かした感想

##### 1つめのサンプル

`<article>`と`<aside>`、`<nav>`、`<section>`を使わなければHeaders StructureとHTML5 Outlineが一致するようです。

##### 2つめのサンプル

最初の`<h1>`が大枠であるdocumentに吸い込まれました。

`<section>`ごとに見出し要素を置き、他の見出し要素がその`<section>`に吸い込まれました。

##### 3つめのサンプル

`<h1>`をトップレベルに複数置けます。

最初の`<h1>`が大枠であるdocumentに吸い込まれ、2つめ以降の`<h1>`がdocumentに吸い込まれず、トップレベルに置かれました。



> `<h1>`は複数使用可能 ~~（ただし `<section>`も併用すること）~~
>
> [どうしてHTML5が廃止されたのか | フューチャー技術ブログ、のHTML5 と HTML Living Standardの違い](https://future-architect.github.io/articles/20210621a/#HTML5-と-HTML-Living-Standardの違い)

HTML5が廃止されてHTML Living Standardになったときの違いとして`<h1>`が複数使用可能になったことをこのページが上げられました。前の仕様では`<h1>`を複数使用できなかったと思われます。

HTML Living Standardのサンプルが`<section>`を併用していないので取り消し線を引かせていただきました。

##### 4つめのサンプル

> Mixing both the `h1`–`h6` model and the `section`/`h1` model can lead to some unintuitive results.

`<section>`の中にあるはずの見出し要素が`<section>`の外に出て直感的でありません。

`<section>`に吸い込まれた見出し`<h1>`よりも下位ランクの見出し`<h2>`にすれば`<section>`の外に出ないようです。

##### 5つめのサンプル

3つめのサンプルと同様に、2つめの`<h1>`が大枠であるdocumentに吸い込まれず、トップレベルに置かれました。

##### 6つめのサンプル

```html
<h1>Ray's blog</h1>
<article>
 <header>
  <nav>
   <a href="?t=-1d">Yesterday</a>;
  </nav>
  <h1>We're adopting a child!</h1>
 </header>
 <p>Janine and I have signed the papers to become the proud parents of baby.</p>
</article>
```

見出し要素`<h1>` が `<article>` の中にあるのに `<article>` の外に出てしまいました。

段落要素`<p>` が `<article>` の中にあるのに `<article>` の管轄下になく、見出し要素`<h1>`の管轄下にあります。

##### 7つめのサンプル

`<hgroup>`は中にある最初の見出しのランクと同様の扱いになるようです。

HeadingsMapの結果がHTML5 OutlinerやW3Cの検証サービスの結果と異なりました。HeadingsMapは`<hgroup>`に対応していないようです。

### HTML5の廃止について調べよう

HTMLの仕様が決まるまでの背景を知っておくことはHTML5のアウトラインを理解するときに役立ちます。

「HTML5 廃止」でGoogle検索しましょう。廃止の経緯や、組織の歴史が分かると思います。

#### W3CとWHATWG

はじめはW3CがHTMLの仕様を決めていましたが、AppleとMozillaとGoogleとMicrosoftが参加するWHATWGという対抗組織がHTML5を廃止させHTML Living StandardというHTML仕様に統一したようです。

#### HTML Living StandardはHTML5か？

> Is this HTML5?
> In short: Yes.
>
> In more length: the term "HTML5" is widely used as a buzzword to refer to modern web technologies, many of which (though by no means all) are developed at the WHATWG. This document is one such; others are available from the WHATWG Standards overview.
>
> [HTML Living StandardのIs this HTML5?](https://html.spec.whatwg.org/multipage/introduction.html#is-this-html5?)

HTML5が廃止されましたが、簡単に言うとHTML Living StandardはHTML5です。HTML5とは広く使われたバズワード（流行語）で最新のWeb技術のことです。



HTML5の廃止とはW3CからWHATWGへとHTML仕様を決める主導権が移ったことだと思います。

## アウトラインの書き方

### アウトラインを書けない場合

思ったようにHTML5のアウトラインを書けない場合に遭遇すると思います。

どういう場合があったかとその場合の書き方を紹介します。

#### 先にnav要素がある場合

[私のページ](https://querykuma.github.io/)で遭遇したのですが、上部のナビゲーションバーが`<h1>`より先にある場合です。`<nav>`がアウトラインの構造を決める要素ですので`<h1>`より先に置けません。

#### 先にfigure要素がある場合

`<figure>`が`<h1>`より先にある場合です。`<figure>`がアウトラインの構造を決める要素ですので`<h1>`より先に置けません。

#### grid-template-areasによる書き方

```html
<body>
	<h1>h1</h1>
	<nav>nav</nav>
</body>
```

```css
body {
  grid-template-areas:
    'nav'
    'main';
  grid-template-columns: 1fr;
  grid-template-rows   : auto 1fr;
}
h1 {
  grid-area: main;
}
nav {
  grid-area: nav;
}
```

grid-template-areasで順番を変えることにより対応できます。

#### flexのorderによる書き方
```html
<body>
	<h1>h1</h1>
	<figure>
		<img src="画像.jpg" alt="画像">
	</figure>
</body>
```

```css
body {
	display: flex;
}
h1 {
	order: 2;
}
figure {
	order: 1;
}
```

flexのorderで順番を変えることにより対応できます。

### 見出しのないセクションの書き方

`<section>`で囲ったが見出しを表示したくない場合に遭遇すると思います。

> 少数の例外を除いて、セクションには見出しを置いてください。
>
> [`<section>`: 汎用セクション要素 - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Element/section)

見出しを置くように案内されています。

どうすればいいでしょうか？

次のように書けば良いと思います。

> ```html
> <section>
> 	<h2 class="hidden">コントロール</h2>
> 	<button class="reply">返信</button>
> </section>
> ```
>
> ```css
> .hidden {
> 	position: absolute;
> 	top: -9999px;
> 	left: -9999px;
> }
> ```
>
> [`<section>:` 汎用セクション要素 - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/ja/docs/Web/HTML/Element/section)

この書き方が画面リーダーに適した CSS のようです。

### Headers StructureとHTML5 Outlineを一致させるべきか

拡張機能のHeadingsMapで確認できる2つの文書構造を一致させるべきでしょうか？

> Sections may contain headings of any rank, but authors are strongly encouraged to either use only h1 elements, or to use elements of the appropriate rank for the section's nesting level.
>
> `<section>`はどのようなランクの見出しを含んでもいいですが、`<h1>`のみを使うか、`<section>`のネスティングレベルに適したランクの要素を使うことが強く推奨されます。
>
> Authors are also encouraged to explicitly wrap sections in elements of sectioning content, instead of relying on the implicit sections generated by having multiple headings in one element of sectioning content.
>
> また、1つのsectioning contentの要素に複数の見出しがあることによって生成される暗黙的セクションに頼らず、sectioning contentの要素で明示的にセクションを囲むことが推奨されます。
>
> [HTML Living StandardのHeadings and sections](https://html.spec.whatwg.org/multipage/sections.html#headings-and-sections)

引用の前半です。

HTML Living Standardの推奨によれば、一致させても一致させなくても、どちらでもいいようです。

一致させないなら`<h1>`要素のみを使いましょう。



脱線しますが、引用の後半を解説します。

```html
<aside>
	<h2>h2の1つめ</h2>
	<h2>h2の2つめ</h2>
</aside>
```

このように書くとh2の2つめが暗黙的なセクションになって`<aside>`の外に出てしまいます。

```html
<aside>
	<section>
		<h2>h2の1つめ</h2>
	</section>
	<section>
		<h2>h2の2つめ</h2>
	</section>
</aside>
```

明示的に`<section>`で囲みましょう。

## おまけ

### Headers StructureとHTML5 Outlineのどちらで構成されたか？

Headers Structureで構成されたかHTML5 Outlineで構成されたかを調べる方法を説明してみます。

Sectioning content（`<article>`と`<aside>`、`<nav>`、`<section>`）のどれかが使われていればHTML5 Outlineです。

Sectioning contentが1つも使われていなければHeaders Structureです。

[Headers StructureとHTML5 Outlineを一致させるべきか](#headers-structureとhtml5-outlineを一致させるべきか)で解説しましたが、HTML5 Outlineの書き方は2つあります。

`<h1>`のみを使う書き方と`<section>`のネスティングレベルに適したランクの要素を使う書き方です。

どちらでもないなら「HTMLのアウトライン 何もわからない」のにSectioning contentを使ったか、構成を隠しているかです。

### GoogleはいつWHATWGに参加したのか？

[日本語のWikipedia](https://ja.wikipedia.org/wiki/Web_Hypertext_Application_Technology_Working_Group)によるとApple、Mozilla、Operaの開発者たちが2004年にWHATWGを結成し、2017年末にMicrosoftもWHATWGに参加したそうです。

GoogleはいつWHATWGに参加したのでしょうか？

[ドイツ語のWikipedia](https://de.wikipedia.org/wiki/Web_Hypertext_Application_Technology_Working_Group)によるとWHATWGの現在のボスはイアン・ヒックソンのようです。

[イアン・ヒックソンのレジュメ](https://ian.hixie.ch/career/resume.html)によるとイアン・ヒックソンは2005年までにMozillaとNetscape、W3C、Operaに参加後、2005年から現在までGoogleに勤務しているそうです。

[韓国語のWikipedia](https://ko.wikipedia.org/wiki/WHATWG)によると2004年、Apple、Mozilla Foundation、Opera Softwareの個人がWHATWGを設立し、当時WHATWG規格の編集長だったイアン・ヒックソンがOpera SoftwareからGoogleに引っ越したことで、GoogleもWHATWGの一員になったそうです。

[ロシア語のWikipedia](https://ru.wikipedia.org/wiki/WHATWG)によるとWHATWGは、ブラウザ会社(Apple、Mozilla Foundation、Opera Software)の従業員によって2004年に設立され、イアン・ヒックソンが代表を務め、翌年Googleに異動したそうです。

2017年としたWikipediaもありましたが2005年、GoogleがWHATWGに参加したことになると思います。

## さいごに

少し前まで「HTMLのアウトライン 何もわからない」でしたので、まだ分かってないところがあると思います。そのような中でアウトラインを理解する方法を説明してみました。

記事を書く途中に分かってないことが多くあることが分かりました。それらを調べて学習することによって理解を深められました。