目次

パンくずリストを作ろう入門編

パンくずリストの作成方法から構造化データの利用法、WAI-ARIAを使った実装方法を説明します。


PREPARATION


想定する読者と前提条件

パソコンの基本操作ができること。HTMLの基礎がわかっていること。 今回の記事は、様々な情報への入り口になるように少しずつ各情報を紹介しております。 決まった書き方が存在しないことへの苛立ちが募らないことを祈ります。


START


そもそもパンくずリストとは?

童話「ヘンゼルとグレーテル」では、兄弟が森に入った時に、弁当として与えられたパンをポケットの中で細かくし、元の場所に戻れるように少しずつ道しるべとして道に置いていきました。

パンくずと言う用語は、この童話で道標として使用されたパンくずに由来しています。

Webサイト上では、利用者がサイト内で今どこを閲覧しているのか、現在位置を見失わないように利用されるナビゲーションをパンくずリストと呼んでいます。

一般的にパンくずリストは、現在のウェブページまで移動する途中にアクセスしたページへのリンクを使って作成されます。

英語では、breadcrumbs と表記します。

実際の使用方法は?

一般的なパンくずリストは、p要素、ol要素、ul要素等を使用してマークアップされます。また、パンくずリスト自体もナビゲーション要素となりますので、nav要素でマークアップすることもできます。

利用者が使いやすいパンくずリストを表現するためには、奇抜な手法(見た目等)よりも一般的に浸透している手法を用いることで、利用者が安心して利用できます。

では早速、様々なサイトのパンくずリストの使われ方を見てみましょう。

  • 例1) 東京2020オリンピック・パラリンピック競技大会の公式ウェブサイト

    上記サイトのパンくずリスト用HTMLの構造を簡略化して表記。

    <nav>
        <p>
            <a href="">ホーム</a>
            <img src="" alt=">">
            <a href="">参加する</a>
            <img src="" alt=">">
            <a href="">東京2020大会の観戦をお考えの皆様へ</a>
            <span>東京2020をもっと楽しもう!</span>
        </p>
    </nav>

    nav要素を使用。リンクはp要素内にa要素を入れ、セパレーターは画像で作成しています。現在位置はspan要素。

    音声読み上げソフト(NVDA)では、上記例を「ホーム 参加する 東京2020大会の観戦をお考えの皆様へ 東京2020をもっと楽しもう! 」と読み上げます。

  • 例2) 総務省

    上記サイトのパンくずリスト用HTMLの構造を簡略化して表記。

    <div>
        <p>
            <a href="">トップページ</a>
            > <a href="">組織案内</a>
            >  地方支分部局
        </p>
    </div>

    div要素を使用。リンクはp要素内にa要素を入れ、セパレーターはHTML内に文字参照で作成しています。現在位置はp要素のテキストノード。

    音声読み上げソフト(NVDA)では、上記例を「トップページ 大なり 組織案内 大なり 地方支分部局」とセパレーターも含めて読み上げます。

  • 例3) 東京都

    上記サイトのパンくずリスト用HTMLの構造を簡略化して表記。

    <div>
        <p><a href="">トップページ</a> > 
            <a href="">教育・文化・スポーツ</a> > 
            <a href="">観光</a> > 
            東京都の観光情報
        </p>
    </div>

    div要素を使用。リンクはp要素内にa要素を入れ、セパレーターはHTML内に文字参照で作成しています。現在位置はp要素のテキストノード。

    音声読み上げソフト(NVDA)では、上記例を「トップページ 大なり 教育・文化・スポーツ 大なり 観光」とセパレーターも含めて読み上げます。

  • 例4) パナソニック

    上記サイトのパンくずリスト用HTMLの構造を簡略化して表記。

    <nav>
        <ol>
        <li><a href="">個人向けトップ</a></li>
        <li><a href="">生活家電</a></li>
        <li><span>洗濯機</span></li>
        </ol>
    </nav>

    nav要素を使用。リンクはol要素内にa要素を入れ、セパレーターはCSSのcontentで作成しています。現在位置は、span要素で表現。

    音声読み上げソフト(NVDA)では、上記例を「個人向けトップ 生活家電 洗濯機」と読み上げます。

作り方のルールは?

いくつか基本的なルールがありますので、確認していきましょう。

  1. パンくずリストの表示位置は統一し、決まった場所に表示します。上でも下でも問題ありません。
  2. 区切り文字は、音声ブラウザで読み上げられないように工夫し、画像やCSSを推奨します。
  3. 最上位の階層に戻るリンクの文字は「ホーム」とします。
  4. パンくずリストはどんなサイトにも必要です。現在地を示す場合、グローバルナビゲーションにも現在地がわかるような工夫します。
  5. トップページには不要です。グローバルナビゲーションにトップページにいることがわかるように工夫します。
以下にol要素を使用した一般的なパンくずリストの雛形を示します。
<nav>
  <ol>
    <li>
      <a href="/">ホーム</a>
    </li>
    <li>
      <a href="/spots/">釣りスポット</a>
    </li>
    <li>
    ルーアン
    </li>
  </ol>
</nav>


QUESTION


  • avatar
    書き方が統一されていないようだけど?

    パンくずリストの書き方は一般化されていないのかい? どの書き方が正解かわからないな?

  • よく直面する問題だわ・・・

    マークアップエンジニアの価値観や解釈の違いによって書き方が 違ってくることが多々あるわ。それだけHTMLの表現の幅が広いって証拠かしら・・・。 どれも正解だし、間違いではないわね。ただ、Webで必須のパーツにも関わらず統一がないってひどい感じがするわ・・・。

    avatar
  • avatar
    nav要素=パンくずなのかい?

    グローバルナビゲーションもnav要素でマークアップし、パンくずリストもnav要素かい? 両方ともnav要素だったら、どっちかメインナビゲーションでどっちがパンくずか区別できるのかい?

  • たしかにそうね・・・。

    nav要素は、nav要素。それ以上の機能が無いわ。それは、divにしてもそう。 つまり、パンくずリストのマークアップに少しだけ機能を付け足して、パンくずリストだって示す必要があるわね。

    avatar
  • avatar
    そんな事ができるのかい?

    HTMLタグの属性を見てもそんな機能は無いけど?

  • HTML機能を拡張する必要があるわね!

    いくつか方法があって、JSON-LD、Microdata、RDFaを使ってHTMLにメタデータを埋め込む方法があるわ。 HTMLをより構造的にする方法を使ってパンくずリストを更に意味のあるものにしてみましょう。

    avatar

メタデータとは?1冊の本を想像してみましょう。 本にはタイトルがあり、著者、出版日等、その本の特徴を示す情報があります。 例えば、本と言う情報を管理する上で、必要な情報としてタイトルなどの情報が必要になるわけです。 このタイトルや著者など”情報のための情報”をメタデータを呼んでいます。

HTMLをより構造化する

では、先程登場したJSON-LD、Microdata、RDFaについて見ていきましょう。

メタデータを埋め込むと先程は説明しましたが、誰もが勝手に独自のルールを決めデータを詰め込むことができるとしたら、 それは意味の無い表現に過ぎません。

では、誰がどうやって共通のルールを決めているかと言うと、 インターネット上の構造化データのスキーマを作成、維持、促進を行っているSchema.orgと呼ばれる団体がルールの策定を行っています。 (Schema.orgは、Google、Microsoft、Yahoo、Yandexが共同で設立した団体です。)

Schema.orgでは、主要な検索エンジン(Google、Microsoft、Yahoo等)が理解できる方法でページをマークアップするために使用できる構造化データを提供しています。

構造化データをHTMLに組み込む仕組みこそが、JSON-LD、Microdata、RDFaになります。

Schema.org公式サイト

どんな構造化データがあるの?

本当に沢山のルールがあります。ニュースや料理のレシピ、商品やイベント情報など様々なデータが定義されています。 今回は、パンくずリストですので、パンくずリストに焦点を当てて紹介していきます。

興味のある方は、以下googleの構造化データギャラリーも御覧ください。

構造化データギャラリー

Microdataを使用した構造化

では早速、Microdataを用いたパンくずリストのマークアップを見ていきましょう。

Microdataは、直接HTMLに属性を追加することで、構造化を行います。

Microdataとは、人やレシピ、イベントや本等Webページ上で共通して登場するもの表現するための記述パターンです。 今回は、パンくずリストを作成しますので、https://schema.org/BreadcrumbListを用いて構造化します。 (今回はMicrodataの入門記事ではありませんので、結果と必要な情報のみを提示します。)

では、先ほど示したパンくずリストをMicrodataを用いて記述したものを見てみましょう。

Microdata

<nav>
  <ol itemscope itemtype="https://schema.org/BreadcrumbList">
    <li itemprop="itemListElement" 
        itemscope itemtype="http://schema.org/ListItem">
         <a itemprop="item" href="/">
             <span itemprop="name">ホーム</span>
         </a>
        <meta itemprop="position" content="1" />
    </li>
    <li itemprop="itemListElement" 
        itemscope itemtype="http://schema.org/ListItem">
         <a itemprop="item" href="/spots/">
             <span itemprop="name">釣りスポット</span>
         </a>
        <meta itemprop="position" content="2" />
    </li>
    <li itemprop="itemListElement" 
        itemscope itemtype="http://schema.org/ListItem">
        < itemprop="name">ルーアン</span>
        <meta itemprop="position" content="3" />
    </li>
  </ol>
</nav>

さて、基本構造はそれほど変わっていませんが、たくさんの属性が追加されましたね。少しだけ説明いたします。

  • itemscope属性はHTMLの要素に対して特定の構造化データを持っていることを示します。
  • itemtype属性で実際にどんな構造化データを持っているかを伝えます。 今回は、https://schema.org/BreadcrumbListを設定することでパンくずリストの構造化データを持っていると伝えたことになります。
  • itemprop属性は意味を付与する属性です。情報のための情報を付与します。
  • span要素のitemprop属性にnameと言う意味を与えパンくずリストの名前を示しています。
  • meta要素が追加となり、itemprop属性を用いてpositionと言う意味付けをします。 positionはリスト内での位置を表し、最上位階層を1とし、階層が深くなるに連れ加算した値をcontent属性に設定します。

最後に作成した構造化データのチェックは以下のサイトで行うことができます。

構造化データテストツール

RDFaを使用した構造化

では、続いてRDFa(正確には、RDFa Liteです)を用いた構造化の例です。RDFaも直接HTMLに属性を追加することで、構造化を行います。

rdfa-lite

<nav>
    <ol vocab="http://schema.org/" typeof="BreadcrumbList">
      <li property="itemListElement" typeof="ListItem">
        <a property="item" typeof="WebPage" href="/">
         <span property="name">ホーム</span></a>
         <meta property="position" content="1">
      </li>
      <li property="itemListElement" typeof="ListItem">
        <a property="item" typeof="WebPage" href="/spots/">
         <span property="name">釣りスポット</span></a>
         <meta property="position" content="2">
      </li>
      <li property="itemListElement" typeof="ListItem">
         <span property="name">ルーアン</span>
         <meta property="position" content="3">
      </li>
    </ol>
</nav>

さて、こちらも基本構造はそれほど変わっていませんが、たくさんの属性が追加されましたね。少しだけ説明いたします。

  • vocab属性はHTMLの要素に対して特定の構造化データを持っていることを示します。 schema.org で定義される語彙を使用すると宣言します。
  • typeof属性で実際にどんな構造化データを持っているかを伝えます。 今回は、BreadcrumbListを設定することでパンくずリストの構造化データを持っていると伝えたことになります。
  • property属性は意味を付与する属性です。情報のための情報を付与します。
  • span要素のproperty属性にnameと言う意味を与えパンくずリストの名前を示しています。
  • meta要素が追加となり、property属性を用いてpositionと言う意味付けをします。 positionはリスト内での位置を表し、最上位階層を1とし、階層が深くなるに連れ加算した値をcontent属性に設定します。

JSON-LDを使用した構造化

JSON-LD(JSON for Linked Data)の説明の前に、まずJSONとはJavaScript等のプログラミング言語で利用されているデータ形式のことです。

JSON自体には特段意味はなく、開発者が自由に構造を定義することが可能です。

Linked Dataとは、JSONが決まりのない自由なデータ形式であるのに対して、データ構造に意味を持たせたものと言えます。 つまり、https://schema.org/で示されるデータ構造を、JSONと言うデータ構造とリンクさせることで、意味のあるデータにすることができます。

MicrodataやRDFaとの決定的な違いは、HTMLを汚染しないことです。メタ情報とHTMLを分離し記述することができます。

json-ld

<script type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": [
            {
                "@type": "ListItem",
                "position": 1,
                "name": "釣り公師団",
                "item": "https://example.com/"
            },{
                "@type": "ListItem",
                "position": 2,
                "name": "釣りスポット",
                "item": "https://example.com/spots/"
            },{
                "@type": "ListItem",
                "position": 3,
                "name": "ルーアン",
                "item": "https://example.com/spots/rouen.html"
            }
        ]
    }
</script>

だいぶ記述の仕方が変わりましたね?と言うより元のHTMLは全く触っておらず、新たなデータを作成しています。

<script type="application/ld+json">〜</script>の中にJSON-LDのコードを記述します。 script要素はHTMLのhead要素内またはbody要素内のどちらに配置しても問題ありませんが、メタデータと言う性質上、head内が適切かと思います。

JSONに触れたことがある方は、馴染みのある記述方法ですね。{}はオブジェクトを表し、[]は配列を表しています。 {}で囲んだオブジェクト内の最後の要素にはカンマ(,)は不要です。同様に、配列最後のオブジェクト要素も(,)が不要です。

現在位置を示すルーアンはitemを省略して記述できます。その場合パンくずリストを設定しているページのURLを検索エンジンは使用します。 今回は絶対パスでの指定をしていますが、相対URLでも問題ありません。

JSON-LDの場合画面上に表示されるわけではありませんので、ホームの文字をサイトタイトルに置き換えています。


QUESTION


  • avatar
    どれも結局一緒だろう?

    表現の違いだけでどれも目的は一緒だろう? どれを使えばいいんだい?好みの問題なのか?

  • どれでもいいわ?

    と言いたいところだけど、それだと困るでしょう?世の中的には、構造化データはJSON-LDを 推奨する動きになりつつあるわ。現にGoogleでは構造化データの記述にJSON-LDを推奨しているの。

    構造化データの仕組みについて

    avatar
  • avatar
    JSON-LDを推奨?

    そもそもの出発点は、HTMLのパンくずリストの意味付けだったはずだが? JSON-LDは、HTMLを汚染しない代わりにHTMLに意味を持たせることはできないじゃないか?

  • 確かに言うとおりね。

    できないわけじゃないわ。WAI-ARIAを使って、HTML要素に"意味"を追加する方法を学びましょう。

    avatar

WAI-ARIAとは?

と、その前にウェブアクセシビリティと言う言葉について理解する必要があります。 ウェブアクセシビリティとは、ウェブサイトの情報や機能の利用しやすさを意味します。

健常者も身体的ハンディキャップを持った人も、 パソコンやモバイル端末等様々な環境の人にも利用しやすくすることです。

WAI-ARIA(Accessible Rich Internet Applications)とは、 ブラウザや支援技術が認識できるさらなる意味をHTMLに追加することによって閲覧のしやすさを向上させ、ウェブサイト利用者の理解を助ける為の技術となります。

アクセシビリティについて詳しく知りたい場合は、下記サイトをご覧ください。

ウェブアクセシビリティ基盤委員会公式サイト

WAI-ARIA日本語訳

WAI-ARIAを使ってみよう

WAI-ARIAの基本は、HTML要素に適用できる追加の意味を定義しています。

この仕様では、主に次の3つの機能があります。 ロール(Role)属性は意味を、プロパティ(Property)属性は性質を、 ステート(State)属性は状態を定義しています。

これらを使いHTMLに意味付けを行うことができます。

W3Cでは、WAI-ARIAの実装例をWAI-ARIA Authoring Practices 1.1で 公開しております。今回は、パンくずリストの項目について取り上げます。

WAI-ARIA Breadcrumb

では、さっそく先ほどのページのサンプルを見てみましょう。

<nav class="breadcrumb" aria-label="Breadcrumb">
  <ol>
    <li>
      <a href="../../">
        WAI-ARIA Authoring Practices 1.1
      </a>
    </li>
    <li>
      <a href="../../#aria_ex">
        Design Patterns
      </a>
    </li>
    <li>
      <a href="../../#breadcrumb">
        Breadcrumb Pattern
      </a>
    </li>
    <li>
      <a aria-current="page" href="./index.html">
        Breadcrumb Example
      </a>
    </li>
  </ol>
</nav>

aria-labelは、nav要素で提供されるナビゲーションのタイプを説明するラベルを提供します。

aria-current="page"は、セット内の最後のリンクに適用され、現在のページを表していることを示します。 (この属性は、a要素にのみ適用されます。)

aria-labelは、サンプルではbreadcrumbとなっていますが、英語表記でかつ日本人にはなじみのない単語です。

実は、オリンピックのウェブサイトでは「現在位置」として表記しています。ここでは、より意味が伝わる「現在位置」を採用します。

また、現在位置を示す文字もURLを指定しハイパーリンクとして書かれていますが、現在位置は一般的にリンクは不要です。 ここでは、hrefを伴わないa要素でマークアップに変更します。

下記例では、「現在位置 ホーム 釣りスポット ルーアン」と音声ブラウザで読まれることになります。

WAI-ARIAを盛り込んだサンプルを提示します。
<nav class="breadcrumb" aria-label="現在位置">
  <ol >
    <li>
      <a href="/">ホーム</a>
    </li>
    <li>
      <a href="/spots/">釣りスポット</a>
    </li>
    <li>
    <a aria-current="page">ルーアン</a>
    </li>
  </ol>
</nav>

JSON-LD+WAI-ARIAのサンプル

簡単にパンくずリストを装飾してみましょう。先ほどのWAI-ARIAのサンプルページのコードを少しだけ変更したものを 掲載しておきます。セパレーターを矢印に変更したのみです。

nav.breadcrumb {
    padding: 0.8em 1em;
    border: 1px solid hsl(0, 0%, 90%);
    border-radius: 4px;
    background: hsl(300, 14%, 97%);
}
nav.breadcrumb ol {
    margin: 0;
    padding-left: 0;
    list-style: none;
}

nav.breadcrumb li {
    display: inline;
}

nav.breadcrumb li + li::before {
    display: inline-block;
    margin: 0 0.25em;
    height: 0.8em;
    content:url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSI4IiBoZWlnaHQ9IjgiPjxwYXRoIGQ9Ik0yLjUgMEwxIDEuNSAzLjUgNCAxIDYuNSAyLjUgOGw0LTQtNC00eiIgZmlsbD0iY3VycmVudENvbG9yIi8+PC9zdmc+)
}
nav.breadcrumb [aria-current="page"] {
    color: #000;
    font-weight: 700;
    text-decoration: none;
}
<!DOCTYPE html>
<html lang="ja-JP">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script type="application/ld+json">
    {
        "@context": "https://schema.org",
        "@type": "BreadcrumbList",
        "itemListElement": [
            {
                "@type": "ListItem",
                "position": 1,
                "name": "釣り公師団",
                "item": "https://example.com/"
            },{
                "@type": "ListItem",
                "position": 2,
                "name": "釣りスポット",
                "item": "https://example.com/spots/"
            },{
                "@type": "ListItem",
                "position": 3,
                "name": "ルーアン",
                "item": "https://example.com/spots/rouen.html"
            }
        ]
    }
    </script>
</head>
<body>
    <nav class="breadcrumb" aria-label="現在位置">
        <ol >
          <li>
            <a href="/">ホーム</a>
          </li>
          <li>
            <a href="/spots/">釣りスポット</a>
          </li>
          <li>
          <a aria-current="page">ルーアン</a>
          </li>
        </ol>
      </nav>
</body>
</html>


COMPLETE


  • avatar
    お疲れ様でした!

    今回は、パンくずリストの概念・構造化データの基礎を学びました。

    見た目だけを意識するのではなく、構造を意識して楽しくマークアップしていきましょう。


SKILL


習得スキルボード

  • パンくずリストの作り方
  • 構造化データ入門

コメント