无障碍访问
SvelteKit 努力默认提供一个可访问的应用平台。Svelte 的 编译时无障碍访问检查 也将应用于您构建的任何 SvelteKit 应用程序。
以下是 SvelteKit 的内置无障碍访问功能的工作原理,以及您需要采取哪些措施来帮助这些功能尽可能好地发挥作用。请记住,虽然 SvelteKit 提供了可访问的基础,但您仍然有责任确保您的应用程序代码可访问。如果您不熟悉无障碍访问,请参阅本指南的 “进一步阅读” 部分以获取其他资源。
我们认识到无障碍访问可能难以实现。如果您想建议改进 SvelteKit 如何处理无障碍访问,请 打开一个 GitHub 问题。
路由公告
在传统的服务器端渲染应用程序中,每次导航(例如,点击 <a>
标签)都会触发完整页面重新加载。发生这种情况时,屏幕阅读器和其他辅助技术将朗读新页面的标题,以便用户了解页面已更改。
由于 SvelteKit 中的页面间导航无需重新加载页面(称为 客户端路由),因此 SvelteKit 会在页面上注入一个 实时区域,该区域将在每次导航后朗读新页面名称。它通过检查 <title>
元素来确定要宣布的页面名称。
由于此行为,您的应用中的每个页面都应具有唯一且描述性的标题。在 SvelteKit 中,您可以通过在每个页面上放置一个 <svelte:head>
元素来实现此目的
<svelte:head>
<title>Todo List</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
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
选项,该选项将保留当前聚焦的元素,而不是重置焦点。如果启用此选项,请确保当前聚焦的元素在导航后仍存在于页面上。如果该元素不再存在,则用户的焦点将丢失,这会导致辅助技术用户感到困惑。
“lang” 属性
默认情况下,SvelteKit 的页面模板将文档的默认语言设置为英语。如果您的内容不是英文,则应更新 src/app.html
中的 <html>
元素,使其具有正确的 lang
属性。这将确保任何读取文档的辅助技术都使用正确的发音。例如,如果您的内容为德语,则应将 app.html
更新为以下内容
<html lang="de">
如果您的内容有多种语言版本,则应根据当前页面的语言设置 lang
属性。您可以使用 SvelteKit 的 handle 钩子 来实现此目的
<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 应用相同。您应该能够将以下通用无障碍访问资源中的信息应用于您构建的任何 Web 体验