# 无障碍

> 构建符合 WCAG 2.1 AA 级的 Shoplazza 主题：语义化 HTML、合理的标题层级、键盘可操作，以及屏幕阅读器兼容。

无障碍的主题能被所有人使用，包括依赖键盘、屏幕阅读器或其他辅助技术的人。目标是达到 [WCAG 2.1](https://www.w3.org/TR/WCAG21/) AA 级，并在构建时遵循以下实践。

## 使用语义化 HTML 和合理的标题层级

为每个用途选用正确的元素——操作用 `<button>`、链接用 `<a>`、地标用 `<nav>`、`<main>`、`<header>`。原生元素自带键盘和屏幕阅读器支持，自定义的 `<div>` 控件则没有。

每个页面只用一个 `<h1>`，且不要跳级（`<h1>` → `<h2>` → `<h3>`）。标题应描述页面结构，而不是为了字号大小来选。

例如，用地标元素包裹页面，并优先用 `<button>`/`<a>` 而不是带点击事件的 `<div>`：

```html
<header>...</header>
<nav aria-label="Primary">...</nav>
<main id="main-content">
  <h1>Product title</h1>
  <button type="button">Add to cart</button>
</main>
<footer>...</footer>
```

## 让一切都可用键盘操作

每个可交互元素都必须能仅用键盘到达并操作。请确认：

* 焦点顺序与视觉及 DOM 顺序一致（从上到下、从左到右）。
* 获得焦点的元素显示可见的焦点指示——不要去掉 outline 又不提供替代。
* 下拉、抽屉、模态框都能用键盘打开、操作和关闭（包括用 `Esc` 键）。

如果你要重新设计焦点指示样式，务必让它清晰可见，而不是直接去掉：

```css
:focus-visible {
  outline: 2px solid #005fcc;
  outline-offset: 2px;
}
```

## 提供跳转链接

键盘和屏幕阅读器用户从页面顶部开始，按顺序逐个 Tab。若不加帮助，他们在每个页面都要穿过整个页头和导航才能到正文。把一个「跳到主内容」链接作为第一个可聚焦元素，让他们直接跳到主内容：

```html
<a href="#main-content" class="skip-link">跳到主内容</a>
```

把它指向主内容元素的 `id`，并且仅在它获得焦点时才显现：

```css
.skip-link {
  position: absolute;
  left: -9999px;
}
.skip-link:focus {
  left: 0;
}
```

## 为图片提供文本替代

每个 `<img>` 都需要 `alt` 属性。对内容图片，用 [image object](/zh-CN/docs/theme/references/liquid/objects/image) 输出其 alt 文本：

```liquid
<img src="{{ product.image | img_url: '600x' }}" alt="{{ product.image.alt | escape }}">
```

对不传达信息的装饰性图片，用空的 `alt=""`，让屏幕阅读器跳过它。

## 保证足够的色彩对比度

文本与其背景之间的对比度至少为 4.5:1。对大字（24px，或加粗 18.66px）以及图标、输入框边框等有意义的非文本元素，最低为 3:1。不要仅靠颜色传达信息——同时配上文字或图标。

具体怎么做到：

- **逐对测量**：用对比度检查工具测前景色和背景色——浏览器 DevTools 的取色器会直接显示比值，或用 [WebAIM Contrast Checker](https://webaim.org/resources/contrastchecker/)。例如 `#767676` 配白底是 4.54:1（正文文本达标），而 `#999999` 配白底只有 2.85:1（不达标）。
- **调到达标为止**：某一对不够时，把文字调深或把背景调浅，直到越过阈值——通常微调明度就够了。
- **留意图片和渐变上的文字**：对比度会随图片各处变化，可在文字背后加一层纯色或半透明遮罩（scrim）。
- **别忘了主题设置**：商家常给主题换色；要测试主题设置允许的各种配色组合，而不只是默认配色。

## 为每个表单输入加标签

用匹配的 `for` 和 `id` 把 `<label>` 与每个输入关联起来，让辅助技术能播报字段用途：

```html
<label for="contact-email">Email</label>
<input id="contact-email" type="email" name="email">
```

字段出错时，用 `aria-describedby` 把错误信息关联到输入，且不要仅用颜色表达错误。

## 让动态组件可访问

对交互组件，用 ARIA 暴露其状态和用途：

* 在菜单、手风琴等切换控件上，设置 `aria-expanded`，并用 `aria-controls` 指向它展开的元素。
* 给模态框和抽屉加 `role="dialog"` 和 `aria-modal="true"`，打开时把焦点移入、打开期间困住焦点、关闭时把焦点还给触发元素。

例如，菜单切换按钮用 `aria-expanded` 反映展开状态（你的 JavaScript 在抽屉打开时把它翻成 `true`）：

```html
<button aria-expanded="false" aria-controls="menu-drawer">Menu</button>
<div id="menu-drawer" hidden>...</div>
```

用 [`t` 过滤器](/zh-CN/docs/theme/references/liquid/filters/localization)从 locale 文件取标签，使其可翻译，例如 `aria-label="{{ 'i18n.general.search' | t }}"`。见[国际化](/zh-CN/docs/theme/best-practices/internationalization)。

## 设置触控目标尺寸

把触控目标设为至少 24 × 24 CSS 像素，便于点按，相邻目标之间留足间距：

```css
.nav-icon {
  min-width: 24px;
  min-height: 24px;
}
```

## 尊重减弱动效的偏好

大幅动画、视差效果和自动播放的轮播，可能让前庭功能障碍的用户感到不适甚至眩晕。操作系统提供了「减少动态效果」设置；用 `prefers-reduced-motion` 媒体查询尊重它——为这些用户关闭动画，同时保留给其他人：

```css
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}
```

## 测试你的主题

在整个开发过程中检查无障碍：

* 仅用键盘浏览整个页面。
* 用屏幕阅读器（如 VoiceOver 或 NVDA）走一遍浏览、结账等关键流程。
* 用对比度检查工具验证色彩对比。
* 校验 HTML，排查结构问题。
