「ページトップへ戻るボタン」のフォーカス問題

いわゆる「ページトップへ戻るボタン」は <a href=#top> で実装されることが多いのですが、コンテンツ内での id=top の有無でフォーカスナビゲーションの挙動が変わります。

<body>
  <!-- フォーカス位置は変わらない -->
  <a href="#top"><img src="back-to-the-top.svg" alt="ページトップへ戻る" /></a>
</body>
<body id="top">
  <!-- コンテンツの先頭部へフォーカスが移動する -->
  <a href="#top"><img src="back-to-the-top.svg" alt="ページトップへ戻る" /></a>
</body>

これは HTML 仕様で定義された挙動(WHATWG)なのですが、閲覧者の立場からすると違和感を覚えるため常に id 属性を設定することで解決できる(zenn.dev)との意見も見られます。

しかし「ページトップへ戻るボタン」と似た機能を持つ Home キーや Ctrl + ↑ キーではフォーカスは移動しません。Tab キーによるフォーカス操作に配慮して id=top を設定すると、今度は別のキー操作と一貫性のない挙動になってしまうのです。

操作 スクロール位置 フォーカス位置 セッション履歴
Home キー 先頭へ移動 不変 不変
ページトップへ戻る 先頭へ移動 不変(id=top 設定時は移動) 更新

つまり Home キーはスクロールを行うものに対して、「ページトップへ戻るボタン」は通常のリンクと同じくナビゲートするものという違いがあります。すなわちフォーカスを移動させるべきかどうかは「何のために戻るボタンを配置しているのか」の目的次第と言えるでしょう。

  • 戻るボタンを「最上部へスクロールするもの」と捉えるならフォーカス位置は変わらず、セッション履歴も更新されないのが自然
  • 戻るボタンを「最上部のコンテンツへリンクを張るもの」(「ページ内リンク」の一種)と捉えるなら宛先の id 属性を設定してフォーカス位置を移動させる

統計を取ったわけではなく主観に過ぎないのですが、「ページトップへ戻るボタン」を配置しているサイトの多くは前者、すなわち Home キーの代替を意図しているのではないでしょうか。だとするとフォーカス位置が移動するのはむしろ不自然であり、id 属性は設定しない方がよいですし、うっかり設定することのないよういっそ文字列 "top" の設定を禁止しても良いかもしれません。

// Markuplint での設定例

/** @type {import('@markuplint/ml-config').Config} */
export default {
  rules: {
    'invalid-attr': {
      options: {
        disallowAttrs: [
          {
            name: 'id',
            value: {
              enum: ['top'],
            },
          },
        ],
      },
    },
  },
};

またこの場合リンクではなくボタン(<button> 要素)が適切になるのですが、しかしこれまで慣習的にリンクで実装されており、ユーザーはセッション履歴が更新される(「ページトップへ戻るボタン」で先頭へスクロールした後にブラウザバックでふたたび元の位置に戻る)ことを期待しているでしょうから、ここは慣例に合わせた方がよいと考えることもできます。

まとめると「ページトップへ戻るボタン」のアクセシビリティ上の問題とは、以下に挙げるように複数の根深い原因が絡み合っている状況と言えます。

  • 制作者の意図と挙動が合致していないケースが多い
  • 本来の意図と慣例がマッチしておらず、あるべきマークアップを目指したところで、むしろユーザーに混乱が起こりうる
  • マークアップの仕方によってはフォーカス位置が変わらないのにセッション履歴が更新されるという、通常のリンクやボタンでは見られない特殊な挙動となる
  • HTML 仕様でも Issue が上がっている[1]が、解決していない

脚注