标签有效
“jsx-a11y/alt-text”: “error” // 强制图片 alt 属性
}
}
运行
npm run lint
时,它会警告如缺少 alt 的
![]()
标签:
// 错误示例:缺少 alt
// 修正后
最佳实践
:在 CI/CD 管道中集成 linting,确保代码合并前通过无障碍检查。Next.js 的
next lint
命令默认包含一些核心规则,但扩展插件能覆盖更多场景。
1.3 避免常见代码陷阱
颜色对比
:确保文本与背景对比度至少 4.5:1。使用工具如 WebAIM Contrast Checker 验证。在 CSS 中,避免仅靠颜色传达信息(如错误状态),应结合图标或文本。
键盘导航
:所有交互元素必须可通过 Tab 键访问。Next.js 的
组件默认支持,但自定义按钮需添加
tabIndex
(如果隐藏)。
2. 组件设计:构建可访问的 React 组件
Next.js 的组件系统允许复用 UI 元素,但设计时需内置无障碍支持。使用 ARIA(Accessible Rich Internet Applications)属性来增强动态内容,但优先依赖原生 HTML。
2.1 ARIA 属性的正确使用
ARIA 用于补充 HTML 语义,尤其在自定义组件中。常见角色包括
role=”button”
、
aria-label
、
aria-expanded
等。
示例:可访问的下拉菜单组件
以下是一个 Next.js 中的下拉菜单,使用 ARIA 管理状态和焦点:
// components/Dropdown.js
import { useState, useRef, useEffect } from ‘react’;
export default function Dropdown() {
const [isOpen, setIsOpen] = useState(false);
const buttonRef = useRef(null);
const menuRef = useRef(null);
useEffect(() => {
if (isOpen) {
menuRef.current?.focus(); // 焦点管理:打开时聚焦菜单
}
}, [isOpen]);
const toggle = () => setIsOpen(!isOpen);
return (
{isOpen && (
)}
);
}
详细说明
:
aria-haspopup
和
aria-expanded
告知屏幕阅读器这是一个弹出菜单及其状态。
role=”menu”
和
role=”menuitem”
定义菜单结构。
焦点管理:使用
useRef
和
useEffect
确保键盘用户能导航(箭头键移动焦点,Enter 选择)。
测试:在 Chrome DevTools 的 Accessibility 面板检查树状结构,或用屏幕阅读器验证。
2.2 处理动态内容(如加载状态)
Next.js 的
Suspense
和
loading.tsx
可以提升加载体验,但需确保加载指示器对辅助技术友好。
示例:加载 spinner
// app/loading.tsx
export default function Loading() {
return (
{/* 视觉 spinner,隐藏于屏幕阅读器 */}
页面加载中,请稍候… {/* 提供文本替代 */}
);
}
为什么?
aria-live
区域会宣布动态变化,确保用户知晓加载进度,而不需手动检查。
3. 表单处理:确保输入和验证的无障碍
表单是无障碍挑战的热点。Next.js 中,使用
react-hook-form
或内置状态管理,但始终验证输入标签、错误消息和焦点。
3.1 标签与输入关联
使用
export default function LoginForm() {
const { register, handleSubmit, formState: { errors } } = useForm();
const onSubmit = (data) => console.log(data);
return (
);
}
详细说明
:
htmlFor
确保屏幕阅读器将标签与输入关联,用户点击标签可聚焦输入。
aria-invalid
和
aria-describedby
提供错误反馈,
role=”alert”
立即宣布错误。
验证:使用
react-hook-form
的
register
处理规则,确保错误消息简洁且位置合理(输入下方)。
3.2 键盘友好验证
确保表单可通过 Enter 提交,错误时焦点移到第一个无效输入。使用
useEffect
实现:
useEffect(() => {
if (Object.keys(errors).length > 0) {
const firstError = document.querySelector(‘[aria-invalid=”true”]’);
firstError?.focus();
}
}, [errors]);
4. 导航与路由:Next.js 特定优化
Next.js 的路由系统(App Router 或 Pages Router)需确保链接和页面切换无障碍。
4.1 可访问链接
使用
而非
以支持客户端导航,但添加
aria-current
表示当前页面。
示例:面包屑导航
// components/Breadcrumbs.js
import Link from ‘next/link’;
import { useRouter } from ‘next/router’;
export default function Breadcrumbs() {
const router = useRouter();
const paths = router.asPath.split(‘/’).filter(Boolean);
return (
);
}
4.2 页面焦点管理
在路由切换时,使用
useEffect
重置焦点到主内容。Next.js 的
next/router
事件可钩子:
import { useEffect } from ‘react’;
import { useRouter } from ‘next/router’;
export default function FocusManager({ children }) {
const router = useRouter();
useEffect(() => {
const handleRouteChange = () => {
const main = document.querySelector(‘main’);
if (main) main.focus();
};
router.events.on(‘routeChangeComplete’, handleRouteChange);
return () => router.events.off(‘routeChangeComplete’, handleRouteChange);
}, [router]);
return {children};
}
为什么?
屏幕阅读器用户在页面切换后需重新定位,避免从头阅读。
5. 用户体验考量:超越代码的全面设计
无障碍不仅是代码,还涉及整体 UX。目标是让应用对所有用户高效、愉悦。
5.1 焦点指示与跳过链接
提供可见焦点环(CSS:
:focus-visible
),并添加“跳过到主要内容”链接。
示例:跳过链接
// components/SkipLink.js
export default function SkipLink() {
return (
跳过导航,直接到主要内容
);
}
// 在布局中使用
// app/layout.js
import SkipLink from ‘./SkipLink’;
export default function RootLayout({ children }) {
return (
{children}
);
}
CSS:
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #000;
color: #fff;
padding: 8px;
text-decoration: none;
}
.skip-link:focus {
top: 0; /* 焦点时显示 */
}
5.2 测试与工具
自动化测试
:使用
@testing-library/react
和
jest-axe
进行单元测试。
示例测试:
“`jsx
//
tests
/navbar.test.js
import { render } from ‘@testing-library/react’;
import { axe } from ‘jest-axe’;
import Navbar from ‘../components/Navbar’;
test(‘navbar has no accessibility violations’, async () => {
const { container } = render();
const results = await axe(container);
expect(results.violations).toHaveLength(0);
});
“`
手动测试
:用键盘导航整个应用;用屏幕阅读器(如 VoiceOver on Mac)测试公告。
性能考虑
:Next.js 的图像优化(
next/image
)支持
loading=”lazy”
,但确保 alt 文本不被压缩。
5.3 文化与本地化
对于中文用户,确保语言属性(
lang=”zh-CN”
),并处理 RTL(右到左)语言如果适用。使用
next-i18next
管理多语言,但验证翻译后的 ARIA 标签。
结论:持续改进无障碍实践
在 Next.js 中兼顾无障碍设计需要从代码规范入手,通过语义化 HTML、ARIA 和工具集成构建基础;在组件和表单中注重细节,如焦点管理和错误反馈;优化导航和用户体验,确保包容性。开始时,从一个页面审计(如用 WAVE 工具)入手,逐步扩展到整个应用。记住,无障碍是迭代过程:定期测试、收集反馈,并参考 WCAG 2.1 AA 标准。通过这些实践,你的 Next.js 网站不仅合规,还能为用户提供卓越体验,真正实现“为所有人设计”。如果需要特定组件的深入示例,欢迎提供更多细节!