メインコンテンツまでスキップ

主題と副題のマークアップにはhgroupを使用する

HTML

広告

主題と副題のマークアップの方法に関しては度々Xでも話題になっていて、例えば次のポストの返信やリポストを見ると、人によって以下のような様々なアプローチがあることがわかります。

参考:過去に話題になったポスト
ポストを別枠で表示する
  • 見出し要素(h1h6)の中に主題と副題の両方を含める
    • この場合の副題はspanではなくstrongsmallを使うと言った意見も見られる
  • 主題をh1要素でマークアップし、副題は隣接するh2要素を使う
  • 疑似要素とcontent:attr()を使って副題を表示する

このブログのトップページでも主題+副題が用いられていて、いくつかのマークアップ方法を検討した結果「hgroupの中に主題のh1要素と副題のp要素を含める」方法を選択しました。

マークアップ例
<hgroup>
<h1 translate="no">TAKLOG</h1>
<p>フロントエンドエンジニアの私的メモブログ</p>
</hgroup>

hgroup要素とは

hgroup要素は2009年にW3C HTML5の仕様書に追加された、見出しとそれに関連する内容(副題)をグルーピングするためのHTML要素です。次のように複数の見出し要素をグルーピングして、副題を表現することを目的としていました。

HTML5のマークアップ例
<hgroup>
<h1>シーソーゲーム</h1>
<h2>勇敢な恋の歌</h2>
</hgroup>

上記のマークアップではh2要素が副題を表しています。仕様ではhgroup要素内ではh1要素のみが見出しとして扱われてh2要素は見出しとしては扱われないことが想定されていましたが、アウトラインアルゴリズムに対応していないブラウザでは仕様で望まれている扱いができず、副題を含めて2つの見出しが存在するように解釈されてしまうという問題がありました。

そういった事情もあり2013年春にはHTML ワーキンググループにおいて廃止が決定し、同年夏には仕様から削除されました。

よく「hgroupはHTML5で廃止された」という文献を見かけますが、これは少し語弊のある記述かもしれません。hgroup要素はHTML5の草案で誕生し、HTML5の勧告がされる前に廃止されたため、W3CのHTML仕様にはhgroup要素が存在した時期は無いためです。hgroup要素は日の目を浴びる前に登場と廃止を経験した悲しい過去を背負ったHTML要素だと言えるでしょう。

参考:`<hgroup>` 要素は今どうなっているのか | 富永日記帳

とは言え、hgroupが削除されたのはW3CのHTML仕様であり、WHATWGのLiving Standardには仕様として残りました。

2021年1月28日にHTML5が廃止され、翌日にHTML Living Standard7が正式にW3C Recommendation(勧告)として発表された後はhgroup仕様的には堂々と使用することができるようになりました。

しかし、依然としてブラウザはアウトラインアルゴリズムに対応していないため、W3Cで廃止となるきっかけになった「副題を含めて2つの見出しが存在するように解釈されてしまうという」という問題は残ったままです。

故に2022年7月にアウトラインアルゴリズムの廃止がされるまで、HTMLに精通した多くの技術者が「hgroupは使うな」とアドバイスしたり、MDNにおいても「支援技術の見出しの読み上げに影響があるから使うんじゃねぇ」と警告がされる事態になっていました。

Wayback Machineで2022年5月のMDNのhgroup要素のドキュメントをスクリーンショットしたもの
2022年5月時点でのMDNのhgroup要素のドキュメント。前述したように警告が表示されている。

アウトラインアルゴリズムの廃止以降はhgroup要素の仕様が大きく変化した

2022年7月にアウトラインアルゴリズムが廃止されてからはhgroup要素の仕様が大きく変わりました。

参考:4.3.7 The hgroup element | HTML Standard

具体的には中に含める見出し要素は1つのみで、小見出しはp要素で前後に配置するというものです。これにより「副題を含めて2つの見出しが存在するように解釈されてしまう」といった問題は解決されることになりました。

アウトラインアルゴリズムの廃止前の仕様アウトラインアルゴリズムの廃止後の仕様
1個以上のh1,h2,h3,h4,h5,h60個以上のpと、それに続くh1,h2,h3,h4,h5,h6と、それに続く0個以上のp
🙆‍♂ Recommended
<hgroup>
<h1>everybody goes</h1>
<p>秩序のない現代にドロップキック</p>
</hgroup>

一方、先述したように現在の仕様ではhgroup要素に含んで良い見出し要素の数は1つまでとなりますので、かつての「複数の見出し要素をグルーピングして副題を表現する」というマークアップは現在では仕様と反していることになりますのでご注意ください。

🙅‍♂ Not Recommended
<hgroup>
<h1>everybody goes</h1>
<h2>秩序のない現代にドロップキック</h2>
</hgroup>

HTML Accessibility API Mappings 1.0によれば、過去の仕様のマークアップに関しては最も優先度の高い見出し要素をhgroup要素の唯一の見出しとして扱い、その他すべての見出し要素はp要素であるかのように扱われる場合があるようです。ただし、ユーザーエージェントがどのように扱うかは任意であり、例えばVoice Overは現在もその他の見出し要素を「見出し」として扱います。そのため、過去の仕様のマークアップは非推奨であることに変わりはありません。

hgroup要素のroleの変更: genericからgroupへ

ようやく実用的になったhgroup要素ですが、hgroup要素のroleにはdiv要素やspan要素と同様にgenericが割り当てられていました。故にhgroup要素はセマンティックな意味を持たず、アクセシビリティマッピング的にはdiv要素で実装するのと変わりがないという有り様で、hgroup要素を率先的に使用する必要性は低かったという印象です。

ところが、2023年3月にARIA in HTMLにIssueが提起され、同年8月にaddress要素とともにhgroup要素のrolegroupに変更されました。

ARIA in HTMLのhgroup要素のドキュメントをスクリーンショットしたもの

この変更によりhgroup要素はセマンティックな意味を持つようになり、単なるdiv要素とは区別されるようになりました。

かつての仕様では勧告される前に廃止され、現在の仕様では存在はするものの四方八方から使うなと言われるなど不遇な立ち位置であったhgroup要素ですが、二度のアップデートにより主題+副題のマークアップ方法としては最も適した要素になったと言えるでしょう。

ちなみに現時点でMDNは更新されておらず、英語版・日本語版共に暗黙のARIAロールは「対応するロールなし」となっているので参照する際は注意してください。

他の主題+副題のマークアップとの比較

主題+副題のマークアップを他の方法で実装した際の比較もしてみましょう。

  • 見出し要素(h1h6)の中に主題と副題の両方を含める
  • 主題をh1要素でマークアップし、副題は隣接するh2要素を使う
  • 疑似要素とcontent:attr()を使って副題を表示する

このうち、「主題をh1要素でマークアップし、副題は隣接するh2要素を使う」に関しては先述した理由から非推奨なので省略します。

見出し要素(h1〜h6)の中に主題と副題の両方を含める

冒頭で引用したポストへのコメントで一番賛同が多い印象だったのがこちらです。

マークアップ例
<h1><span>Mémento-Mori</span></h1>

見出し要素に主題と副題の両方を含めることのメリットは、副題も見出しジャンプ機能や見出しの読み上げ時に認識されるという点でしょうか。

しかし、主題となる見出し要素に内包される以上、副題は主題の一部であって独立した副題ではないという解釈もできます。また、副題のマークアップは見出し要素の中のspan要素(セマンティックな意味を持たないrole="generic"要素)で行うため、主題と副題の区別はスタイリングによる視覚的な判別でしかできないという課題もあります。

副題を主題と共に支援技術に読み上げて欲しい場合はこの方法を検討する価値はありますが、主題と副題を明確に区別したいのであればこのマークアップは不十分かもしれません。

また、見出し要素の中の副題に関してsmallを使用するという意見も見られましたが、これは現在のHTMLの仕様にはしてはならないと記述がされているので気をつけてください。同時にこのようなマークアップを行うならhgroup要素を使いなさいとも記述されています。

The small element must not be used for subheadings; for that purpose, use the hgroup element.

結論としては副題を見出しの一部として認識したいのならこちらの方法も検討できますが、主題と副題を明確に区別したいのであればhgroup要素に軍配が上がるでしょう。

疑似要素とcontent:attr()を使って副題を表示する

カスタムデータ属性に副題を持たせ、疑似要素にcontent:attr()でテキストを出力するというものです。

マークアップ例
<h1 data-subtitle="Theme of es">【es】</h1>
<style>
h1::after {
display: block;
content: attr(data-subtitle);
}
</style>

コーディングテクニック的な技術記事でよく見かける手法であり、僕も駆け出しの頃はこの方法で副題を表示していた時期もありましたが、今では次のような理由からこのような手法は行わなくなりました。

  • content:attr()で出力したテキストはコンテンツとして認識されない
  • いくつかの機械翻訳ではcontent:attr()で出力したテキストは翻訳されない
  • content:attr()で出力したテキストは選択&コピーできない
  • content:attr()で出力したテキストはページ内検索でヒットしない
  • 装飾扱いしたいテキストのためにcontent:attr()で出力をしているのなら、疑似要素のテキストは支援技術の読み上げ対象になるので意味のない実装である

これらのアクセシビリティ的な理由に加えてそもそもcontent:attr()で出力するメリットが存在しないというのも理由の一つです。普通にHTMLに直書きしたほうが総合的な記述量は抑えられるでしょうし、もしも装飾扱いしたいならaria-hidden="true"属性を指定する、機械翻訳を防ぎたいのならtranslate="no"属性を指定する、仮にテキスト選択とページ内検索のヒットまで防ぎたいならinert属性を指定するという選択肢もあります。実装コスト的にはテキストをカスタムデータ属性に持たせるかタグで囲むかの違いでしかなく、わざわざデメリットが目立つ方法を選ぶ理由は無いでしょう。

hgroup要素の使用と比較した際の優位点は考えられませんでした。

同じ意味を持つ日本語+英語の見出し構成について

話は変わりますが、よくある同じような意味を持つ日本語+英語のような見出し構成においてもaria-hidden="true"属性などの指定はせずにそのまま主題+副題としてマークアップをするようにします。

🙅‍♂ Not Recommended
<h1>会社概要</h1>
<div aria-hidden="true">About</div>
🙆‍♂ Recommended
<hgroup>
<h1>会社概要</h1>
<p lang="en">About</p>
</hgroup>

理由としてはテキストとして表示されている以上、情報格差を無くすためには読み上げられたほうがいいんじゃないかという考えによるものです。支援技術の読み上げ的に不要では?という意見もありますが、そもそも読み上げ時に邪魔になるテキストは視覚的にも邪魔になる可能性が高いので、デザインの段階から見直してもいいのかもしれません。

日本語+英語の見出し構成は主題+副題の関係になるのか?という意見もあるとは思いますが、同じ意味を持つ日本語と英語のテキストが主題+副題の関係になっている作品は多く存在するため、僕個人の考えでは問題ないという認識です。有名どころではHysteric Blueの『春〜spring』やサザンオールスターズの『エロティカ・セブン EROTICA SEVEN』という楽曲がありますが、同じような意味を持つ日本語+英語の構成が主題+副題の関係になっています。

role=“doc-subtitle”について

過去に副題のマークアップにrole="doc-subtitle"を使用できると知ったものの、アクセシビリティ上の問題から使用を諦めたことがあります。

参考:Be Wary of doc-subtitle — Adrian Roselli

参考記事によるとVoice Overなどの支援技術がrole="doc-subtitle"を指定した要素を「heading level 2」と読み上げてしまう不具合があったとのことです。これにより、かえってアクセシビリティに悪影響を与えかねないという内容でした。

現在の状況を確認するためにVoice Overで検証を行ったところ以下の結果が得られました。

  • Google Chrome+Voice Overでは、レベルのない「副題」として読み上げられている
  • Safari+Voice Overでは、「heading level 2」と読み上げられてしまう

したがって、現時点でもrole="doc-subtitle"の使用は控えたほうが賢明だと言えます。副題のマークアップにはhgroup要素を使用するなど、他の適切な方法を選択したほうが良いでしょう。

参考リンク