Skip to main content

无障碍

SvelteKit 默认努力为您的应用程序提供一个无障碍的平台。Svelte 的编译时无障碍检查也将适用于您构建的任何 SvelteKit 应用程序。

以下是 SvelteKit 内置无障碍功能的工作原理,以及您需要做什么来帮助这些功能尽可能好地工作。请记住,虽然 SvelteKit 提供了无障碍的基础,但您仍然要负责确保您的应用程序代码是无障碍的。如果您是无障碍新手,请参阅本指南的“进一步阅读”部分获取更多资源。

我们认识到实现无障碍可能很困难。如果您想就 SvelteKit 处理无障碍的方式提出改进建议,请提交 GitHub issue

路由公告

在传统的服务端渲染应用程序中,每次导航(例如点击 <a> 标签)都会触发完整的页面重载。当这种情况发生时,屏幕阅读器和其他辅助技术会读出新页面的标题,让用户理解页面已经改变。

由于 SvelteKit 中页面之间的导航无需重新加载页面(称为客户端路由),SvelteKit 在页面上注入了一个实时区域,在每次导航后读出新页面名称。它通过检查 <title> 元素来确定要宣布的页面名称。

因此,您应用程序中的每个页面都应该有一个独特的、描述性的标题。在 SvelteKit 中,您可以通过在每个页面上放置 <svelte:head> 元素来实现:

src/routes/+page
<svelte:head>
	<title>待办事项列表</title>
</svelte:head>

这将使屏幕阅读器和其他辅助技术能够在导航发生后识别新页面。提供描述性标题对于 SEO 也很重要。

焦点管理

在传统的服务端渲染应用程序中,每次导航都会将焦点重置到页面顶部。这确保了使用键盘或屏幕阅读器浏览网页的人可以从页面开始处开始交互。

为了在客户端路由期间模拟这种行为,SvelteKit 在每次导航和增强型表单提交后会将焦点设置在 <body> 元素上。有一个例外 - 如果存在带有 autofocus 属性的元素,SvelteKit 将转而聚焦该元素。使用该属性时,请确保考虑对辅助技术的影响

如果您想自定义 SvelteKit 的焦点管理,可以使用 afterNavigate 钩子:

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
@type{HTMLElement | null}
to_focus
= var document: Documentdocument.ParentNode.querySelector<Element>(selectors: string): Element | null (+4 overloads)

Returns the first element that is a descendant of node that matches selectors.

MDN Reference

querySelector
('.focus-me');
const to_focus: Element | null
@type{HTMLElement | null}
to_focus
?.focus();
});

您也可以使用 goto 函数以编程方式导航到不同的页面。默认情况下,这将具有与点击链接相同的客户端路由行为。但是,goto 也接受一个 keepFocus 选项,该选项将保留当前聚焦的元素,而不是重置焦点。如果启用此选项,请确保当前聚焦的元素在导航后仍然存在于页面上。如果该元素不再存在,用户的焦点将丢失,这会让辅助技术用户感到困惑。

“lang” 属性

默认情况下,SvelteKit 的页面模板将文档的默认语言设置为英语。如果您的内容不是英语,您应该更新 src/app.html 中的 <html> 元素,使其具有正确的 lang 属性。这将确保任何阅读文档的辅助技术使用正确的发音。例如,如果您的内容是德语,您应该将 app.html 更新为:

src/app
<html lang="de"></html>

如果您的内容提供多种语言,您应该根据当前页面的语言设置 lang 属性。您可以使用 SvelteKit 的 handle hook来实现:

src/app
<html lang="%lang%"></html>
src/hooks.server
/** @type {import('@sveltejs/kit').Handle} */
export function 
function handle({ event, resolve }: {
    event: any;
    resolve: any;
}): any
@type{import('@sveltejs/kit').Handle}
handle
({ event: anyevent, resolve: anyresolve }) {
return resolve: anyresolve(event: anyevent, {
transformPageChunk: ({ html }: {
    html: any;
}) => any
transformPageChunk
: ({ html: anyhtml }) => html: anyhtml.replace('%lang%', function get_lang(event: any): string
@paramevent
get_lang
(event: anyevent))
}); }
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: Handlehandle:
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.

@paraminput the html chunk and the info if this is the last chunk
transformPageChunk
: ({ html: stringhtml }) => html: stringhtml.String.replace(searchValue: string | RegExp, replaceValue: string): string (+3 overloads)

Replaces text in a string, using a regular expression or search string.

@paramsearchValue A string or regular expression to search for.
@paramreplaceValue A string containing the text to replace. When the {@linkcode searchValue} is a RegExp, all matches are replaced if the g flag is set (or only those matches at the beginning, if the y flag is also present). Otherwise, only the first match of {@linkcode searchValue} is replaced.
replace
('%lang%', function get_lang(event: any): string
@paramevent
get_lang
(event: RequestEvent<Partial<Record<string, string>>, string | null>event))
}); };

进一步阅读

在大多数情况下,构建无障碍 SvelteKit 应用程序与构建无障碍 Web 应用程序是一样的。您应该能够将以下通用无障碍资源中的信息应用到您构建的任何 Web 体验中:

在 GitHub 编辑此页面

上一页 下一页