发布于 2026-08-20 · 作者 MarkupGen 团队
Figma 转无障碍 HTML:实用指南

快速回答: 在 Figma 转 HTML 的工作流中,无障碍访问并不是打开一个开关就能解决的事——而是一系列具体的决策:用真正的语义化元素代替加了样式的
<div>,标题顺序匹配内容结构(Figma 本身并没有"标题层级"这个原生概念),为表单字段和纯图标按钮添加标签,设计可见的焦点状态,保证足够的颜色对比度,以及谨慎使用 ARIA——只在语义化 HTML 本身无法表达这种交互时才用。自动化输出可以帮你完成大部分工作;但仍需要一次简短的人工核查,来补上设计文件本身无法承载的信息。
为什么无障碍访问会在 Figma 转 HTML 的过程中丢失
Figma 文件描述的是设计"看起来"是什么样子。它并不会描述屏幕阅读器应该朗读什么内容、下一个该获得焦点的是哪个元素,或者某一对颜色对视力低下的用户来说是否清晰可辨。这个信息差,才是无障碍访问在转换过程中出问题的真正原因——不是因为疏忽,而是因为无障碍访问所需要的一部分信息,本来就不存在于设计文件里。即便视觉效果做到像素级还原,如果底层标记只是一堆没有结构、没有标签、也不支持键盘操作的通用 <div>,它在无障碍访问上依然是失败的。
解决办法不是靠一次自动化处理就能搞定的。而是要弄清楚:哪些无障碍访问方面,一款优秀的转换工具已经能通过生成真实结构(而不是纯视觉标记)自动做对;哪些方面则始终需要设计师、开发者,或者两者共同做出主动决策——因为这些信息,设计文件本来就没有携带。
影响无障碍访问的 Figma 设计决策
在任何转换工具介入之前,一些常见的 Figma 使用习惯,就已经会在后续环节埋下无障碍访问问题:
- 只靠颜色传递信息。 用红色标记的必填表单字段,或者只是把同一颜色调浅一档来表示的禁用按钮——对于无法区分这些色调的用户来说,这些区别都是不可见的。这种区分需要一个额外的信号(图标、文字标签、图案),而不能只靠颜色变化。
- 把文字做进图片里。 一个导出成扁平化 PNG 的标题,看起来可能和真实文字图层一模一样,但它无法被屏幕阅读器朗读,无法被浏览器调整大小,也无法被爬虫索引。
- 没有设计可见的焦点状态。 大多数 Figma 组件集都设计了默认、hover,有时还有 disabled 状态——但焦点状态(供使用键盘 Tab 键浏览页面的用户使用)往往根本没被设计出来,因此转换过程中也就没有东西可以承接。
- 纯图标按钮在文件里没有任何无障碍名称。 一个表示"删除"的垃圾桶图标,视觉上一目了然。但除非图层本身被赋予有意义的命名,否则 Figma 图层里没有任何信息能告诉转换工具——或屏幕阅读器——这个图标究竟是什么意思。
- 标题大小不一致。 Figma 并不像 CMS 或文字处理软件那样有专门的"Heading 2"元素——文字图层就只是文字,只不过被设置成看起来是某种大小而已。两个在不同 frame 里视觉上很相似的标题,在实际内容层级中完全可能代表完全不同的级别。
这些都不是转换工具的 bug,而是必须在流程中的某个环节被决定下来的事情——提前认识到这一点很重要,而不是想当然地以为工具会自动推断出来。
语义化 HTML 与地标元素
这是一款优秀的 Figma 转代码工具理应默认就能做对的部分:使用真正的 <header>、<nav>、<main>、<article>、<section>、<aside> 和 <footer> 元素,而不是整页都用没有标签的 <div> 搭建。地标元素之所以重要,是因为屏幕阅读器用户正是靠它们直接跳转到"主要内容"或"导航",而不需要按顺序逐个 Tab 键浏览整个页面。想了解 MarkupGen 输出在结构上具体是什么样子,可参考 Figma to Semantic HTML;想了解语义化标记和可爬取性之间的重叠关系,可参考 Is Figma-to-HTML Output SEO-Ready?——这两个问题背后的根本原因相同,解决方式也大体相通。
标题层级
每个页面只有一个 <h1>,并且标题要按顺序逐级下降——<h3> 应该出现在已经有 <h2> 的区块里面,而不是仅仅因为设计中某个文字图层看起来是那个大小,就直接跳到这一级。如前所述,Figma 本身没有标题层级这个原生概念,所以一个样式设置得很大的文字图层,并不会自动变成 <h1>——无论标记是由哪种工具生成的,这一点都值得人工核查,因为它取决于对内容实际结构的理解,而不只是视觉大小。
按钮与链接
这是转换后标记中最常见的无障碍访问错误之一,而且 Figma 的组件结构并不会替你解决这个问题:<button> 用于当前页面上的某个动作(提交、打开弹窗、删除某项内容);<a href> 用于跳转到另一个页面或视图。一份设计文件里满是样式相同的胶囊形状按钮,根本无法看出哪个是哪个——这是一个语义层面的决策,而不是视觉层面的,它会直接影响键盘行为(按钮和链接默认响应的按键并不相同)以及屏幕阅读器朗读的内容。
表单与标签
每个输入框都需要一个真正的、以编程方式关联的 <label>——而不是用 placeholder 来充数。placeholder 文字一旦用户开始输入就会消失,默认对比度也普遍偏低,而且并非所有屏幕阅读器都会可靠地把它当作标签朗读出来。如果出于设计原因,表单看起来需要"没有标签",应该使用视觉上隐藏的标签,而不是直接把标签从标记中彻底移除。错误提示信息需要与对应字段建立关联(通常通过 aria-describedby),而不能只是放在字段附近、单纯靠颜色来提示问题。
图片与 alt 文字
导出的图片需要有意义的 alt 属性,而不是空字符串或者一个文件名。这是少数几个真正无法绕开人工核查的环节之一:一张装饰性背景图究竟是用来做什么的,和一张产品图需要被如何描述,往往仅凭 Figma frame 本身是看不出来的——设计文件承载的只是像素,而不是意图。纯装饰性的图片应该使用空的 alt=""(这样屏幕阅读器会跳过它们),而有实际意义的图片则需要真实描述它们所传达的内容,而不只是它们看起来是什么样子。
键盘导航
每一个可交互元素——链接、按钮、表单字段——都需要能够仅通过键盘访问和操作,并且顺序要与视觉阅读顺序保持一致。这正是 Auto Layout 真正有帮助的地方:因为 Auto Layout 的结构会延续为一个符合逻辑的 DOM 顺序,而不是一堆绝对定位的碎片,所以 Tab 键的浏览顺序往往会自动跟随阅读顺序,而不会像自由排布、绝对定位的布局那样,出现无法预测的跳跃。
焦点状态
由于 Figma 的组件集很少包含专门设计的焦点状态,这通常是转换后页面里最常见的一个无障碍访问缺口:使用键盘的用户在界面中按 Tab 键浏览,却完全看不出自己当前停留在哪个位置。最起码,不要在移除浏览器默认的焦点轮廓(outline: none)之后,不用同样醒目的样式去替代它——这是一个很常见、也很容易在"还原设计"的名义下被上线的错误,而设计本身其实从一开始就没有考虑过这一点。
颜色对比度
Figma 允许你随意选择任意两种颜色搭配,而不管它们放在一起是否清晰可辨,所以这一点需要明确核查,而不能想当然地假设没问题。WCAG AA 标准要求正文文字的对比度至少达到 4.5:1,大号文字(18px 以上加粗,或 24px 以上常规字重)以及图标、输入框边框等有意义的 UI 组件则至少要达到 3:1。在转换之前,先用对比度检测工具核查设计中实际使用的颜色搭配——在 Figma 里修正一个色值 token,远比事后在生成的标记里到处排查要划算得多。
ARIA——什么时候有用,什么时候反而有害
ARIA 的第一原则至今依然成立:与其用错的 ARIA,不如不用 ARIA。一个原生的 <button> 本身就已经拥有正确的 role,可以获得焦点,并且默认就能响应 Enter 和空格键——给它再加上 role="button" 没有任何实际作用,反而有可能和元素本身真正的语义产生冲突。ARIA 真正该出场的场景,是语义化 HTML 本身无法独立表达这种交互的时候:
- 该用的场景: 给没有可见文字的纯图标按钮加上
aria-label(比如意味着"删除"的垃圾桶图标);给控制可折叠区域的开关加上aria-expanded;给无需刷新页面就会更新内容的区域加上aria-live="polite"(比如表单校验提示、购物车数量)。 - 不该用的场景: 给已经拥有正确原生语义的元素额外加上 ARIA role;使用与已经可见并会被朗读的内容重复的装饰性 ARIA;或者在并非真正紧急的场合使用
aria-live="assertive"——它会打断屏幕阅读器正在朗读的内容,也非常容易被滥用。
响应式场景下的无障碍访问
无障碍访问问题不会因为在某一个尺寸下被修好了,就在所有断点下都保持修复状态。即使布局被压缩,移动端的触控目标也至少需要维持在大约 44×44px——一个在桌面端点击起来很舒适的按钮,一旦被 Auto Layout 的缩放约束压小,就可能变得太小、难以稳定点按。文字需要能够自适应换行,而不是在窄屏下被裁切或重叠,内容顺序也不应该在不同断点之间发生令人困惑的变化,从而破坏屏幕阅读器所依赖的那种符合逻辑的阅读顺序。
常见的 Figma 转 HTML 无障碍访问错误
- 每一个可点击元素都被转换成了
<div onclick>,而不是真正的<button>或<a>。 - 纯图标按钮没有
aria-label,因为对应的 Figma 图层就只被命名成了"Icon 4"。 - 状态(错误、禁用、选中)仅靠颜色来传达。
- 焦点状态被设置了
outline: none,却没有用任何可见的样式来替代。 - 表单字段仅用 placeholder 文字充当唯一的标签。
- 装饰性图片的
alt文字被设成了文件名,而不是空的alt=""。 - 标题层级是根据设计中的字号来选定的,而不是根据实际的内容结构。
前后对比:一个纯图标按钮
改造前——视觉效果正确,但不具备无障碍访问能力:
<div class="icon-btn" onclick="deleteItem()">
<svg><!-- trash icon --></svg>
</div>
改造后——视觉效果相同,但真正可用:
<button type="button" class="icon-btn" aria-label="Delete item" onclick="deleteItem()">
<svg aria-hidden="true"><!-- trash icon --></svg>
</button>
两者的差别完全不在视觉层面——而在于:一个真正的 <button> 元素(可获得焦点、可通过键盘操作、能被屏幕阅读器正确朗读)、一个赋予图标无障碍名称的 aria-label,以及给装饰性 SVG 加上的 aria-hidden="true",使其不会被重复朗读一遍。
实用无障碍访问清单
- 每个页面只有一个
<h1>;标题按层级顺序下降,而不是按字号大小排列 - 存在真正的地标元素(
header、nav、main、footer) - 每一个可点击的动作都是
<button>;每一个导航链接都是<a href> - 每个表单输入框都有一个真正关联的
<label>——而不只是一个 placeholder - 有意义的图片配有描述性的
alt文字;装饰性图片使用alt="" - 每个可交互元素都有可见的焦点状态
- Tab 键顺序与视觉阅读顺序一致
- 文字和 UI 组件的对比度符合 WCAG AA 标准(4.5:1 / 3:1)
- 颜色永远不是传达状态或含义的唯一信号
- ARIA 只用在语义化 HTML 本身无法表达该交互的地方
- 触控目标在移动端断点下依然可用
- 布局在窄屏下能够自适应换行,不会出现文字裁切或重叠
生产上线前应如何审查生成的代码
MarkupGen 的输出默认就会优先使用语义化元素和真实的标题结构,而不是需要额外开启的选项,而 Auto Layout 的结构能够延续成符合逻辑的 DOM 顺序,正是让正确的 Tab 键顺序从一开始就成为可能的主要原因。每次导出都会获得的自动 AI 质量评分,确实是一个很有用的初步信号——但它明确是一个视觉匹配评分,比较的是渲染出的预览效果与原始设计。它并不会核查 ARIA 是否正确、对比度是否达标,或者键盘行为是否正常,因为这些在截图对比里根本看不出来。把上面这份清单当作在拿到高视觉评分之后还要做的人工核查,而不是替代它——关于这一原则在更广泛的代码审查中的应用,可参考 How to Evaluate AI-Generated HTML Before You Ship It。
在你自己的设计稿上试试看
想知道一份设计在哪些地方需要做无障碍访问核查,最快的方式就是把它转换出来,打开真实的标记代码看一看。免费试用 MarkupGen,或者先阅读完整的 Figma 转 HTML 转换指南,了解本文所建立在其上的端到端工作流。
