Accessibility
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): voidA lifecycle function that runs the supplied callback when the current component mounts, and also whenever we navigate to a 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): voidA lifecycle function that runs the supplied callback when the current component mounts, and also whenever we navigate to a 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 | nullto_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.
querySelector('.focus-me');
const to_focus: Element | nullto_focus?.focus();
});您也可以使用goto函数以编程方式导航到不同的页面。默认情况下,这将具有与点击链接相同的客户端路由行为。然而,goto还接受一个keepFocus选项,该选项将保留当前聚焦的元素而不是重置焦点。如果您启用此选项,请确保在导航后当前聚焦的元素仍然存在于页面上。如果该元素不再存在,用户的焦点将会丢失,这将为辅助技术用户带来困惑体验。
“lang” 属性
默认情况下,SvelteKit 的页面模板将文档的默认语言设置为英语。如果您的内 容不是英语,您应该更新<html>元素在src/app.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: 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): stringget_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>) | 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: 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.
replace('%lang%', function get_lang(event: any): stringget_lang(event: RequestEvent<Partial<Record<string, string>>, string | null>event))
});
};进一步阅读
对于大多数情况,构建一个可访问的 SvelteKit 应用与构建一个可访问的 Web 应用相同。您应该能够将以下通用可访问性资源中的信息应用于您构建的任何 Web 体验: