Calling card · No.02

给动效党的一份无障碍清单

≈ 2 MIN READ前端无障碍

01好看和可用不是敌人

这个博客全站都是斜切、网点、闪烁、转场。但我给自己立了条硬规矩:所有动效都必须可被关掉,所有颜色都必须能被读懂。

02开工前的五条检查

  1. prefers-reduced-motion 必须真的生效,而不是写个空媒体查询
  2. 所有可交互元素都能用 Tab 走到,焦点样式必须显眼(本站是红色虚线框)
  3. 颜色对比度:正文对背景 ≥ 4.5:1;纯红底上的白字要加描边或黑底衬
  4. 不靠颜色单独传达信息——标签同时有文字
  5. 自定义光标必须保留原生行为,键盘用户不受影响
css
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: .001s !important;
    transition-duration: .001s !important;
    animation-iteration-count: 1 !important;
  }
}

03自定义光标的坑

cursor: none 会让鼠标消失在所有地方——包括输入框和滚动条。两条必须守住的规矩:

  1. 只在精确指针设备上启用(触屏设备用系统光标)
  2. 显示和隐藏必须成对:自定义光标没画出来时,绝不能隐藏系统光标,否则用户会得到一个「不存在的鼠标」
css
@media (pointer: fine) {
  body.p5-cursor, body.p5-cursor * { cursor: none !important; }
}
js
// 只有确认开始绘制自定义光标,才加上这个 class
function show() {
  if (shown) return;
  shown = true;
  cursor.style.display = 'block';
  document.body.classList.add('p5-cursor');
}
function hide() {
  if (!shown) return;
  shown = false;
  cursor.style.display = 'none';
  document.body.classList.remove('p5-cursor');
}

04测试清单

测试方法通过标准
键盘导航只用 Tab / Enter / ↑↓能到达全部功能
减弱动效系统开启「减少动态效果」无闪烁、无长动画
缩放浏览器 200%不出现横向滚动条
对比度Lighthouse / axe≥ 90 分

05对比度别靠肉眼判断

红色的 #e60012 上放白字,对比度只有约 4.3:1,不达标。三种修法:

  1. 加描边或阴影,让文字与直接背景形成高对比
  2. 换成米白 #f6f4ef 并把字重提到 700
  3. 红底只承载大字号(≥ 24px 且粗体,标准放宽到 3:1)
css
/* 红底白字的安全写法:四向描边 + 阴影 */
.badge {
  background: var(--red);
  color: #fff;
  font-weight: 800;
  text-shadow: 0 1px 0 #000, 0 -1px 0 #000, 1px 0 0 #000, -1px 0 0 #000;
}

06焦点状态必须能被看见

outline: none 是这个行业最常见的错误之一。焦点框是你自己画的品牌资产,不是浏览器的累赘:

css
:focus-visible {
  outline: 3px dashed var(--red);
  outline-offset: 3px;
}