被多数前端开发忽略的重要特性!
作者:前端充电宝
作为前端开发者,我们常常沉浸在UI动效、性能优化和新技术栈的研究中,却忽视了一个直接影响25%用户的重要问题——Web 可访问性。本文将深入解析前端可访问性的核心要点及具体实现。
可访问性是什么?
Web 可访问性是指通过设计和开发技术,确保网页或应用能够被所有人无障碍地访问和使用,包括残障人士、老年用户、临时受伤者(如手部受伤)或使用特殊设备(如屏幕阅读器、语音控制工具)的人群。其核心目标是消除访问障碍,实现信息平等。
Web 可访问性的重要性:
- 法律合规:许多国家和地区(如欧盟、美国)要求公共网站必须符合可访问性标准(如 WCAG),否则可能面临法律风险。如果你的应用用户人群是这些国家的,就需要特别关注开发中的可访问性。
- 用户体验:提升所有用户的操作便利性,例如清晰的导航、高对比度配色对普通用户同样友好。
- SEO 优化:可访问性实践(如语义化 HTML)通常与搜索引擎优化(SEO)兼容,提升搜索排名。
WCAG
WCAG(Web Content Accessibility Guidelines,网页内容可访问性指南)是由 W3C(万维网联盟)制定的国际标准,旨在确保网页内容对所有人均可访问和使用。
根据 Web 内容可访问性指南(WCAG),Web 可访问性可以归纳为以下四个核心原则:
- 可感知: 用户必须能够感知提供的信息。
-
-
文本替代:为非文本内容(如图片、图表)提供
alt
文本或描述。 - 多媒体可访问:为视频提供字幕,为音频提供文本转录。
- 适配性:内容在不同设备(如屏幕阅读器、移动端)上可正常显示。
-
文本替代:为非文本内容(如图片、图表)提供
- 可操作: 用户界面组件和导航必须是可操作的。
-
- 键盘导航:所有功能可通过键盘(Tab、Enter、方向键)操作。
- 避免闪烁内容:防止快速闪烁的动画引发光敏性癫痫。
- 足够时间:用户有充足时间阅读或操作(如表单填写倒计时可延长)。
- 可理解: 用户必须能够理解和使用信息和用户界面。
-
- 一致性:导航、标签、按钮功能保持一致。
- 错误提示:表单输入错误时提供明确的文字说明和修正建议。
-
语言明确:避免使用复杂术语,页面语言通过
lang
属性声明。
- 健壮: 内容必须兼容当前和未来的技术。
-
-
语义化 HTML:使用标准标签(如
<button>
、<nav>
),避免滥用<div>
模拟控件。 -
ARIA 支持:为动态内容补充 ARIA 属性(如
role
、aria-label
)。
-
语义化 HTML:使用标准标签(如
WCAG 要求分为三个等级,从低到高依次为:
可访问性的前端实现
Web 可访问性需要贯穿开发全流程,从前端技术实现到设计协作,再到测试验证。
语义化HTML
根据内容的含义选择合适的 HTML 标签,这有助于屏幕阅读器等辅助技术理解页面结构,方便用户导航。
<!-- 错误:用 div 模拟按钮 -->
<div onclick="submit()">提交</div>
<!-- 正确:语义化按钮 -->
<button onclick="submit()">提交</button>
常见的语义化标签包括:
标签 | 作用 |
---|---|
<header> |
定义文档或节的页眉,包含介绍性内容,如网站标志、标题、导航栏等 |
<nav> |
专门定义导航链接部分,包含指向不同页面或同一页面不同部分的主要导航链接 |
<main> |
规定文档的主要内容,该内容应独一无二,不包含重复出现的内容 |
<article> |
表示文档中独立、完整且可独立分发的内容块,如博客文章、新闻报道等 |
<section> |
对文档内容进行分块,将相似主题的内容分组,不一定能独立存在 |
<aside> |
定义所处内容之外的内容,常表现为侧边栏或插入内容,与周围内容相关但非主要部分 |
<footer> |
定义文档或节的页脚,包含版权信息、作者信息、联系方式等 |
<h1> - <h6>
|
定义不同级别的标题,构建文档大纲结构,利于搜索引擎理解及用户浏览 |
<ul> |
创建无序列表,列表项无特定顺序,以项目符号显示 |
<ol> |
创建有序列表,列表项按数字或字母顺序排列,适用于强调顺序的内容 |
<dl> |
创建定义列表,包含<dt> (定义术语)和<dd> (定义描述)对,展示术语及其定义 |
<blockquote> |
定义从其他来源引用的内容,视觉上常呈现为缩进,可搭配<cite> 指定引用来源 |
<q> |
定义短的行内引用,浏览器自动在两端加引号 |
<time> |
定义日期和时间,方便浏览器和搜索引擎识别,可通过datetime 属性指定具体值 |
语义化 HTML 的好处:
- 提高可访问性: 语义化HTML可以帮助辅助技术(如屏幕阅读器)更好地理解页面结构和内容,从而为残障用户提供更好的体验。
- 增强SEO(搜索引擎优化): 搜索引擎爬虫依赖 HTML 标签来理解网页的内容和结构。使用语义化HTML可以使搜索引擎更准确地抓取和索引页面,有助于提高搜索排名。
- 改善代码可读性和维护性: 语义化HTML使代码更具结构性和逻辑性,易于理解和维护。
- 符合Web标准和最佳实践: 语义化HTML符合W3C和其他标准组织推荐的最佳实践,有助于构建高质量的Web应用。
键盘导航
键盘导航是 Web 可访问性的重要组成部分,它允许用户仅使用键盘来浏览和操作网页,这对于那些无法使用鼠标或其他指针设备的用户(如肢体残障人士、键盘快捷方式偏好者)来说至关重要。
可聚焦元素
可聚焦元素是指用户可以通过键盘的 Tab 键将焦点移动到这些元素上的元素,并且焦点顺序应符合逻辑。常见的可聚焦元素包括链接(<a>
)、按钮(<button>
)、输入框(<input>
、<textarea>
)、下拉框(<select>
)等。
<a href="#">前端充电宝</a>
<button>点击我</button>
<input type="text"placeholder="输入内容">
<select>
<option value="1">选项1</option>
<option value="2">选项2</option>
</select>
在上述代码中,用户可以使用 Tab 键依次将焦点移动到链接、按钮、输入框和下拉框上。
焦点顺序
- 自然顺序:键盘焦点的移动顺序应该与网页内容的逻辑和视觉顺序一致。通常,焦点会按照 HTML 文档中元素出现的先后顺序进行移动。例如,在一个表单中,焦点会从第一个输入框开始,依次移动到后续的输入框、按钮等元素。
-
调整顺序:在某些情况下,可能需要调整焦点顺序。可以使用
tabindex
属性来实现。 -
-
tabindex="0"
:将元素添加到正常的 Tab 顺序中,即使该元素默认不可聚焦。 -
tabindex="-1"
:使元素可聚焦,但不包含在正常的 Tab 顺序中,可以通过 JavaScript 等方式将焦点设置到该元素上。 -
tabindex="正数"
:指定元素的焦点顺序,数值越小越先获得焦点,但不建议过多使用这种方式,因为可能会破坏自然的焦点顺序。
-
焦点可见性
当元素获得焦点时,应该有明显的视觉指示,以便用户清楚地知道当前焦点所在的位置。可以通过修改元素的样式(如改变边框颜色、添加背景色、显示下划线等)来实现。
button:focus, input:focus, a:focus{
outline:2px solid #007BFF;/* 蓝色边框 */
box-shadow:005pxrgba(0,123,255,0.5);/* 添加阴影效果 */
}
注意事项:
- 避免移除默认的
outline
样式,除非提供了更好的替代方案。 - 提供高对比度的颜色,确保视觉上有足够的可见性。
键盘操作支持
- 常见操作:不同类型的元素应该支持相应的键盘操作。例如:
-
- 链接:按下 Enter 键可以激活链接,跳转到相应的页面。
- 按钮:按下 Enter 键或 Space 键可以触发按钮的点击事件。
- 输入框:可以使用方向键在输入框内移动光标,按下 Enter 键在某些情况下可以提交表单。
- 下拉框:使用方向键可以选择下拉框中的选项,按下 Enter 键可以确认选择。
- 自定义元素的键盘操作:对于自定义的交互元素(如自定义菜单、对话框等),需要通过 JavaScript 来实现相应的键盘操作支持。例如,一个自定义菜单可以通过监听键盘事件,根据用户按下的方向键来切换菜单项的选中状态,按下 Enter 键来执行相应的操作。
跳过导航
对于一些大型网页,可能存在大量的导航链接和重复的内容,用户可能希望快速跳过这些内容,直接访问主要内容。这时可以提供 “跳过导航” 链接。
实现方法:在页面顶部添加一个隐藏的链接,当用户使用键盘将焦点移动到该链接时,链接显示出来,用户按下 Enter 键可以直接跳转到页面的主要内容区域。
<a href="#main-content" class="skip-nav">跳过导航</a>
<header>
<nav>
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">产品</a></li>
<li><a href="#">关于我们</a></li>
</ul>
</nav>
</header>
<main id="main-content">
<h1>主要内容标题</h1>
<p>主要内容文本...</p>
</main>
.skip-nav{
position: absolute;
top:-40px;
left:0;
background:#fff;
padding:8px;
border:1px solid #ccc;
transition: top 0.3s ease;
}
.skip-nav:focus{
top:0;
}
这样,当用户使用键盘将焦点移动到该链接时,链接会显示出来,按下 Enter 键可以直接跳转到页面的主要内容区域。
测试验证
- 手动测试: 使用键盘在网页上进行导航,检查焦点顺序是否正确、焦点可见性是否明显、元素的键盘操作是否正常等。
-
- Tab键测试:通过Tab键逐个测试页面上的交互元素,确保每个元素都可以被聚焦并操作。
- Shift + Tab:测试反向导航,确保焦点顺序正确。
- Enter和Space 键:测试按钮、链接等交互元素是否可以通过Enter或Space键激活。
- Esc键:测试模态对话框、下拉菜单等是否可以通过Esc键关闭。
- 自动化测试:使用 axe-core 工具库进行检查。
ARIA 属性
ARIA(Accessible Rich Internet Applications)属性是 HTML5 规范的一部分,旨在帮助开发者增强网页的可访问性,特别是在处理动态内容和复杂用户界面时。通过使用ARIA属性,可以为屏幕阅读器和其他辅助技术提供更多的信息,从而提升用户体验。
ARIA 属性主要分为三类:角色、状态、属性。
角色
角色定义了元素在页面中的功能或用途,常见的角色包括button
、menu
、dialog
等。
-
role="button"
:将一个普通的<div>
元素定义为按钮,使其具有按钮的语义。
<div role="button"tabindex="0">前端充电宝</div>
-
role="menu"
和role="menuitem"
:用于创建自定义菜单,明确菜单和菜单项的角色。
<ul role="menu">
<li role="menuitem"><a href="#">选项1</a></li>
<li role="menuitem"><a href="#">选项2</a></li>
</ul>
-
role="dialog"
:用于定义一个对话框。
<div id="dialog"role="dialog"aria-modal="true">
<h2>标题</h2>
<p>内容</p>
<button id="closeDialog">关闭</button>
</div>
注意事项:
- 尽量使用原生HTML元素(如
<button>
、<nav>
等),它们自带语义化角色。 - 只有在必要时才使用
role
属性来增强自定义组件的可访问性。
状态
状态表示元素当前的状态,如是否选中、是否展开等。常见的状态包括aria-checked
、aria-expanded
等。
-
aria-checked
:用于复选框和单选框,指示其选中状态。
<input type="checkbox"id="check-box"aria-checked="false">
<label for="check-box">选择</label>
-
aria - expanded
:用于可展开 / 折叠的元素,如菜单、手风琴组件等,指示其展开状态。
<button aria-controls="content"aria-expanded="false">展开内容</button>
<div id="content"hidden>具体内容</div>
属性
属性提供了额外的信息,如标签、描述等。常见的属性包括aria-label
、aria-labelledby
、aria-describedby
等。
-
aria-label
:为元素提供一个明确的标签,用于替代元素内部的文本,特别是当元素没有可见文本时,适用于简单的替代文本。
<input type="search"aria-label="搜索框">
<button aria-label="关闭菜单">X</button>
-
aria-labelledby
:引用其他元素的ID作为标签来源,适用于引用现有文本作为标签的情况。
<h1 id="page-title">网站</h1>
<nav aria-labelledby="page-title">
<ul>
<li><a href="#home">首页</a></li>
<li><a href="#about">关于我们</a></li>
</ul>
</nav>
-
aria-describedby
用于为元素提供额外的描述信息,通常与表单验证错误消息一起使用。
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"aria-invalid="true"aria-describedby="email-error">
<span id="email-error"class="error">请输入有效的邮箱地址</span>
多媒体内容
确保多媒体内容对所有用户都是可访问的,包括视力障碍者、听力障碍者以及其他有特殊需求的用户,是创建包容性网站的重要部分。
图片可访问性
-
替代文本: 为图像提供替代文本(
alt
属性),以便屏幕阅读器能够描述图像的内容。需要注意: -
- 提供有意义的
alt
属性,避免使用空字符串(除非图像是纯粹装饰性的)。 - 对于装饰性图像,可以使用
alt=""
来告诉屏幕阅读器忽略该图像。
- 提供有意义的
<img src="logo.png"alt="公司Logo">
-
长描述: 对于复杂的图像或图表,简单的
alt
属性可能不足以描述其全部内容,此时可以使用<figcaption>
标签结合<figure>
标签为图像添加说明。
<figure>
<img src="complex_graph.png"alt="一张复杂的销售数据折线图">
<figcaption>该折线图展示了过去一年中不同季度的产品销售数据变化趋势。</figcaption>
</figure>
视频可访问性
-
字幕: 为视频添加字幕,帮助听力障碍者理解视频内容,也有助于在嘈杂环境或用户选择静音时理解视频内容。可以在
<video>
标签中使用<track>
标签添加字幕文件,kind
属性设置为captions
。
<video controls>
<source src="example.mp4"type="video/mp4">
<track kind="captions"src="captions.vtt"srclang="zh"label="中文字幕">
</video>
-
音频描述: 音频描述是对视频中视觉内容的口头描述,帮助视力障碍者理解视频中的重要视觉元素。同样使用
<track>
标签来实现,kind
属性设置为descriptions
。
<video controls>
<source src="video.mp4"type="video/mp4">
<track kind="descriptions"src="descriptions.vtt"srclang="zh"label="视频描述">
</video>
-
控制和交互: 提供易于使用的视频控制功能,让所有用户都能方便地播放、暂停、调整音量、快进等。可以在
<video>
标签中添加controls
属性,显示默认的视频控制条。也可以通过 JavaScript 自定义控制界面,但要确保其可通过键盘操作。
<video id="myVideo"controls>
<source src="example.mp4"type="video/mp4">
</video>
<script>
const video =document.getElementById('myVideo');
// 添加键盘事件监听器
document.addEventListener('keydown',(e)=>{
if(e.key =' '){// 空格键播放/暂停
e.preventDefault();
if(video.paused){
video.play();
}else{
video.pause();
}
}elseif(e.key ='ArrowLeft'){// 左箭头后退5秒
video.currentTime -=5;
}elseif(e.key ==='ArrowRight'){// 右箭头前进5秒
video.currentTime +=5;
}
});
</script>
音频可访问性
- 音频转录: 为听障用户或在无法播放音频的情况下提供音频内容的文字版本。
<audio controls>
<source src="audio.mp3"type="audio/mpeg">
</audio>
<p>点击 <a href="audio_transcription.txt">这里</a> 查看音频转录文本。</p>
- 音频控制: 确保音频播放器的控制按钮可以通过键盘操作,并且对屏幕阅读器友好。
<audio id="myAudio"controls>
<source src="example.mp3"type="audio/mpeg">
</audio>
<script>
const audio =document.getElementById('myAudio');
// 添加键盘事件监听器
document.addEventListener('keydown',(e)=>{
if(e.key =' '){// 空格键播放/暂停
e.preventDefault();
if(audio.paused){
audio.play();
}else{
audio.pause();
}
}elseif(e.key ='ArrowLeft'){// 左箭头后退5秒
audio.currentTime -=5;
}elseif(e.key ==='ArrowRight'){// 右箭头前进5秒
audio.currentTime +=5;
}
});
</script>
整体策略
-
自动播放限制: 避免自动播放多媒体内容,特别是带有声音的视频或音频,以免干扰用户的体验。可以使用
preload="none"
或preload="metadata"
来延迟加载视频,直到用户明确请求播放。
<video controlspreload="none">
<source src="example.mp4"type="video/mp4">
</video>
- 焦点管理: 确保当多媒体内容加载或动态更新时,焦点正确管理,不会导致用户失去当前的操作上下文。
表单设计
设计一个易于理解和使用的表单是提升用户体验和可访问性的关键。
结构与布局
-
清晰的层次结构: 确保表单有一个清晰的层次结构,使用户能够轻松理解每个部分的目的和内容。可以使用
<fieldset>
和<legend>
来分组相关的表单元素,并且确保每个表单部分都有明确的标题或说明。
<form id="registrationForm">
<fieldset>
<legend>注册信息</legend>
<label for="username">用户名:</label>
<input type="text"id="username"name="username"required>
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"required>
<label for="password">密码:</label>
<input type="password"id="password"name="password"required>
</fieldset>
<fieldset>
<legend>联系方式</legend>
<label for="phone">电话号码:</label>
<input type="tel"id="phone"name="phone">
<label for="address">地址:</label>
<textarea id="address"name="address"></textarea>
</fieldset>
<button type="submit">提交</button>
</form>
- 逻辑顺序: 按照用户的自然填写顺序排列表单字段,避免跳跃式布局。
<label for="firstName">名字:</label>
<input type="text"id="firstName"name="firstName"required>
<label for="lastName">姓氏:</label>
<input type="text"id="lastName"name="lastName"required>
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"required>
标签
-
使用
<label>
标签: 为每个表单控件提供明确的标签,以便屏幕阅读器能够正确读取,可以使用for
属性将标签与相应的输入字段关联起来。
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"required>
- 隐藏标签: 对于某些装饰性或视觉上不必要的标签,可以使用CSS将其隐藏,但仍然对屏幕阅读器可见。
<label for="search"class="sr-only">搜索:</label>
<input type="search"id="search"name="search"placeholder="搜索...">
.sr-only{
position: absolute;
width:1px;
height:1px;
padding:0;
margin:-1px;
overflow: hidden;
clip:rect(0,0,0,0);
border:0;
}
输入字段
-
类型提示: 使用HTML5的输入类型提示(如
email
、tel
、date
等),帮助浏览器提供更好的输入体验(如自动完成、键盘布局等)。
<input type="email"id="email"name="email"required>
<input type="tel"id="phone"name="phone">
<input type="date"id="birthday"name="birthday">
- 占位符: 占位符文本可以帮助用户了解应该输入的内容,但不应替代标签。
<input type="email"id="email"name="email"placeholder="example@example.com"required>
表单验证
-
客户端验证: 在用户提交表单之前进行客户端验证,以防止无效数据提交,可以使用 HTML5 内置的验证属性(如
required
、pattern
等)。
<form id="registrationForm">
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"requiredaria-invalid="false"aria-describedby="email-error">
<span id="email-error"class="error"></span>
<button type="submit">提交</button>
</form>
<script>
const form =document.getElementById('registrationForm');
const emailInput =document.getElementById('email');
const emailError =document.getElementById('email-error');
form.addEventListener('submit',(e)=>{
if(!emailInput.validity.valid){
e.preventDefault();
emailInput.setAttribute('aria-invalid','true');
emailError.textContent ='请输入有效的邮箱地址';
emailInput.focus();
}
});
</script>
- 服务器端验证: 即使有客户端验证,仍需在服务器端进行验证,以确保数据的安全性和完整性。
即时反馈
-
实时验证: 在用户输入过程中提供即时反馈,帮助他们在提交表单前纠正错误,可以使用
aria-invalid
属性指示输入的有效性状态。
<form id="registrationForm">
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"requiredaria-invalid="false"aria-describedby="email-error">
<span id="email-error"class="error"></span>
<button type="submit">提交</button>
</form>
<script>
const emailInput =document.getElementById('email');
const emailError =document.getElementById('email-error');
emailInput.addEventListener('input',()=>{
if(!emailInput.validity.valid){
emailInput.setAttribute('aria-invalid','true');
emailError.textContent ='请输入有效的邮箱地址';
}else{
emailInput.setAttribute('aria-invalid','false');
emailError.textContent ='';
}
});
</script>
- 成功反馈: 在用户成功提交表单后,提供明确的成功确认信息。
辅助功能
- ARIA属性: 使用ARIA属性增强表单的可访问性,特别是在复杂交互中。
-
- 使用
aria-required
指示必填字段。 - 使用
aria-describedby
提供额外描述信息(如错误消息)。
- 使用
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"requiredaria-required="true"aria-describedby="email-error">
<span id="email-error"class="error"></span>
- 键盘导航: 确保表单可以通过键盘操作,并且焦点管理合理。
<form id="registrationForm">
<label for="username">用户名:</label>
<input type="text"id="username"name="username"required>
<label for="email">邮箱地址:</label>
<input type="email"id="email"name="email"required>
<button type="submit">提交</button>
</form>
<script>
document.addEventListener('keydown',(e)=>{
if(e.key ==='Enter'){
const focusedElement =document.activeElement;
if(focusedElement.tagName.toLowerCase()==='button'){
focusedElement.click();
}
}
});
</script>
模态框
模态框是一种常见的UI组件,用于显示临时信息或要求用户进行特定操作。
HTML结构
模态框的基本结构应包含一个对话框容器和关闭按钮,并且使用适当的ARIA属性来定义其角色和状态。
- 使用
role="dialog"
来标识模态框。 - 使用
aria-modal="true"
来告知屏幕阅读器这是一个模态对话框,阻止背景内容的交互。 - 提供明确的标题(
aria-labelledby
)和描述(aria-describedby
),帮助用户理解对话框的内容。
<div id="myModal"role="dialog"aria-modal="true"aria-labelledby="modalTitle"aria-describedby="modalDescription"style="display: none;">
<h2 id="modalTitle">模态标题</h2>
<p id="modalDescription">这是模态内容。</p>
<button id="closeModal">关闭</button>
</div>
焦点管理
- 初始焦点: 当模态框打开时,应将焦点移动到模态框内的第一个可聚焦元素上。如果模态框有多个可聚焦元素,选择最相关的元素作为初始焦点。
functionopenModal(){
const modal =document.getElementById('myModal');
modal.style.display ='block';
// 将焦点移到关闭按钮上
document.getElementById('closeModal').focus();
}
-
模态框内焦点循环:在模态框打开时,焦点应限制在模态框内部,防止用户通过 Tab 键将焦点移出模态框,与页面其他部分交互。可以通过第三方库如
react-focus-lock
来实现,也可以通过监听keydown
事件,处理Tab键导航,确保焦点始终停留在模态框内。
functiontrapFocus(event){
const modal =document.getElementById('myModal');
const focusableElements = modal.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])');
const firstFocusableElement = focusableElements[0];
const lastFocusableElement = focusableElements[focusableElements.length -1];
if(event.shiftKey &&document.activeElement = firstFocusableElement){
// Shift + Tab 从第一个元素移出
lastFocusableElement.focus();
event.preventDefault();
}elseif(!event.shiftKey &&document.activeElement = lastFocusableElement){
// Tab 从最后一个元素移出
firstFocusableElement.focus();
event.preventDefault();
}
}
document.addEventListener('keydown', trapFocus);
- 关闭模态框时恢复焦点:当模态框关闭时,应将焦点恢复到打开模态框的触发元素上,以便用户可以继续之前的操作。
const closeModalButton =document.getElementById('close-modal');
closeModalButton.addEventListener('click',()=>{
modal.hidden =true;
openModalButton.focus();
});
样式与视觉提示
- 视觉焦点指示: 为可聚焦元素提供清晰的视觉焦点指示,帮助视力障碍者识别当前聚焦的位置。
button:focus, input:focus, select:focus, textarea:focus{
outline:2px solid #007bff;
outline-offset:2px;
}
- 背景遮罩: 使用背景遮罩来模糊或隐藏背景内容,使模态框更加突出,背景遮罩应覆盖整个视口,并具有一定的透明度。
<div id="overlay"style="display: none;"></div>
<div id="myModal"role="dialog"aria-modal="true"aria-labelledby="modalTitle"aria-describedby="modalDescription"style="display: none;">
<!-- 模态框内容 -->
</div>
<style>
#overlay{
position: fixed;
top:0;
left:0;
width:100%;
height:100%;
background-color:rgba(0,0,0,0.5);
z-index:9998;
}
#myModal{
position: fixed;
top:50%;
left:50%;
transform:translate(-50%,-50%);
background-color: white;
padding:20px;
z-index:9999;
}
</style>
<script>
functionopenModal(){
const overlay =document.getElementById('overlay');
const modal =document.getElementById('myModal');
overlay.style.display ='block';
modal.style.display ='block';
// 将焦点移到关闭按钮上
document.getElementById('closeModal').focus();
}
functioncloseModal(){
const overlay =document.getElementById('overlay');
const modal =document.getElementById('myModal');
overlay.style.display ='none';
modal.style.display ='none';
// 恢复之前的焦点
if(previousActiveElement){
previousActiveElement.focus();
}
}
</script>
小结:可访问性不是功能,而是责任。通过实现这些技术细节,我们不仅满足 WCAG 标准,更是为所有用户构建真正的包容性网络。从下一个功能需求开始,将可访问性刻进你的开发 DNA。