HTML の見出し要素をちゃんと知る
まずは仕様を確認。
4.3.6 The h1, h2, h3, h4, h5, and h6 elements - HTML Standard
見出し要素を使用できるコンテキストは以下の2つ
- hgroup 要素の子として
- ヘディングコンテンツが期待される場所
ヘディングコンテンツは、その場所が明示的に <section>
などのセクショニングコンテンツ要素を使用してマークアップされているか否かに関わらずセクションの見出しを定義する。
見出しとアウトラインについて。
- 見出し要素はその数字に対応した見出しレベルを持つ
- 見出しレベルが低いほど、その見出しが持つ祖先セクションの数が少なくなる
- アウトラインとは、文書内のすべての見出しをツリー順に並べたものである
- 文書に1つ以上の見出しがある場合、アウトライン内の少なくとも1つの見出しの見出しレベルは1(
<h1>
)でなければならない - アウトライン内の別の見出しリードに続く各見出しは、リードの見出しレベルよりも小さい、等しい、または1つ大きい見出しレベルを持たなければならない
以下の例は見出しレベルがスキップされているため、仕様に違反している。
<body>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<section>
<h3>Taste</h3>
<p>They taste lovely.</p>
</section>
</body>
1つ大きい見出しレベルを使用して以下のように修正できる。
<body>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<section>
<h2>Taste</h2>
<p>They taste lovely.</p>
</section>
</body>
アウトラインをチェックするために HeadingsMap や HTML5 Outliner などの拡張機能を利用することができる。
<h1>
が存在してもいいのか?
1つのページ内に複数の 仕様上は禁止されていないものの、MDN には「1つのページに複数の <h1>
要素を使用しない」として以下のように述べられている。
1 つのページに複数の
<h1>
要素を使用することは HTML 標準では認められていますが(入れ子でない限り)、これはよい習慣とはみなされません。1 つのページには、ページの内容を説明する 1 つの<h1>
要素(文書の<title>
要素と同様)を置くのが一般的です。
また補足として以下のように述べられている。
メモ: 入れ子になったコンテンツ区分要素の中で複数の <h1> 要素を入れ子にすることは、HTML 標準の古いバージョンでは認められていました。しかし、これはよい習慣とはみなされず、現在は非適合となっています。詳しくは、There Is No Document Outline Algorithm をご覧ください。
アウトラインアルゴリズム刷新に関する一連の動きはHTML のアウトラインアルゴリズムが見出しレベルをベースとしたものに刷新されそう | 富永日記帳に詳しい。
一般論として文書内の <h1> 要素は一つにとどめた方が良いでしょう。
という記述のとおり、よほど特殊な事情がなければページ内の <h1>
は1つであるべきだろう。理想的には <main>
要素の内容を表す最初の子孫要素であることが望ましいと言える。
<h1>
にサイトロゴやブランドロゴを入れるのは適切か?
<h1>
にサイトロゴやブランドロゴを入れることを明確に禁止する仕様や言説は見当たらないが、見出しによって文書のアウトライン(≒ 目次)が形成される、という観点に立つならば、一般論として <h1>
はその文書のタイトルであるべきであると言える。
古い記事だが、Should Your <h1> Tag Be Your Logo?の「見出しは実際に何をするのか?」というセクションでは「サイトの最初の見出しは、あなたのページの内容を最もよく説明するものであるべきです。これがロゴになることもありますが、ほとんどの場合はそうではありません。」として、ロゴを <h1>
にすべきでない具体的な理由を「ユーザビリティ」「アクセシビリティ」「ロボット対策」の3つの側面から述べている。
1. ユーザビリティ
見出し要素は情報を整理し、ユーザーを適切にナビゲートするため使われるべきである。ロゴは実際には情報やナビゲーションではなく、サイトに関するメタデータであり、ページの内容に関する関連情報ではない。
2. アクセシビリティ
ロゴのような「インチキ」な見出しをつけることは、スクリーンリーダーを使うユーザーにとって、すべてのページで余分なテキストを聞かなければならないことを意味する。
3. ロボット対策
クローラーは様々な理由でウェブサイトをスキャンする。偽の <h1>
を追加することでページの構造とコンテンツについて彼らを混乱させ、コンテンツを誤って表示したり、他のアグリゲーターで誤って分類したりする可能性がある。
上記は「なぜ見出しを正しく用いることが重要なのか」という疑問の回答にもなっている。これらを考慮すると、ロゴを <h1>
にするメリットは存在しないどころか、様々な点でデメリットとなり得る場面の方が多いと結論づけることができる。
具体的な例として、amazon.co.jp では商品名が <h1>
になっている。
ameba ブログでは記事タイトルが <h1>
で、左上のサービスロゴは <div>
でマークアップされている。
<section>
に見出しは必須か?
必須ではないが、慣習として見出しとセットで使用されることが一般的であると言える。 また、文書のアウトラインを形成するのはあくまで見出し要素であり、 <section>
と見出し要素をセットで使用することによって何らかの機能が発生するわけではない。
<section>
がアクセシブルな名前を持つ場合は role=region(ランドマーク) に、そうでない場合は role=generic となる。
<section>
が見出しを持つ場合、その見出し要素がアクセシブルな名前として利用されることが一般的である。<section>
にアクセシブルな名前を与える方法は優先順位の高い順に以下のとおり。
aria-labelledby
aria-label
title
ただし title
は macOS Safari 等で意図しない動作をすることがあるため推奨されない。
参考:Accessibility of the section element | scottohara.me
以下は aria-labelledby
を使用して<section>
にアクセシブルな名前を与える例。
<body>
<main>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<!-- この section は role=region になる -->
<section aria-labelledby="section-heading">
<h2 id="section-heading">Taste</h2>
<p>They taste lovely.</p>
</section>
</main>
</body>
まとめ
- 必ずしも
<section>
と見出し要素をセットで使う必要はない - アウトラインを形成するのは見出し要素。アウトラインだけが必要なのであれば
<section>
にアクセシブルな名前は必要ない -
<section>
をランドマークとして公開したいのであればアクセシブルな名前を与える -
<section>
のアクセシブルな名前は、そのセクションに内包される見出し要素であることが一般的
見出しとアクセシビリティ
Heading off confusion: When do headings fail WCAG? - TPGi を参考に、WCAG 達成基準の失敗と成功という観点から見出しのアクセシビリティを考えてみる。
見出しに関連する WCAG 達成基準
WCAG の中で見出しに関連する達成基準は以下で、A ~ AAA の各レベルで見出しに触れていることが分かる。
1.3.1 情報及び関係性: 何らかの形で提示されている情報、構造、及び関係性は、プログラムによる解釈が可能である、又はテキストで提供されている。(レベル A)
セマンティックなマークアップと適切な構造化によるマシンリーダビリティやテキストの提供を求める達成基準。ここではセマンティクスが求められており、すべての画面やページに見出しが必要ということは述べられていない。
2.4.6 見出し及びラベル: 見出し及びラベルは、主題又は目的を説明している。(レベル AA)
見出しの内容に関するもので、1.3.1 と同様、見出しそのものを求めるものではない。
2.4.10 セクション見出し: セクション見出しを用いて、コンテンツが整理されている。(レベル AAA)
ここで初めて見出しが存在することを求められる。この達成基準が AAA となっている理由として、あらゆる種類のコンテンツに見出しを挿入することが常に可能であるとは限らないため、とされている。例えばウェブコンテンツであっても、ユーザー生成コンテンツや、管轄外の CMS から提供されるコンテンツなどは後から任意の見出しを入れることは困難である。
WCAG で失敗とみなされない例
見出しの欠如
上記で確認した通り、見出しの欠如自体は失敗とみなされない。とはいえ見出しの重要性は明らかであり、例えばコンテンツの制作者と提供者が一致する(= 見出しの有無をコントロールできる)ウェブコンテンツに適用範囲を限定するなどして独自の達成基準とするのは悪くないのではないと思う。
<h1>
の欠如
画面やページに <h1>
が存在しないこと自体が失敗とみなされることはなさそうである。しかし一般論として、ページのタイトルと一致したり、主題を適切に表現するような <h1>
が提供されることが望ましいことに変わりはない。
<h1>
が存在すること
複数の 逆もまた然りで、複数の <h1>
の存在が失敗とみなされるとは言及されていない。
HTML の仕様上でも禁止はされていないが、MDN には「1つのページに複数の <h1>
要素を使用しない」として以下のように述べられている。
1 つのページに複数の
<h1>
要素を使用することは HTML 標準では認められていますが(入れ子でない限り)、これはよい習慣とはみなされません。1 つのページには、ページの内容を説明する 1 つの<h1>
要素(文書の<title>
要素と同様)を置くのが一般的です。
また補足として以下のように述べられている。
メモ: 入れ子になったコンテンツ区分要素の中で複数の <h1> 要素を入れ子にすることは、HTML 標準の古いバージョンでは認められていました。しかし、これはよい習慣とはみなされず、現在は非適合となっています。詳しくは、There Is No Document Outline Algorithm をご覧ください。
アウトラインアルゴリズムの導入が検討されていた時代は複数の <h1>
を運用することが認められていたものの、結局アルゴリズム自体が仕様からドロップしたため、その点からも現在は推奨されないものであると述べられている。アウトラインアルゴリズムの刷新に関する一連の動きはHTML のアウトラインアルゴリズムが見出しレベルをベースとしたものに刷新されそう | 富永日記帳に詳しい。
一般論として文書内の <h1> 要素は一つにとどめた方が良いでしょう。
という記述のとおり、よほど特殊な事情がなければページ内の <h1>
は1つであるべきだろう。理想的には <main>
要素の内容を表す最初の子孫要素であることが望ましいと言える。
見出しレベルのスキップ
こちらも WCAG の中では明確な失敗とはみなされないが、達成基準 1.3.1 や 2.4.10 の達成方法として「G141: 見出しを用いてウェブページを構造化する」や「H42: 見出しを特定するために、h1 要素~ h6 要素を使用する」、「H69: コンテンツの各セクションの開始位置に見出し要素を提供する」といったものが紹介されている。
一方、HTML Living Standard の 4.3.11 Headings and outlinesでは、見出しの仕様は以下のように定義されている。
- 見出し要素はその数字に対応した見出しレベルを持つ
- 見出しレベルが低いほど、その見出しが持つ祖先セクションの数が少なくなる
- アウトラインとは、文書内のすべての見出しをツリー順に並べたものである
- 文書に1つ以上の見出しがある場合、アウトライン内の少なくとも1つの見出しの見出しレベルは1(
<h1>
)でなければならない - アウトライン内の別の見出しリードに続く各見出しは、リードの見出しレベルよりも小さい、等しい、または1つ大きい見出しレベルを持たなければならない
よって、WCAG では失敗とならない見出しレベルのスキップも、HTML の仕様上は不適切であると言える。
以下の例は見出しレベルがスキップされているため、仕様に違反している。
<body>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<section>
<h3>Taste</h3>
<p>They taste lovely.</p>
</section>
</body>
上記は1つ大きい見出しレベルを使用して以下のように修正できる。
<body>
<h1>Apples</h1>
<p>Apples are fruit.</p>
<section>
<h2>Taste</h2>
<p>They taste lovely.</p>
</section>
</body>
HeadingsMap や HTML5 Outliner などの拡張機能を利用して見出しレベルをチェックする習慣を身に付けたい。
同じテキストの複数の見出し
一見すると「2.4.6 見出し及びラベル」の失敗例となりそうだが、これは文脈に依存する。
例えば以下のように、同階層に同じテキストの複数の見出しが存在する場合は明らかに混乱を招く。
<body>
<h1>フルーツ</h1>
<p>リンゴはフルーツ</p>
<h1>フルーツ</h1>
<p>レモンはフルーツ</p>
<h1>オレンジ</h1>
<p>オレンジはフルーツ</p>
</body>
一方で、以下のように分割された各セクションに同じサブ見出しが存在するようなシチュエーションは比較的一般的である。
<body>
<h1>フルーツ</h1>
<section>
<h2>リンゴ</h2>
<h3>このフルーツについて</h3>
</section>
<section>
<h2>レモン</h2>
<h3>このフルーツについて</h3>
</section>
<section>
<h2>オレンジ</h2>
<h3>このフルーツについて</h3>
</section>
</body>
このことから、同じテキストを持つ複数の見出しが失敗となるかどうかは文脈や構造に依存するということが言える。
WCAG で失敗とみなされる例
それでは逆に失敗とみなされる例とはどのようなものだろうか。
見出しとしてマークアップされていない見出しのようなテキスト
あるテキストが見出しを意図されながら見出し要素を用いてマークアップされていない場合、「プログラムによる解釈」が不可能となることから「達成基準 1.3.1: 情報及び関係性」の失敗とみなすことができる。
「達成基準 1.3.1 の失敗例 - 情報を伝えるために、適切なマークアップ又はテキストを用いずに、テキストの提示の変化を使用している」では、具体的な失敗例として以下が挙げられている。
- CSS を用いて p 要素を見出しのような見た目にする
- 見出しとして用いられる文字画像で、その画像が見出しタグでマークアップされていない
- 単語やフレーズを強調するために CSS を用いて見た目を制御しているが、その強調のセマンティックを表すマークアップが行われていない場合
非論理的な見出し順
例えば、直前の見出しが <h3>
であるにもかかわらず、その次に来る見出しが <h2>
であるようなケースを「非論理的な見出し順」と言うことができ、「達成基準 1.3.1: 情報及び関係性」 の失敗とみなされる。「達成基準 1.3.1 の失敗例 - コンテンツにおける関係を表さない方法で、構造的なマークアップを使用している」では「プレゼンテーション上の効果を目的とした見出し要素の使用」という例が示されている。
<h1>Study on the Use of Heading Elements in Web Pages</h1>
<h3>Joe Jones and Mary Smith<h3>
<h4>March 14, 2006</h4>
<h2>Abstract</h2>
<p>A study was conducted in early 2006 ...
</p>
これはあくまで順序についての失敗例であり、見出しレベルをスキップできないということを意味するものではない。
説明的でない見出し
「達成基準 2.4.6: 見出し及びラベルを理解する」では見出しの内容について言及されており、「見出しが明快かつ内容が分かるように記述」することを要求している。
以下の例では、それぞれのセクションを説明するのに十分な見出しが提供されているとは言えないため失敗とみなすことができる。
<h2>レシピ</h2>
<p>完璧なリゾットを作るには…が不可欠です。</p>
<h2>レシピ</h2>
<p>コック・オ・ヴァンはフランスの伝統的な煮込み料理です。</p>
何が「説明的」という点について絶対的な基準は存在しないものの、その見出しを見たときに関連するセクションの内容が把握できるか?という観点でチェックできるとよいかもしれない。