为什么捐赠
API 浏览器
联系站长
无障碍
v2.25

无障碍(Accessibility,常缩写为"a11y")意味着你的网站或应用能被所有人使用——包括依赖屏幕阅读器、纯键盘操作、语音控制或其他辅助技术(AT)的用户。Quasar 组件内置了完善的无障碍层:语义化标签、WAI-ARIA 属性、键盘交互模式和焦点管理。本页介绍框架为你做了什么、哪些部分有意留给你的应用来处理,以及如何在各组件文档中查找详细说明。

无障碍是框架和你的应用之间的一份"契约"。Quasar 能渲染出正确的 role="checkbox" 配合 aria-checked 和 Space/Enter 键处理,但它无法知道一个纯图标按钮"表达什么意思"、你的品牌配色对比度是否足够、也不知道某个抽屉代表哪种导航地标。下方的组件概览矩阵会精确告诉你每部分职责归谁。

Quasar 提供了什么

语义化标签

组件在有对应原生 HTML 元素时优先使用原生标签——真正的 <button>(QBtn)、<a href>(各处的路由链接)、<form>(QForm)、<table>(QTable)、<hr>(QSeparator),以及来自 QLayout 家族的完整地标集合:<header><footer><aside><main>。原生元素自带语义、状态和键盘行为,这始终比用 ARIA 重新实现更稳健。

当视觉设计需要自定义元素时,组件会声明对应的 ARIA role 并管理所需的状态:role="checkbox"/"radio"/"switch" 配合 aria-checked(包括 mixed)、role="slider"/"spinbutton" 配合 aria-valuemin/max/nowrole="progressbar"role="tablist"/"tab"/"tabpanel"role="tree"/"treeitem"(虚拟滚动模式下通过 aria-level/aria-setsize/aria-posinset 补偿)、role="combobox" + "listbox"/"option"(QSelect),以及 role="separator" 配合完整的键盘调节支持(QSplitter)。

有些容器刻意不声明 role,因为它们可以容纳任意内容,错误的 role 会导致无效标记。QMenu 就是典型例子:ARIA 的 menu role 只允许子节点是 menu item,因此 QMenu 保持中性,由你在其内部的 QList 上声明 role="menu"(当内容确实是命令列表时)。QItem 则会根据上下文推导自身 role——在已声明的 menu 内是 menuitem,在 list 内是 listitem,可点击时是 button,导航时是普通链接。详见 QList/QItem 的无障碍章节。

装饰性元素对辅助技术隐藏:每个 QIcon 默认渲染 aria-hidden="true"(交互式图标如输入框的清除按钮会通过 role 和本地化标签重新暴露),背景遮罩层、虚拟滚动填充区、自定义滚动条等辅助结构也全部 aria-hidden

键盘支持

  • 激活:所有可点击的元素都支持键盘激活。QBtn 甚至在链接形态(<a>)按钮上合成了 Space 激活——原生 <a> 只响应 Enter——确保两个键都能用。可点击的 QItem、chip、展开头部、可排序表头和步骤条头部都处理 Enter/Space
  • 组合控件使用漫游 tabindex(roving tabindex)——整个控件是一个 Tab stop,用方向键在内部移动,符合 WAI-ARIA APG 规范:QTabs、QOptionGroup(单选模式)、QRating、QDate 的日历面板、QCarousel 的导航、QEditor 的工具栏以及 QTree。
  • 取值控件响应方向键(QSlider、QRange、QKnob、QSplitter、QTime 的微调器),大多还支持 Home/EndPageUp/PageDown;QSelect 实现了完整的 combobox 键盘契约,包括前缀搜索。
  • Escape 关闭以链式方式工作:只有最顶层打开的弹出(对话框、菜单、提示、叠加模式的抽屉)响应,逐个关闭弹出层。持久弹出会抖动或忽略而非关闭。
  • 水平方向键支持 RTLRTL 支持)——选项卡、单选组、滑块、日期导航、编辑器工具栏和分割面板全部在 RTL 语言包下镜像方向。

注意 Escape 处理和焦点回收是桌面模式行为;在移动平台上,关闭操作通过 Quasar 的 History 插件连接到平台返回键(Capacitor/Cordova 构建)。

焦点管理

  • 对话框记录打开它的元素,在渲染时将焦点移入对话框(遵循 autofocus/data-autofocus),在模态时捕获溢出的焦点,关闭时将焦点还原到打开者。
  • 菜单同理,但有一个改进:在菜单最后一个可聚焦元素上按 Tab(或第一个元素上按 Shift+Tab)会关闭菜单并从锚点继续 Tab 导航——键盘焦点永远不会泄漏到 portal 背后的虚空中。
  • 焦点移动会在弹出层过渡动画播放时排队,避免竞争的焦点意图发生竞态;在模态对话框内打开的菜单会渲染在对话框元素_内部_,这样 aria-modal 不会将其从辅助技术中隐藏。
  • QForm 在校验失败后聚焦第一个无效字段。
  • 焦点环仅在键盘操作时显示:鼠标或触摸交互后,组件将焦点停放在不可见的辅助元素上,避免焦点环闪烁;键盘聚焦时则保持可见指示器。这是内置行为——无需 :focus-visible polyfill。(内置指示器样式针对桌面模式;同时使用触摸和键盘的混合应用可能需要自定义焦点样式。)

屏幕阅读器标签和语言包

内置控件标签——输入框的清除按钮、chip 的删除图标、展开/折叠箭头、分页器的 首页/上一页/下一页/末页、QDate 的月/年导航、轮播箭头、编辑器工具栏——来自当前激活的 Quasar 语言包,会自动以你应用的语言播报。如果你编写自定义语言包,请覆盖这些 key(其中有些如 label.expand 是函数);屏幕阅读器用户获得的就是语言包提供的内容。

ARIA 属性透传

你放在 Quasar 组件上的任何 aria-* 属性(或 role)都会到达语义正确的元素:在表单字段上它到达原生 <input>/聚焦目标,在 QDialog 上它到达 role="dialog" 元素,以此类推。你的属性会覆盖自动生成的属性(表单字段上的 aria-describedby 会_合并_而非覆盖)。这是下面"你的职责"列表中所有内容的标准机制——无需特殊 prop。

你的应用需要负责什么

无障碍名称。 没有什么能为你自动生成有意义的名称。请为以下情况提供 aria-label(或可见文本):纯图标的 QBtn 和 FAB;为 QImg 提供 alt;为 QVideo 提供 title;为 QDialog、QDrawer、QToolbar、QOptionGroup 以及任何你希望可区分的 role="navigation"/role="group" 容器提供 aria-label/aria-labelledby。多个未标记的地标或工具栏是 WCAG 违规。注意 QTooltip 不会为其锚点命名——它只起描述作用——所以纯图标控件即使带有 tooltip 也需要自己的 aria-label

自定义触发器上的弹出语义。 QBtnDropdown 和 QSelect 完整连接了它们触发器的 ARIA(aria-expanded、条件性 aria-controls),从 v2.25 起 QMenu 也会在其锚点上维护 aria-expanded(加上声明在 QMenu 自身 role 对应的 aria-haspopup)。它只在锚点是 ARIA 允许该状态的控件时才能这么做,因此你的锚点需要是 <button>、链接或带有 widget role 的元素——普通 <div> 什么都得不到,这是设计如此。在弹出内部的 QList 上声明 role(推荐做法)仍然需要你自己提供 aria-haspopup——在 QMenu 锚点上作为普通属性,在 QBtnDropdown 上通过其 toggle-aria-haspopup prop。详见 QMenuQBtnDropdown

地标结构。 QLayout 家族为你免费提供了每种地标各一个——不要再添加自己的 <main>(QPage 已经是了),并标记多个抽屉或导航区域使它们可以被区分。

颜色对比度。 Quasar 不强制对比度检查,无论是浅色还是深色模式。请使用 WebAIM 对比度检查器 等工具检查你的品牌配色是否符合 WCAG 2.2 对比度最低要求(普通文本 4.5:1)——如果同时支持两种主题则两种都要检查。

减少动画。 只有 CSS 动画辅助类 尊重 prefers-reduced-motion。组件过渡、涟漪效果和滚动驱动效果(QParallax)不会——对动画敏感的用户需要你自行减弱这些效果(例如 $q.config.ripple = false、transition prop、禁用自动播放)。QCarousel 的 autoplay 在 hover 或聚焦时不会暂停;如果使用了它,请提供暂停控件(WCAG 2.2.2)。

播报异步状态。 加载指示器——QSpinner、QInnerLoading、QSkeleton、QAjaxBar、QUploader 的逐文件状态——都是纯视觉的。当状态变化对用户有意义时,请用 live region(role="status" 加上简短文本如"加载中…")包裹或伴随它们,并用 aria-hidden="true" 隐藏纯装饰性的占位符。

手势的键盘替代。 滑动操作(QSlideItem)、下拉刷新和触摸平移没有键盘路径。请提供平行操作方式——可见按钮、上下文菜单,或将 QPullToRefresh 的 trigger() 方法连接到按钮。

视口缩放。 WCAG 1.4.4 要求文本可放大至 200%。Quasar CLI 脚手架在 web 模式下允许捏合缩放(width=device-width, initial-scale=1);早期脚手架生成的应用带有 user-scalable=no, maximum-scale=1 的 viewport meta,这会导致所有自动化审计失败——请更新 index.html 中的 <meta name="viewport"> 使其匹配。Cordova/Capacitor 构建有意保持固定视口以获得原生应用体验;OS 级别的缩放(iOS 的辅助功能缩放、Android 放大)在那里覆盖了无障碍需求。解锁视口的一个副作用:iOS Safari 在字号小于 16px 的输入框获得焦点时会自动缩放页面。如果这影响了你的设计,请设置 Sass 变量 $input-font-size: 16px(或将 16px 字号限定到你的字段上)而不是重新禁用缩放。

测试。 没有框架能替代测试。请用纯键盘走一遍关键流程(所有功能都能到达吗?焦点可见吗?能退出来吗?);用屏幕阅读器跑一遍(VoiceOver 随 macOS/iOS 附带,NVDA 在 Windows 上免费);并在 CI 中加入 axe 或 Lighthouse 的自动化检查——它们捕获机械性问题(名称、对比度、ARIA 有效性),让你的手工测试可以专注于流程。

组件概览

每个组件名都链接到其文档页面的"无障碍"章节,其中描述了确切行为——包括限制——以及你需要在此基础上添加什么。

按钮

组件内置行为键盘
QBtn原生 <button><a>(需要时派生 role="button");aria-disabled;带 percentage 加载时的 progressbar ARIAEnter/Space,包括链接按钮上的 Space
QBtnDropdown展开/折叠模式:aria-expandedaria-controls(弹出层存在时)、本地化展开/折叠标签、可选的 toggle-aria-haspopup继承自 QBtn + QMenu
QBtnGroup仅视觉分组——需要你自己添加 role="group" + aria-label每个按钮是独立的 Tab stop
QBtnToggle每个选项有 aria-pressed;通过 attrs 为每个选项设置标签每个按钮 Enter/Space
QFab触发器上的 aria-expanded/aria-controls;关闭时操作项对辅助技术隐藏;焦点返回触发器Enter/Space 打开和激活

导航

组件内置行为键盘
QTabsrole="tablist"/"tab" 配合 aria-selectedaria-orientation漫游 tabindex;方向键(RTL 感知)、Home/End;显式激活
QTabPanelsrole="tabpanel"tabindex="0";tab↔panel 的 id 关联需要手动连接(已文档化)面板可通过 Tab 到达
QBreadcrumbs原生链接;无地标/aria-current——需要你自己用 <nav> 包裹并标记当前页面原生链接行为
QPagination命名的 role="navigation";本地化的 首页/上一页/下一页/末页 标签;活动页面上的 aria-current按钮 Enter/Space;输入模式下 Enter 提交
QStepperaria-current="step";每步是一个有标签的 group;可导航的头部暴露为按钮(禁用的暴露为 aria-disabled 按钮)可导航头部 Enter/Space
QToolbar / QBarrole="toolbar"——页面有多个时通过 aria-label 命名子元素是独立的 Tab stop

表单字段

组件内置行为键盘
QField / QInput<label for> 关联;错误通过 role="alert" 配合 aria-invalid/aria-errormessage/aria-describedby 播报(仅在消息渲染时);可访问的清除按钮原生编辑;清除按钮 Enter/Space
QSelect完整 combobox 模式:role="combobox" + aria-expanded/aria-controls/aria-activedescendantrole="listbox"/"option" 配合 aria-selected 和虚拟滚动感知的 aria-setsize/posinset方向键打开/导航、前缀搜索、Home/EndPageUp/PageDownEnter 选择、Esc 关闭
QForm原生 <form>;校验失败时聚焦第一个无效字段原生提交
QEditorrole="textbox" + aria-multiline;工具栏遵循 APG toolbar 模式并带有本地化标签工具栏漫游 tabindex,方向键/Home/EndCtrl 格式化快捷键
QFile字段框架 + 校验 ARIA;可键盘打开选择器Enter/Space 打开选择器
QUploader真正的按钮配合本地化名称、progressbar ARIA——但你仍需播报状态变化原生按钮激活

表单控件

组件内置行为键盘
QCheckboxrole="checkbox"、三态 aria-checked(含 mixed)、aria-label 来自 labelEnter/Space 切换
QRadiorole="radio" + aria-checked;组语义来自 QOptionGroupEnter/Space 选择
QTogglerole="switch" + aria-checkedEnter/Space 切换
QOptionGrouprole="radiogroup"/"group";APG 单选组模式漫游 tabindex;方向键选择(RTL 感知),跳过禁用项
QSlider / QRangerole="slider" 配合 aria-valuemin/max/nowaria-orientationaria-readonly(QRange:每个滑块一个命名的 slider)方向键步进(RTL/垂直感知),PageUp/PageDown ×10
QRating每颗星的单选组模式,带有逐星标签(icon-aria-label漫游 tabindex;方向键移动,Enter/Space 选择
QKnob可聚焦元素上的 role="slider" 配合值 ARIA方向键步进,PageUp/PageDown ×10
QColorTune(调节)选项卡(原生 input + slider)是无障碍访问路径,带有本地化的标签页/字段/滑块名称;调色板/光谱仅支持指针操作Tune 选项卡上的原生 input + slider 键
QDate日期按钮带有完整日期标签、aria-pressed 选中状态、今天的 aria-current="date";本地化导航漫游 tabindex;方向键跨月移动、Home/EndPageUp/PageDown(+Shift 跨年)
QTime表头每个单位为 role="spinbutton",带有本地化标签和值 ARIA;表盘是纯指针可视化方向键步进、Home/End、直接数字输入

弹出层

组件内置行为键盘
QDialogrole="dialog" + aria-modal;打开时焦点移入,模态时焦点被约束,关闭时焦点还原——通过 aria-label/aria-labelledby 命名Esc 关闭(持久对话框会抖动)
QMenu设计上无 role 的弹出;在内部 QList 上声明 role="menu";控件锚点上的 aria-expanded;关闭时焦点还原Esc 关闭;Tab 超出边缘时关闭并从锚点继续
QTooltip通过 aria-describedby 描述其锚点(显示时)——永不命名它;role="tooltip";键盘聚焦时显示Esc 关闭但不移动焦点(WCAG 1.4.13)
QPopupProxy根据屏幕尺寸在 QMenu 和 QDialog 之间切换——语义跟随渲染的组件委托
QPopupEdit基于 QMenu 的编辑面板;本地化的 设置/取消 按钮;关闭时不会静默提交Esc 取消;Enter 保存需要你自己连接

列表和数据

组件内置行为键盘
QList / QItem根据上下文派生 role:list/listitemmenumenuitem、可点击→button、链接保持链接;禁用的可操作项有 aria-disabled可点击项 Enter/Space
QExpansionItem头部 role="button" 配合 aria-expanded/aria-controls 和本地化展开/折叠标签;折叠内容真正隐藏Enter/Space 切换
QTable原生 <table>;可排序表头带有 aria-sort 和键盘排序;本地化的选择、分页和加载名称Enter/Space 排序;其他部分使用标准控件
QMarkupTable原生 <table> 包装器(可滚动区域是 Tab stop)——表头/scope/caption 语义由你负责原生
QTreerole="tree"/"treeitem"/"group" 配合 aria-expanded/selected/checked;虚拟模式添加 aria-level/setsize/posinset漫游 tabindex;方向键导航/展开/折叠、Home/EndEnter 选择、Space 展开——或在可勾选节点上勾选
QVirtualScroll填充区对辅助技术隐藏;切片变化时焦点不会落到 <body> 上;屏幕外的项目对辅助技术不存在当容器拥有滚动时,它是一个 Tab stop
QTimeline原生 <ul>/<li> 结构静态内容
QChatMessage文本内容可读;发送/接收仅是视觉区分——通过 name 传达作者身份静态内容
QCarousel导航为 tablist,使用漫游 tabindex 和逐幻灯片标签;幻灯片为 tabpanel;本地化箭头方向键(方向和 RTL 感知)、Home/End;选择跟随焦点

反馈和媒体

组件内置行为键盘
QBadgerole="status"(礼貌的 live region)、aria-label 来自 label
QBannerrole="alert"——动态插入时自动播报
QChip可点击 chip 为 role="button"(选择 chip 有 aria-pressed);删除图标支持键盘操作并带有本地化标签Enter/Space 激活/删除
QLinearProgress / QCircularProgressrole="progressbar" 配合值 ARIA(不确定状态时移除)——请添加 aria-label
QAjaxBar活动时有 progressbar ARIA,空闲时 aria-hidden
QSpinner无——搭配 live region 或作为装饰性隐藏
QInnerLoading仅视觉遮罩——需要你自己播报状态并管理被覆盖的内容
QSkeleton装饰性占位符——需要你自己标记加载区域
QIcon始终 aria-hidden="true";通过 attrs 为语义图标重新声明
QImgrole="img"alt 命名;alt="" 将其标记为装饰性
QAvatar / QCard展示性容器;tag prop 用于语义结构
QSeparator原生 <hr> 配合 aria-orientation
QVideo<iframe>title prop 命名——请务必提供内嵌播放器自身的
QParallax滚动驱动的运动;使用 media 插槽放置有意义的图片(alt)并考虑减少动画偏好的用户

布局和滚动

组件内置行为键盘
QLayout通过子组件构建地标骨架:<header><footer><aside><main>
QHeader / QFooter真正的 <header>/<footer> 地标;隐藏的边距条离开辅助技术树;reveal-hidden 模式在焦点时重新显示焦点触发重新显示
QDrawer<aside> 地标;遮罩层和打开条对辅助技术隐藏;叠加模式下无焦点陷阱Esc 关闭模态状态的抽屉
QPage渲染页面的 <main>——不要再添加另一个
QPageScroller定位包装器——在插槽中放置真正的按钮以支持键盘访问通过插槽中的按钮
QScrollArea自定义滚动条对辅助技术隐藏;内容溢出时容器是 Tab stop可聚焦后原生滚动键
QSplitter完整的 WAI-ARIA 窗口分割器:role="separator"aria-controls、值 ARIA、本地化名称方向键调节(RTL 感知)、Home/EndEnter 折叠/恢复
QSlideItem滑动操作仅支持指针——请提供键盘替代方案无内置
QInfiniteScroll通过原生滚动加载;加载状态不播报支持键盘滚动
QPullToRefresh指针手势;通过按钮暴露 trigger() 给键盘用户通过你自己的按钮

纯视觉或无渲染的工具组件,无无障碍表面:QSpaceQPageStickyQIntersectionQResizeObserverQScrollObserverQNoSsrQSlideTransitionQResponsive

外部资源

  • WCAG 2.2 — Web 内容无障碍指南快速参考
  • WAI-ARIA 创作实践指南 (APG) — Quasar 组件遵循的交互模式
  • MDN 无障碍 — 实用的 HTML/ARIA 参考
  • WebAIM — 文章、对比度检查器和屏幕阅读器调查数据
  • axe DevTools 和 Lighthouse — 浏览器和 CI 中的自动化审计
  • NVDA(Windows,免费)和 VoiceOver(macOS/iOS 内置)— 用来测试的屏幕阅读器