SPA のアクセシビリティを強化する Nuxt の Route Announcer 機能

2024/07/01に公開

SPA におけるアクセシビリティ課題について

シングルページアプリケーション(SPA)は、1つのHTMLファイルに対してJavaScriptとWeb APIを活用して、ユーザーに素早いページ切り替えの体験を提供するウェブアプリケーションの一形態です。

しかし、SPAにはアクセシビリティの課題があります。例えば、視覚障害のあるユーザーが使うスクリーンリーダーという支援技術ではページが遷移したことを認識できないことがあります。これは、JavaScriptを使ってページを切り替える際に発生する問題です。

具体的には、ユーザーがあるページから別のページへ移動した際、スクリーンリーダーが新しいページに移動したことを認識しないことがあります。

この問題を解決するために、JavaScriptとWAI-ARIAという技術を使って、Route Announcerという方法があります。これを活用することでページ遷移時にスクリーンリーダーへ新しいページの情報を伝えることができます[1]

多くのフレームワーク(GatsbyJS、Next.js、SvelteKit、Astroなど)ではこの方法が実装されていますが、Nuxtではこれまで未実装でした。

この問題点をNuxtにてどのように解消するかについてを昨年のVue Fes Japan 2023のやまのくよりRoute Announcer相応のコンポーネントを作る方法を発表しました[2]

ですが、この度Nuxt 3.12よりアクセシビリティの向上の項目で <NuxtRouteAnnouncer> コンポーネントと useRouteAnnouncer composables関数が導入されました。

どのような挙動をしてくれるのか

初期インストールされたデフォルトの状態のままだと特に変化は見られないのですが、各ページにて useHeadtitle を指定することでその真価が発揮されます。

リンクをクリックしてページが切り替わっているがスクリーンリーダーにはなにも通知されていない

title がない状態だとページが切り替わっても特に変化がみられません。

aboutへのリンクをクリックして「About」、indexへのリンクをクリックして「Home」とスクリーンリーダーへ通知が届いている

ですが title を設定することで、ページが切り替わったあとにその内容が読み上げられるようになっています。

Route Announcer を構成するコンポーネントと関数

次にNuxt上で動くRoute Announcerを構成するコンポーネントとcomposables関数のそれぞれについてを紹介していきます。

<NuxtRouteAnnouncer>

スクリーンリーダーのために、ページタイトル要素を取得して通知するためのコンポーネントです。

Route Announcerコンポーネントです。Nuxt 3.12で初期インストールすると以下のように app.vue に導入されます。

<template>
  <div>
    <NuxtRouteAnnouncer />
    <NuxtWelcome />
  </div>
</template>

全体のレイアウトコンポーネントか、ページコンポーネントに設置して使います。

具体的な説明は @splendente さんが紹介していますのでそちらをご参照ください。

https://zenn.dev/splendente/articles/nuxt-route-announcer-verification

useRouteAnnouncer

ページタイトルの変更を監視し、それに応じてアナウンサーメッセージを更新するcomposables関数です。<NuxtRouteAnnouncer>はこの関数を活用して組み立てられています。Unheaddom:rendered にフックして、ページのタイトルを読み取り、スクリーンリーダーへの通知される仕組みになっています。

<script setup lang="ts">
  const { message, politeness, set, polite, assertive } = useRouteAnnouncer();
</script>

useRouteAnnouncer は引数に politeness を受取り、off(通知を切る)、polite(すべての通知が終わった後に通知する)、assertive(即座に通知する)のいずれかを設定できます。デフォルトの値は polite になっています。

useRouteAnnouncer からは以下プロパティやメソッドが利用できるようになります。

  • message ... 読み上げられるメッセージ部分
  • politeness ... スクリーンリーダーの読み上げ方法。off, polite, assertive が設定できます
  • set(message, politeness = "polite") ... messageとpolitenessを設定するメソッド
  • polite(message) ... politenessを polite に設定して set() を実行するメソッド
  • assertive(message) ... politenessを assertive に設定して set() を実行するメソッド

Nuxtのアクセシビリティ向上への取り組み

今回導入された <NuxtRouteAnnouncer> の取り組み以外にもアクセシビリティに関する機能を充実させるものが進められています。

ロードマップから、Nuxt内部にaxe-coreというアクセシビリティチェックツールのビルトインやナビゲーションにおけるフォーカス管理、スキップリンクの生成なども予定されています。

https://github.com/nuxt/nuxt/issues/23255

まとめ

この記事では、Nuxtのクライアントサイドルーティング時のアクセシビリティ課題を解消するための <NuxtRouteAnnouncer> について紹介しました。

アクセシビリティ向上における開発者への負担軽減が期待されるので、ぜひ3.12.2以降にアップデートして使ってみてください。

脚注
  1. 実装の詳細については令和最新Route Announcer事情より参照ください。 ↩︎

  2. 発表資料は画面遷移から考えるNuxtアプリケーションをアクセシブルにする方法を参照ください。 ↩︎

GitHubで編集を提案
Vue・Nuxt 情報が集まる広場 / Plaza for Vue・Nuxt.

Discussion