可访问性常被当成「加分项」,但它其实是可用性的底线:键盘用户、读屏用户、在强光下看手机的人、把字号调到 200% 的人,都是真实存在的使用者。下面这份清单是我每次上线前都会走一遍的,不需要安装任何工具。
一、只用键盘走一遍
拔掉鼠标,从地址栏按 Tab 开始:
- 能否到达所有可点击元素?
- 焦点框是否始终可见?
- 顺序是否符合视觉顺序?
- 弹窗打开后,Tab 是否被困在弹窗内?Esc 能否关闭?
最常见的失败是 outline: none。设计上嫌焦点框丑可以理解,但直接去掉等于让键盘用户失去位置感。正确做法是换成可见的自定义样式:
:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 2px;
}
用 :focus-visible 而不是 :focus,鼠标点击时就不会出现焦点框。
二、看对比度,不靠眼睛
正文对背景的对比度至少要 4.5:1,大字号(18px 粗体或 24px 常规以上)至少 3:1。深色主题尤其容易翻车:灰色文字放在近黑背景上,看着「高级」,实际根本读不清。
一个简单判断:把页面截图转成灰度,如果正文和小字标签混在一起分不出层级,对比度多半不够。
三、检查语义结构
在浏览器里关掉 CSS 看一眼,或者打开无障碍树:
- 页面是否只有一个
h1? - 标题层级是否连续(不要 h2 直接跳到 h4)?
- 导航是否在
<nav>里,正文是否在<main>里? - 按钮是
<button>还是加了onclick的<div>?
用 <div> 做按钮是最常见的错误:它不能被 Tab 聚焦、不能回车触发、读屏软件也不会念成「按钮」。换成原生元素,这些能力全部免费。
四、给图片和图标补文字
<!-- 内容图 -->
<img src="/chart.png" alt="2026 年访问量逐月上升,9 月达到峰值" />
<!-- 纯装饰图 -->
<img src="/divider.svg" alt="" aria-hidden="true" />
<!-- 图标按钮 -->
<button aria-label="关闭菜单"><svg aria-hidden="true">…</svg></button>
alt 不是「图片描述」,而是「这张图传达了什么信息」。如果图片只是装饰,空 alt 才是正确的,念出来反而干扰。
五、测试放大与减少动效
把浏览器缩放调到 200%,看是否出现横向滚动、文字是否被裁切。再用系统设置打开「减少动态效果」,确认页面没有视差、没有自动播放的循环动画。
这一条在做了星空、滚动渐入这类效果的项目里尤其重要:
@media (prefers-reduced-motion: reduce) {
.reveal {
opacity: 1;
transform: none;
transition: none;
}
}
六、关掉 JavaScript 看一次
静态站点应该做到「没有 JS 也能读完内容」。检查:
- 正文是否完整可见?
- 导航链接是否还能点?
- 是否有内容因为等待脚本而一直隐藏?
常见的坑是滚动渐入:元素初始 opacity: 0,等 IntersectionObserver 加类名才显示。脚本出错时整页空白。解法是只在 JS 确认可用时才隐藏元素——先给 <html> 加一个 js 类,CSS 写成 .js .reveal { opacity: 0 }。
七、表单与反馈
如果有输入框:
- 每个输入都有对应的
<label>(不是只有 placeholder); - 错误提示与输入框关联(
aria-describedby); - 操作结果用
aria-live="polite"播报,比如「已复制」。
十分钟,换一批用户
这份清单跑完大概十分钟,但它决定了一部分人能不能用你的网站。可访问性不是给「少数人」做的特殊适配,它覆盖的是所有处在临时受限状态的人:在地铁上单手操作、屏幕反光、戴着手套、网络很慢。
把它写进上线流程,比事后补要省力得多。