Appearance
CSS 可访问性
CSS 可访问性是指通过样式设计确保所有用户(包括残障人士)都能有效使用网页内容。
概述
CSS 在创建可访问的网页中扮演着重要角色,它不仅影响视觉呈现,还直接影响辅助技术的使用体验。
颜色与对比度
颜色对比度要求
css
/* 确保文本与背景有足够对比度 */
.high-contrast-text {
color: #000000; /* 深色文本 */
background-color: #ffffff; /* 浅色背景 */
/* 对比度至少为 4.5:1(正常文本)或 3:1(大文本) */
}
/* 良好对比度示例 */
.accessible-text {
color: #212121; /* 深灰色 */
background-color: #f5f5f5; /* 浅灰色 */
}
/* 避免低对比度 */
.poor-contrast {
color: #cccccc; /* 浅灰色文字 */
background-color: #eeeeee; /* 浅色背景 */
}
不仅依赖颜色传达信息
css
/* 不推荐:仅使用颜色传达信息 */
.status-error {
color: #dc3545; /* 红色 */
}
/* 推荐:结合颜色和其他视觉线索 */
.status-error {
color: #dc3545;
background-color: #f8d7da;
border-left: 5px solid #dc3545;
}
.status-error::before {
content: "× ";
font-weight: bold;
}
/* 使用图标增强理解 */
.icon-error::before {
content: "⚠ ";
}
焦点指示器
焦点样式的重要性
css
/* 保持默认焦点样式 */
.focusable-element:focus {
outline: 2px solid #007cba;
outline-offset: 2px;
}
/* 自定义焦点样式 */
.custom-focus:focus {
background-color: #f0f8ff;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
outline: 2px solid transparent;
}
/* 确保所有可聚焦元素都有焦点样式 */
a, button, input, textarea, select, [tabindex]:not([tabindex="-1"]) {
transition: outline 0.2s ease;
}
a:focus, button:focus, input:focus, textarea:focus, select:focus {
outline: 2px solid #007cba;
outline-offset: 2px;
}
避免移除焦点样式
css
/* 不推荐:完全移除焦点样式 */
.element:focus {
outline: none;
}
/* 推荐:提供替代的焦点指示器 */
.element:focus {
outline: 2px solid #007cba;
outline-offset: 2px;
/* 或者使用其他视觉指示器 */
border: 2px solid #007cba;
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25);
}
文本可读性
字体大小和行高
css
/* 使用相对单位 */
.readable-text {
font-size: 1.125rem; /* 18px,相对于根元素 */
line-height: 1.5; /* 推荐的行高比例 */
max-width: 65ch; /* 每行最多65个字符 */
}
/* 确保文本可以缩放 */
.scalable-text {
font-size: 1.2rem; /* 使用 rem 而非 px */
line-height: 1.6;
}
/* 避免固定宽度导致文本溢出 */
.text-container {
word-wrap: break-word;
overflow-wrap: break-word;
hyphens: auto; /* 自动换行 */
}
文本转换
css
/* 避免全部大写,影响可读性 */
.avoid-all-caps {
/* text-transform: uppercase; */
/* 这会影响某些用户的阅读体验 */
}
/* 保持原始文本格式 */
.normal-text {
text-transform: none;
}
/* 适当使用粗体强调 */
.important-text {
font-weight: bold;
}
动画和过渡
尊重用户动画偏好
css
/* 检测用户减少动画偏好 */
@media (prefers-reduced-motion: reduce) {
* {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
/* 特定动画元素 */
.animation-element {
animation: none !important;
}
}
/* 渐进增强的动画 */
.smooth-transition {
transition: transform 0.3s ease, opacity 0.3s ease;
}
@media (prefers-reduced-motion: reduce) {
.smooth-transition {
transition: none;
}
}
安全的动画属性
css
/* 推荐:使用不会引起重排的属性 */
.accessible-animation {
animation: fadeSlide 0.3s ease;
}
@keyframes fadeSlide {
from {
opacity: 0;
transform: translateX(-20px);
}
to {
opacity: 1;
transform: translateX(0);
}
}
/* 避免:引起重排的动画属性 */
.bad-animation {
/* 避免动画化 width, height, margin, padding 等 */
}
媒体查询和用户偏好
深色模式支持
css
/* 支持用户深色模式偏好 */
@media (prefers-color-scheme: dark) {
body {
background-color: #1a1a1a;
color: #ffffff;
}
.card {
background-color: #2d2d2d;
border: 1px solid #444;
}
}
/* 确保在所有主题下都有足够的对比度 */
:root {
--text-color: #212121;
--bg-color: #ffffff;
--border-color: #cccccc;
}
@media (prefers-color-scheme: dark) {
:root {
--text-color: #e0e0e0;
--bg-color: #1a1a1a;
--border-color: #444444;
}
}
.theme-element {
color: var(--text-color);
background-color: var(--bg-color);
border: 1px solid var(--border-color);
}
高对比度模式
css
/* 支持高对比度模式 */
@media (prefers-contrast: high) {
.element {
color: CanvasText;
background-color: Canvas;
border: 2px solid CanvasText;
}
.button {
border: 2px solid ButtonText;
background-color: ButtonFace;
color: ButtonText;
}
}
隐藏内容的可访问性
屏幕阅读器专用内容
css
/* 仅对屏幕阅读器可见 */
.sr-only {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
/* 高亮当前焦点元素 */
.focusable-sr {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
.focusable-sr:focus {
position: static;
width: auto;
height: auto;
margin: 0;
overflow: visible;
clip: auto;
white-space: normal;
}
隐藏但可访问
css
/* 隐藏视觉元素但保持可访问性 */
.hidden-visual {
visibility: hidden; /* 保持布局空间 */
}
/* 或者使用 aria-hidden */
.visually-hidden {
position: absolute !important;
left: -9999px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
导航辅助
跳转到主内容
css
/* 跳转链接样式 */
.skip-link {
position: absolute;
top: -40px;
left: 6px;
background: #000;
color: #fff;
padding: 8px;
z-index: 1000;
text-decoration: none;
}
.skip-link:focus {
top: 6px;
}
面包屑导航
css
.breadcrumb {
padding: 0.75rem 1rem;
margin-bottom: 1rem;
list-style: none;
background-color: #e9ecef;
border-radius: 0.25rem;
}
.breadcrumb-item + .breadcrumb-item::before {
display: inline-block;
padding-right: 0.5rem;
padding-left: 0.5rem;
color: #6c757d;
content: "/";
}
/* 确保面包屑对屏幕阅读器友好 */
.breadcrumb-item.active {
color: #6c757d;
}
表单可访问性
标签关联
css
/* 确保标签和输入框正确关联 */
.form-group {
margin-bottom: 1rem;
}
.form-label {
display: block;
margin-bottom: 0.5rem;
font-weight: bold;
}
.form-input {
display: block;
width: 100%;
padding: 0.375rem 0.75rem;
font-size: 1rem;
line-height: 1.5;
border: 1px solid #ced4da;
border-radius: 0.25rem;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
}
.form-input:focus {
outline: 0;
border-color: #80bdff;
box-shadow: 0 0 0 0.2rem rgba(0, 123, 255, 0.25);
}
错误状态
css
.form-error {
border-color: #dc3545;
box-shadow: 0 0 0 0.2rem rgba(220, 53, 69, 0.25);
}
.error-message {
color: #dc3545;
font-size: 0.875em;
margin-top: 0.25rem;
display: block;
}
/* 确保错误信息对所有用户都可见 */
.field-error {
position: relative;
}
.field-error::after {
content: "×";
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
color: #dc3545;
font-weight: bold;
}
响应式设计与可访问性
触摸目标大小
css
/* 确保触摸目标足够大 */
.touch-target {
min-height: 44px; /* iOS 建议最小尺寸 */
min-width: 44px;
padding: 12px 16px;
}
.button {
min-height: 44px;
min-width: 44px;
padding: 12px 24px;
}
/* 链接和按钮的触摸区域 */
a.button, button {
touch-action: manipulation; /* 确保触摸响应 */
}
缩放支持
css
/* 允许页面缩放 */
html {
font-size: 16px; /* 基准字体大小 */
}
.scalable-container {
max-width: 100%;
overflow-x: auto;
}
/* 避免固定宽度导致的问题 */
.avoid-fixed-width {
/* width: 300px; */
max-width: 100%;
width: auto;
}
实用技巧
可访问的颜色系统
css
:root {
/* 定义高对比度颜色对 */
--text-primary: #212121;
--text-secondary: #757575;
--text-hint: #9e9e9e;
--bg-primary: #ffffff;
--bg-secondary: #f5f5f5;
/* 强调色,确保高对比度 */
--accent-primary: #1976d2;
--accent-secondary: #7b1fa2;
}
/* 使用CSS自定义属性确保一致性 */
.accessible-element {
color: var(--text-primary);
background-color: var(--bg-primary);
}
焦点管理
css
/* 管理动态内容的焦点 */
.focus-trap {
outline: 2px solid transparent;
}
.focus-trap:focus-within {
outline: 2px solid #007cba;
outline-offset: 2px;
}
/* 模态框焦点管理 */
.modal:focus {
outline: none;
}
.modal-content {
outline: 2px solid #007cba;
outline-offset: 2px;
}
测试和验证
可访问性测试工具
css
/* 为自动化测试提供钩子 */
[data-a11y-test] {
/* 用于可访问性测试的特殊样式 */
}
/* 确保测试时的一致性 */
.testable-element {
/* 避免随机样式影响测试 */
transition: none !important;
animation: none !important;
}
最佳实践
- 确保文本与背景对比度至少为 4.5:1
- 提供清晰的焦点指示器
- 尊重用户的动画偏好设置
- 使用语义化的HTML结构
- 为非文本内容提供替代文本
- 确保所有功能都可以通过键盘访问
- 避免基于颜色的唯一信息传达
- 提供足够的触摸目标大小
- 使用相对单位以支持缩放
- 定期测试可访问性功能