Accessibility
SvelteKit は、アプリにアクセシブルなプラットフォームをデフォルトで提供するよう努めています。Svelte の コンパイル時のアクセシビリティチェック(compile-time accessibility checks) は、あなたがビルドする SvelteKit アプリケーションにも適用されます。
ここでは、SvelteKit の組み込みのアクセシビリティ(accessibility)機能がどのように動作するか、そしてこれらの機能が可能な限りうまく動作するようにするために必要なことについて説明します。SvelteKit はアクセシブルな基盤を提供しますが、アプリケーションのコードをアクセシブルにするのはあなたの責任であることを覚えておいてください。もし、アクセシビリティ(accessibility)についてよく知らないのであれば、このガイドの “参考文献” セクションで、その他のリソースを参照してください。
私たちは、アクセシビリティ(accessibility)を正しく行うのは難しいことだと認識しています。SvelteKit のアクセシビリティ対応について改善を提案したい方は、GitHub issue を作成 してください。
Route announcements
旧来のサーバーレンダリングアプリケーションでは、全てのナビゲーション (例えば、<a>
タグをクリックするなど) で、ページのフルリロードを引き起こします。これが起こると、スクリーンリーダーやその他の支援技術が新しいページのタイトルを読み上げ、それによってユーザーはページが変更されたことを理解します。
SvelteKit では、ページ間のナビゲーションではページのリロードが発生しないため (クライアントサイドルーティングとして知られる)、SvelteKit はナビゲーションごとに新しいページ名が読み上げられるようにライブリージョンをページに注入します。これは、<title>
要素を検査することで、アナウンスするページ名を決定します。
この動作のために、アプリの全ページにユニークで説明的なタイトルを付けるべきです。SvelteKit では、各ページに <svelte:head>
要素を配置することでこれを行うことができます:
<svelte:head>
<title>Todo List</title>
</svelte:head>
これにより、スクリーンリーダーやその他の支援技術が、ナビゲーション後に新しいページを識別することができるようになります。説明的なタイトルを提供することは、SEO にとっても重要なことです。
フォーカス管理
旧来のサーバーレンダリングアプリケーションでは、ナビゲーションでフォーカスがページのトップにリセットされます。これによって、キーボードやスクリーンリーダーを使用して web をブラウジングする方が、ページの先頭からやり取りできるようになります。
クライアントサイドルーティング中にこの挙動をシミュレートするために、SvelteKit は各ナビゲーションや 強化されたフォーム送信(enhanced form submission) の後、<body>
要素にフォーカスを合わせます。1つ例外があります - autofocus
属性が付いている要素が存在する場合、SvelteKit はその要素にフォーカスを合わせます。この属性を使用するときは、支援技術(assistive technology)に対する影響を必ず考慮してください。
SvelteKit のフォーカス管理をカスタマイズしたい場合は、afterNavigate
hook を使います:
import { function afterNavigate(callback: (navigation: import("@sveltejs/kit").AfterNavigate) => void): void
A lifecycle function that runs the supplied callback
when the current component mounts, and also whenever we navigate to a new URL.
afterNavigate
must be called during a component initialization. It remains active as long as the component is mounted.
afterNavigate } from '$app/navigation';
function afterNavigate(callback: (navigation: import("@sveltejs/kit").AfterNavigate) => void): void
A lifecycle function that runs the supplied callback
when the current component mounts, and also whenever we navigate to a new URL.
afterNavigate
must be called during a component initialization. It remains active as long as the component is mounted.
afterNavigate(() => {
/** @type {HTMLElement | null} */
const const to_focus: Element | null
to_focus = var document: Document
document.ParentNode.querySelector<Element>(selectors: string): Element | null (+4 overloads)
Returns the first element that is a descendant of node that matches selectors.
querySelector('.focus-me');
const to_focus: Element | null
to_focus?.focus();
});
goto
関数を使用して、プログラムで別のページにナビゲーションさせることもできます。デフォルトでは、これはクライアントサイドルーティングでリンクをクリックするのと同じ動作です。しかし goto
は、keepFocus
オプション を受け付けます。このオプションは、フォーカスをリセットする代わりに、現在フォーカスされている要素にフォーカスを保持したままにします。このオプションを有効にする場合は、現在フォーカスされている要素がナビゲーション後にもまだ存在することを確かめてください。もしその要素が存在しなければ、ユーザーのフォーカスは失われ、支援技術のユーザーにとって混乱した体験になります。
The “lang” attribute
デフォルトでは、SvelteKit のページテンプレートには、ドキュメントのデフォルト言語に英語が設定されています。もしコンテンツが英語でない場合、src/app.html
の <html>
要素を更新し、正しい lang
属性を持たせる必要があります。これによって、ドキュメントを読む支援技術が正しい発音を使えるようになります。例えば、コンテンツがドイツ語の場合、app.html
を以下のように更新してください:
<html lang="de">
コンテンツが複数の言語で使用可能な場合、開いているページの言語に基づいて lang
属性を設定できるようにする必要があります。これは、SvelteKit の handle hook を使用して行うことができます:
<html lang="%lang%">
/** @type {import('@sveltejs/kit').Handle} */
export function function handle({ event, resolve }: {
event: any;
resolve: any;
}): any
handle({ event: any
event, resolve: any
resolve }) {
return resolve: any
resolve(event: any
event, {
transformPageChunk: ({ html }: {
html: any;
}) => any
transformPageChunk: ({ html: any
html }) => html: any
html.replace('%lang%', function get_lang(event: any): string
get_lang(event: any
event))
});
}
import type { type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle } from '@sveltejs/kit';
export const const handle: Handle
handle: type Handle = (input: {
event: RequestEvent;
resolve(event: RequestEvent, opts?: ResolveOptions): MaybePromise<Response>;
}) => MaybePromise<...>
The handle
hook runs every time the SvelteKit server receives a request and
determines the response.
It receives an event
object representing the request and a function called resolve
, which renders the route and generates a Response
.
This allows you to modify response headers or bodies, or bypass SvelteKit entirely (for implementing routes programmatically, for example).
Handle = ({ event: RequestEvent<Partial<Record<string, string>>, string | null>
event, resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve }) => {
return resolve: (event: RequestEvent, opts?: ResolveOptions) => MaybePromise<Response>
resolve(event: RequestEvent<Partial<Record<string, string>>, string | null>
event, {
ResolveOptions.transformPageChunk?(input: {
html: string;
done: boolean;
}): MaybePromise<string | undefined>
Applies custom transforms to HTML. If done
is true, it’s the final chunk. Chunks are not guaranteed to be well-formed HTML
(they could include an element’s opening tag but not its closing tag, for example)
but they will always be split at sensible boundaries such as %sveltekit.head%
or layout/page components.
transformPageChunk: ({ html: string
html }) => html: string
html.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)
Replaces text in a string, using a regular expression or search string.
replace('%lang%', function get_lang(event: any): string
get_lang(event: RequestEvent<Partial<Record<string, string>>, string | null>
event))
});
};
その他の参考情報
ほとんどの場合、アクセシブルな SvelteKit アプリを構築するのはアクセシブルな Web アプリを構築するのと同じです。以下の一般的なアクセシビリティ(accessibility)に関するリソースから得られる情報は、どんな Web エクスペリエンスを構築する場合でも適用できるはずです