SEOとアクセシビリティを意識した「パンくずリスト」のマークアップの方法

## 概要

パンくずの正確な書き方とはなんだろうか考えてみる。

単純に見た目だけパンくずにしようとすると下記のようにリストで階層構造を表して、見た目を「パンくず」っぽくする実装になる。

```html
<ol class="breadcrumb">
  <li><a href="https://example.jp/">トップページ</a></li>
  <li><a href="https://example.jp/list/">記事一覧</a></li>
  <li class="current"><a href="https://example.jp/detail/">詳細</a></li>
</ol>
```

見た目だけはこれで良いのだが、この HTML 構造だとスクリーンリーダーやボットなどが「パンくず」を辿るこどはできない。

## 仕様

「正解の仕様」を定めるために、下記の技術仕様を軸に実装する。

- **リッチリザルト**
  検索結果に情報を増やすという意味で（SEO 対策としても有）
- **WAI-ARIA**
  アクセシビリティの向上として

### リッチリザルト

検索エンジンなどの Bot にパンくずリストを認識させたいのであれば、UI は要らない。JSON-LD の構造化データを用意するだけで良い。

```html:JSON-LD
<script type="application/ld+json">
{
  "@context": "http://schema.org",
  "@type": "BreadcrumbList",
  "name": "パンくずリスト",
  "itemListElement": [
    {
      "@type": "ListItem",
      "position": 1,
      "item": { "@id": "https://example.jp/", "name": "トップページ" }
    },
    {
      "@type": "ListItem",
      "position": 2,
      "item": { "@id": "https://example.jp/list/", "name": "記事一覧" }
    },
    {
      "@type": "ListItem",
      "position": 3,
      "item": {
        "@id": "https://example.jp/detail",
        "name": "詳細"
      }
    }
  ]
}
</script>
```

**参考：**

- [Google の検索結果にパンくずリストのリッチリザルト表示をするには構造化データだけ用意すれば良い](https://zenn.dev/hiro/articles/c5e403cca4325b9a953d)

ライブラリなどでこの JSON-LD とパンくずリストの UI が簡単に出力されるのであれば管理や実装の手間はない。ただそうでない場合、UI との二重管理になってしまう（また、ドキュメントのサイズも大きくなる）。今回は UI があるので、構造化データも組み合わせておきたい。

microdata でマークアップした場合は下記のようになる。

```html:microdata
<ol itemscope itemtype="https://schema.org/BreadcrumbList">
  <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
    <a itemprop="item" href="https://example.jp/"><span itemprop="name">トップページ</span></a>
    <meta itemprop="position" content="1" />
  </li>
  <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
    <a
      itemscope
      itemtype="https://schema.org/WebPage"
      itemprop="item"
      itemid="https://example.com/books/sciencefiction"
      href="https://example.jp/list/"
    >
      <span itemprop="name">記事一覧</span></a
    >
    <meta itemprop="position" content="2" />
  </li>
  <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
    <a
      itemscope
      itemtype="https://schema.org/WebPage"
      itemprop="item"
      itemid="https://example.com/books/sciencefiction"
      href="https://example.jp/deail/"
    >
      <span itemprop="name">詳細</span>
    </a>
    <meta itemprop="position" content="3" />
  </li>
</ol>
```

このパンくずはリッチリザルトのテストを通っているので Google 検索結果にもパンくずリストのリッチスニペットとして表示されるだろう。

**参考：**

- [Google - リッチリザルト テスト](https://search.google.com/test/rich-results?utm_campaign=devsite&utm_medium=microdata&utm_source=breadcrumb&id=Jfp9vP3CGzT_BRFkYwdfrQ)
- [Google - 単一のパンくずリスト](https://developers.google.com/search/docs/data-types/breadcrumb?hl=ja)

## WAI-ARIA

W3C の WAI-ARIA のページに「[パンくずリストの例](https://www.w3.org/TR/wai-aria-practices-1.1/examples/breadcrumb/index.html)」が記載されていた。

使用するプロパティは下記。

| 属性                    | 要素 | 使用法                                                     |
| ----------------------- | ---- | ---------------------------------------------------------- |
| `aria-label="パンくずリスト"` | nav  | nav 要素で提供されるナビゲーションのタイプを説明するラベル |
| `aria-current="page"`     | a    | 最後のリンクに適用され、現在のページを表していることを示す |

それを踏まえた実装サンプルは下記の通り。

```html:WAI-ARIA
<nav aria-label="パンくずリスト" class="breadcrumb">
  <ol>
    <li>
      <a href="https://example.jp/">トップページ</a>
    </li>
    <li>
      <a href="https://example.jp/list/">記事一覧</a>
    </li>
    <li>
      <a href="https://example.jp/detail/" aria-current="page">詳細</a>
    </li>
  </ol>
</nav>
```

ちなみにパンくずの構造間の区切り（セパレーター）は、スクリーンリーダーで読み上げられるのを防ぐために HTML には記述せず、CSS で記述する方が良いとのこと（当該ページのサンプルでは `li::before` で実装されていた）。

### 合体

```html:microdata+WAI-ARIA
<nav aria-label="Breadcrumb">
  <ol itemscope itemtype="https://schema.org/BreadcrumbList">
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
      <a itemprop="item" href="https://example.jp/"><span itemprop="name">トップページ</span></a>
      <meta itemprop="position" content="1" />
    </li>
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
      <a
        itemscope
        itemtype="https://schema.org/WebPage"
        itemprop="item"
        itemid="https://example.com/books/sciencefiction"
        href="https://example.jp/list/"
      >
        <span itemprop="name">記事一覧</span></a
      >
      <meta itemprop="position" content="2" />
    </li>
    <li itemprop="itemListElement" itemscope itemtype="https://schema.org/ListItem">
      <a
        itemscope
        itemtype="https://schema.org/WebPage"
        itemprop="item"
        itemid="https://example.com/books/sciencefiction"
        aria-current="page"
        href="https://example.jp/deail/"
      >
        <span itemprop="name">詳細</span>
      </a>
      <meta itemprop="position" content="3" />
    </li>
  </ol>
</nav>
```

## 所管

パンくずは、PC と SP のデバイスサイズの差から配置の場所が異なりデザインや役割が大きくことなることも多い。

アクセシビリティを重視する意図があれば、WAI-ARIA に沿ったマークアップを施しデバイス依存しないデザインをするべきだ。アクセシビリティよりも SEO としてパンくずリストが必要なのであればリッチリザルトに載るように JSON-LD で構造化だけ読み込んでおくのも手だ。

これら両方を重視したいとなった場合、最後に記述したような膨大なコードを今現在は記述する必要がありそうだ。