【HTML】main 要素 – 最新の仕様に準拠してますか?

main 要素はページの主要なコンテンツを表しますが、ネットで調べると、細かい点では記事によって言っていることが異なっていることにお気づきでしょうか。それは、W3C HTML5 仕様がバージョンアップされる過程、そして、W3C HTML5 仕様が終了し、WAHTWG HTML 仕様が最新となった現在に至るまでに、main 要素の仕様が変貌したからです。今回は、過去の仕様のおさらいしつつ、最終的な現在の正しい仕様について解説します。

main 要素の使い方

main 要素の意味については、HTML 仕様のバージョンアップに関わらず一貫して、ページの主要なコンテンツを表すことになっています。多くの人にとって、ここに誤解はないでしょう。WordPress のようなブログシステムや、さまざまな HTML テンプレートでは、当たり前のように main 要素が使われています。

<body>
  <!-- ページヘッダー -->
  <header>
    <img src="logo.jpg" alt=""> webfrontend.ninja
  </header>
  <!-- 広告 -->
  <aside>
    <a href="https://…"><img src="ad.jpg" alt="…"></a>
  </aside>
  <!-- メインコンテンツ -->
  <main>
    <article>
      <h1>記事タイトル</h1>
      <p>記事本文…</p>
    </article>
  </main>
  <!-- ページフッター -->
  <footer>
    <p><small>&copy; webfrontend.ninja</small></p>
  </footer>
</body>

このように、通常は main 要素はページに 1 つとなるはずです。

実は主要なコンテンツではない?

仕様のバージョンアップの過去を見ると、main 要素の意味に関して、「主要なコンテンツ」という言い方が微妙に変化しています。

W3C HTML5 仕様が現役だったころは、main 要素の意味は main content と記載されていました。しかし、現行の WHATWG HTML 仕様では dominant contents と記載されています。日本語訳にしてしまうと、どちらも「主要なコンテンツ」と訳せてしまいます。

しかし、わざわざ main を dominant に変更したのは、理由があるはずです。しかも content という単数形から contents という複数形に変わっています。これは、WHATWG HTML 仕様ではページの中に複数の main 要素をマークアップできるようになっているためです。

ページに 2 つ以上の main 要素を入れられるが、しかし…

main 要素の役割を考えると、ページに複数の main 要素を入れることはできないはずです。しかし、1 つを除いて、それ以外の main 要素に hidden 属性をマークアップすれば、ページに複数の main 要素を入れることは可能です。

<body>
  <main>
    <h1>いま有効なメインコンテンツ</h1>
    <p>この main 要素が表示中です。</p>
  </main>
  <main hidden>
    <h1>いま無効なメインコンテンツ</h1>
    <p>この main 要素は非表示になっています。</p>
  </man>
</body>

hidden 属性がセットされた要素は、そのページには関係がないという意味を持ち、ブラウザーはその要素を非表示にします。つまり、無いものとしてみなすわけです。そのため、事実上、機能する main 要素はページに 1 つしか存在できないということです。

しかし、この仕様には違和感を感じませんか?hidden 属性をセットした要素は事実上存在しないわけですから、わざわざ仕様で言わなくても良さそうなものです。

実は、W3C HTML5 仕様と WHATWG HTML 仕様が併存していたとき、main 要素の数がそれぞれで食い違っていました。当初WHATWG HTML 仕様では複数の main 要素を許していました。その後、W3C HTML5 仕様ではページに 1 つしか main 要素を許さないよう制限しました。日本の Web 業界では W3C のほうが権威性があり好まれる傾向があるせいか、多くのネット記事では W3C の仕様が紹介されていたというわけです。

長い間、この分裂は決着がつかなかったのですが、徐々にお互いの仕様が近づいていき、W3C HTML 5.2 では、現在の WHATWG HTML 仕様に近い形になりました。しかし W3C HTML 5.2 が勧告になったときには、もう HTML5 ブームも過ぎ去り、あまり話題になりませんでした。そのため、新しい記事が作られることも、古い記事がアップデートされることもなくなってきたのでしょう。

なぜ 2 つ以上の main 要素が必要だったのか?

通常、一つのページに複数の main 要素は不必要と思うのではないでしょうか。では、なぜ WHATWG では複数の main 要素のマークアップを許していたのでしょうか。

筆者はその経緯を詳しくは知りませんが、現状の WHATWG HTML 仕様の main 要素の規定やサンプルコードを見る限り、SPA(Single Page Application)の事情も理由の一つと思われます。

次のマークアップ例は、nav 要素のリストのリンクをクリックすると表示画面が切り替わるウェブアプリを想定しています。

<body>
  <header>
    <h1>時計アプリ</h1>
    <nav>
      <ul id="gnavi">
        <li><a href="#page-clock">時計</a></li>
        <li><a href="#page-pref">設定</a></li>
        <li><a href="#page-help">ヘルプ</a></li>
      </ul>
    </nav>
  </header>
  <main id="page-clock">
    <h2>時計</h2>
    <p>…</p>
  </main>
  <main id="page-pref" hidden>
    <h2>設定</h2>
    <p>…</p>
  </main>
  <main id="page-help" hidden>
    <h2>ヘルプ</h2>
    <p>…</p>
  </main>
</body>

表示画面は 3 つありますが、それぞれ main 要素でマークアップされています。うち 2 つの main 要素には hidden 属性がマークアップされているため、非表示になっています。

次の JavaScript で画面を切り替える仕組みを実現することができます。

const gnavi = document.getElementById('gnavi');
gnavi.addEventListener('click', (event) => {
  if (event.target.nodeName === 'A') {
    const main_el_list = document.querySelectorAll('main');
    for(let i=0; i<main_el_list.length; i++) {
      main_el_list.item(i).hidden = true;
    }
    const id_selector = event.target.getAttribute('href');
    document.querySelector(id_selector).hidden = false;
  }
});

現在では、SPA を開発するのであれば、AngularJS、React、Vue.js などの JavaScript ライブラリーを使うことがほとんどでしょうが、簡単なものであれば、このように自作することができます。画面の数が多くないのであれば、一つの HTML 内にすべての画面をマークアップしておきたいのではないでしょうか。また、SPA で画面が切り替わる際に書き換えられるコンテンツは、まさに main 要素にふさわしいコンテンツです。

main 要素を使ってよい場所

ネットで main 要素について調べると、main 要素は article 要素、aside 要素、footer 要素、header 要素、nav 要素の中では使ってはいけないと書かれているのを見たことがあるのではないでしょうか。実は、この定義はもう古く、W3C HTML5 時代の名残です。

現在の WHATWG HTML 仕様では、main 要素の祖先要素はアクセシブルネームを持たない html 要素、body 要素、div 要素、form 要素に限定されなければいけない、と規定されています。

アクセシブルネームとはスクリーンリーダーなどのツール(支援技術)がコンテンツを読み上げる際に使う名前のことですが、 html 要素、body 要素、div 要素、form 要素は、何もしなければ アクセシブルネームを持ちませんので、いったんは気にしなくても大丈夫です。

main 要素の祖先には html 要素、body 要素、div 要素、form 要素しかあってはならないわけですから、main 要素が使える場所としては、W3C HTML5 時代の規定と比べてかなり厳しくなってます。とはいえ、main 要素の意味を考えると、利用場所が制限されたとしても困ることはないはずです。

まとめ

main 要素はすべてのページで使うことができ使用頻度が高い要素です。最新の仕様に基づいた用法を正しく守って使いましょう。

一点、筆者自身が気になるところがあります。main 要素は form 要素の中で使っても良いことになっているのですが、それが謎です。なぜでしょうかね?もし分かったら共有します。

もう一つ、変な疑問が湧いてきました。main 要素は hidden 属性を使えばページの中でいくつもマークアップできることになっていますが、それが許されるなら、body 要素も同じルールで良くないでしょうか?まぁ、いろいろと困ることが発生するから許されていないのでしょうけどね。

今回は以上で終わりです。最後まで読んでくださりありがとうございました。それでは次回の記事までごきげんよう。

Share