Plugins for Checking Accessibility in Figma Before the Handoff
Evaluate Figma accessibility plugins by what they catch before code exists: contrast violations, missing focus orders, and heading structure errors that CSS alone cannot fix.
The Handoff That Happens Before the Code
Open the Figma file. A red outline sits around the primary button. The annotation reads 'focus order: 3' and the contrast ratio next to it shows 3.2:1 against the header background. Before you write a single line of CSS, you know this component fails WCAG 2.2 AA for normal text. You also know the developer receiving this file must fix it or ship accessibility debt. Figma accessibility checker plugins earn their place at this moment. They catch what code linters and devtools miss, because the design is not code yet.
What Figma Accessibility Checker Plugins Catch Before Development
Code linters run against CSS, HTML, and JavaScript. They flag missing alt attributes or an `outline: none`. They cannot see the design intent that never made it into a class name. A Figma accessibility audit before development works on the source of truth: the visual layout. Plugins like Stark, Able, and Contrast read the canvas. They compute ratios from the actual fill colors, not from a variable name that might be wrong. They simulate color blindness by transforming the entire artboard into protanopia, deuteranopia, or tritanopia views, so you see which adjacent elements collapse into the same tone. They walk the layer tree and flag purely decorative elements that lack an alt text placeholder. They list every text layer that falls below the 4.5:1 threshold for normal size or 3:1 for large text.
Structured Reports, Not Screenshots
The developer receives a structured report. It is a CSV or a JSON payload listing each violation with the layer name, the exact color pair, the measured ratio, and the WCAG success criterion breached. That plugin output becomes the ticket you paste into your issue tracker. What these tools cannot check is the interactive state: a hover color that appears only on a prototype trigger, or a focus ring drawn outside the component frame. They cannot verify that the spacing around a touch target meets the 24 by 24 CSS pixel minimum for WCAG 2.2, because spacing is not a visual property a checker can parse from pixel fills alone. You still need a human to read the annotation layer for those.
WCAG Contrast Check Figma Plugin: The 4.5:1 and 3:1 Thresholds
Every WCAG contrast check Figma plugin you install computes the same formula: (L1 + 0.05) divided by (L2 + 0.05), where L1 is the relative luminance of the lighter color and L2 of the darker one. The plugin does not invent the math. It applies WCAG 2.2's unchanged requirement, which demands 4.5:1 for normal text and 3:1 for large text, defined as at least 18 point or 14 point bold. The value that matters for your CSS is not the ratio itself but the color pair that produces it. When the plugin flags a failure, you need a replacement color that passes. The plugin's suggestion is often a darker shade of the same hue. Verify it against the design system's palette rather than accepting the first suggestion.
Gradients and Images: The Sampling Problem
A common failure case is a text layer over a gradient or an image. The plugin samples the background at the text's bounding box, but a gradient shifts the luminance across the box. The measured ratio holds at the sample point and fails at the edge. Put the text in a solid container or use a `text-shadow` that darkens the background behind the glyphs. Do not ship a gradient background with white text and hope the plugin is wrong. The browser renders the same gradient, and the ratio remains 2.8:1 where the text crosses the lightest band. The plugin reports what the browser will compute. It does that reliably for flat colors.
Focus Order Annotation Figma Design: Making Keyboard Navigation Explicit
Focus order annotation in Figma design is a layer property, not a CSS property. Place a numbered label on each interactive element, button, link, input, select, in the order a keyboard user should tab through them. The plugin, such as the one from the Stark suite, exports that annotation as a list mapping to a `tabindex` sequence in the DOM. For a developer, this is gold: it tells you the intended order before you write the HTML. A linter cannot infer focus order from a flex row that wraps on a narrow viewport, because the visual order changes at the breakpoint. The annotation gives you the source order that must hold in the markup.
Building the Focus State from the Annotation
Here is a runnable CSS sample that builds a focus state from that annotation. The annotation says the primary button is focus order 3, and the design specifies a 2px solid outline in the accent color with a 4px offset. Your CSS uses `:focus-visible` with a `:focus` fallback, because older versions of Safari do not support `:focus-visible` and would otherwise show no indicator.
/* From Figma focus order annotation: element 3, outline: 2px #005FCC, offset: 4px */
.button-primary:focus {
outline: 2px solid #005FCC;
outline-offset: 4px;
}
.button-primary:focus-visible {
outline: 2px solid #005FCC;
outline-offset: 4px;
}
/* Do not remove the :focus rule: it is the fallback for browsers without :focus-visible */
The annotation also tells you which elements to skip, like a decorative SVG that is not focusable. That is where the `inert` attribute comes in: setting `inert` on a container removes it from focus order and from the accessibility tree. You want this for a modal's backdrop when it is closed. The common mistake is using `aria-hidden="true"` on a focusable element, which hides it from screen readers but leaves it in the tab order, creating a focus trap. The annotation prevents that by marking the element as non-interactive, and you translate that to `inert` in the HTML.
Accessible Color Palette Figma Plugin: From oklch to CSS Variables
An accessible color palette Figma plugin does not check individual pairs in isolation. It audits the entire palette for internal harmony. Plugins like Contrast and Able generate a matrix of every color combination, flagging those that fail 4.5:1 or 3:1. They also suggest colors in the oklch color space, which is perceptually uniform. A 10% lightness change looks like a 10% lightness change to the eye. This is a step beyond WCAG's relative luminance, which is a formula, not a perception model. The plugin exports the palette as CSS custom properties, and you drop those into your `:root` block.
Here is a CSS color scheme derived from a plugin-verified accessible palette. The plugin confirmed that the text color #1A1A1A on background #FFFFFF passes at 16:1, and that the accent color #0066CC on white passes at 5.6:1. The variables carry the design system's names, so the handoff is unambiguous.
:root {
--text-primary: #1A1A1A; /* on white: 16:1, passes AAA */
--background-base: #FFFFFF;
--accent-action: #0066CC; /* on white: 5.6:1, passes AA */
--accent-hover: #004499; /* on white: 7.9:1, passes AAA */
--surface-muted: #F2F2F2; /* for cards, not for text */
}
/* Usage: color: var(--text-primary); background-color: var(--background-base); */
The plugin cannot verify that a hover state meets the requirement when the hover color is applied only in a prototype's interaction trigger. That is a manual review gap you must close by checking the hover swatch in the same tool. A common failure is a design that uses a lighter gray for disabled text, which fails 3:1 against the background. The plugin flags it. Fix it by using the same text color with reduced opacity only if the background is solid, but opacity is not a color change, so you still need the underlying ratio to hold.
Figma Accessibility Audit Before Development: Heading Hierarchy and Landmark Annotation
A Figma accessibility audit before development covers more than colors and focus. It checks the heading hierarchy. Every text layer that is a heading carries a level: H1, H2, H3, and so on. The plugin scans the layer names or the text style and produces a tree that shows whether a jump skips a level, like going from H2 to H4. That tree is the specification for your HTML. A CSS linter cannot know that your `h3` element is actually the page's fourth heading in visual order, because the visual order might be a two-column layout where the left column has the H1 and the right column has an H2 that appears first in the DOM. The annotation resolves that.
Translating Audit Output to Semantic HTML
Here is an HTML heading structure built from a Figma heading hierarchy audit. The audit output listed the heading levels in reading order. Translate that directly into semantic elements, not divs with classes.
<h1>Account Settings</h1>
<h2>Profile Information</h2>
<h3>Display Name</h3>
<h3>Email Address</h3>
<h2>Security</h2>
<h3>Change Password</h3>
Landmark Annotations and Touch Targets
Landmark annotation is the other output: the plugin lets you mark a frame as a banner, navigation, main, or complementary region. The developer maps those to the ` `, ` `, ` `, and ` ` elements. A common failure is a design where the footer contains a newsletter signup that is visually below the content but semantically part of the main flow. The annotation tells you to wrap it in the main landmark, not a separate footer, so screen reader users do not traverse the footer twice. The audit also covers touch target size, flagging any element smaller than 24 by 24 CSS pixels, which is the WCAG 2.2 minimum for pointer targets, not the older 44-pixel guideline that was a recommendation.
WCAG Contrast Check Figma Plugin: What It Cannot See
A WCAG contrast check Figma plugin has a blind spot for APCA, the method proposed for WCAG 3.0. APCA is a draft specification, not a W3C Recommendation as of the latest working draft. No Figma plugin computes it natively yet. APCA produces a different number, called Lc, ranging from 0 to 106, with a polarity sign for light-on-dark versus dark-on-light. The plugin you have computes the WCAG 2.x ratio, which remains the legally referenced standard in Section 508, EN 301 549, and most procurement contracts. If your client asks for APCA, you need a separate tool. Tell them no engine ships a `color-contrast()` function that would compute it automatically. That CSS function is in the Color Module Level 6 working draft, and it will not run anywhere.
Invisible Failures the Plugin Misses
The plugin also cannot catch a focus indicator that is removed entirely. The classic failure is a developer who writes `outline: none` on a button and replaces it with a `box-shadow` that only appears on `:focus`, not `:focus-visible`. In a browser lacking `:focus-visible` support, the keyboard user gets no indicator at all. The Figma annotation specifies the outline, but the plugin does not check your CSS. You must verify the fallback rule exists. Another invisible failure is the visually-hidden class: the plugin checks that a label exists, but it cannot know that the CSS for visually-hidden forgot `white-space: nowrap`, which causes the label to wrap into a visible line and break the layout. The audit catches the missing alt text placeholder, but not the CSS that implements it incorrectly.
What the Developer Receives: Plugin Output Format and the Manual Review Gap
The plugin output format varies by tool. The useful ones export a structured list. Stark exports a CSV with columns for the layer name, the issue type, the WCAG criterion, the measured value, and the suggested fix. Able exports a JSON object you can feed into a script that creates tickets in Jira. Contrast gives you a visual overlay on the canvas, but you can also copy the color pairs as CSS variables. The output is machine-readable. You do not retype a ratio or a color hex and risk a typo. That is the difference between a plugin and a screenshot.
Closing the Manual Review Gap
The manual review gap is the space between what the plugin measures and what the browser renders. Plugins assume the design file is the truth. The browser is the final renderer. A gradient background, a `text-shadow`, a filter like blur or saturate, and an opacity below 1 all change the effective ratio in ways the plugin cannot sample because those effects are applied in CSS, not in Figma's fill. The honest workflow: use the plugin to catch the flat-color failures, then run a tool like the Accessibility Insights extension on the built page to catch the composited failures. The plugin reduces the accessibility debt you would otherwise accumulate in the handoff. It does not eliminate the need for a runtime check.
The one thing the plugin cannot give you is a pass for WCAG 2.2 success criterion 2.4.11, which requires a focus not obscured by other content. That depends on whether a sticky header or a modal overlaps the focused element at the moment of focus, which is a runtime state. The annotation can mark the expected focus target, but the browser decides whether it is visible. Your CSS can mitigate it with `scroll-margin-top` on the element. The plugin will not tell you which value to use. That is a manual decision informed by the actual viewport height.
FAQ: Five Questions Developers Ask About Figma Accessibility Plugins
Q: Do Figma accessibility plugins replace manual accessibility testing?
A: No. They catch static contrast, focus order, and heading hierarchy in the design file. They cannot verify runtime states like hover, focus visibility under a sticky header, or screen reader announcements. You still need a manual keyboard walk and a screen reader test on the built page.
Q: What is the difference between WCAG contrast and APCA?
A: WCAG 2.x uses a formula based on relative luminance, which is a mathematical approximation. APCA is a perceptually based model proposed for WCAG 3.0, but it is a draft with no browser support and no legal standing yet. Use WCAG 2.2 for compliance, and treat APCA as a research preview.
Q: Can a Figma plugin check touch target size in WCAG 2.2?
A: Yes, but only if the element is a frame with a defined width and height. The plugin flags anything below 24 by 24 CSS pixels, which is the WCAG 2.2 minimum. It does not check the spacing around the target, which is also a requirement, so you must verify that manually.
Q: What should I do when the plugin flags a failure but the client insists on the color?
A: Ask for the brand color to be used only for large text (at least 18pt or 14pt bold) or for decorative elements that are not the sole means of conveying information. If it must be normal text, provide a darker shade that passes 4.5:1. The plugin's suggestion is a starting point, not a verdict.
Q: How do I integrate the plugin output into my design system?
A: Export the palette as CSS variables and the focus annotations as a comment in the component's code. The plugin output format is not a standard, so treat the CSV or JSON as an intermediate format. The lasting artifact is the variable names and the focus rule you write into your base stylesheet.
The Full Picture: What a Figma Accessibility Checker Plugin Handoff Actually Looks Like
You are at the end of a sprint, and the design file is final. The Figma accessibility checker plugin handoff is the bridge between the design and the code. Run the audit. Export the report. Paste the violations into your issue tracker. Fix the contrast failures by swapping in the plugin-suggested colors, which you then define as CSS custom properties. The focus order annotation becomes a `tabindex` sequence in your HTML, or more likely, a DOM order that matches the visual order by restructuring the markup. The heading hierarchy becomes the actual `h1`, `h2`, and `h3` elements. The landmark annotations become the ` `, ` `, ` `, and ` ` wrappers.
Where the Workflow Fails
The failure case is when the plugin finds nothing, and you trust it blindly. The plugin cannot see the focus trap created by an `aria-hidden` container with a focusable child, nor can it see the visually-hidden label that wraps because `white-space: nowrap` is missing. Those are CSS failures that only a runtime test reveals. The plugin's real value is that it forces the design to specify the accessibility contract before code. The developer is not guessing. It is a tool for the design-system author who needs to defend a 4.5:1 minimum to a brand manager, and for the performance-conscious developer who knows that fixing contrast in CSS later costs a re-render and a round trip with the designer.
Who This Workflow Suits
This workflow suits the front-end developer who writes CSS daily and wants to ship a component that does not carry accessibility debt. It suits the design-system author who needs a vocabulary to explain why a color fails and what the fallback is. It does not suit the designer who wants to keep the creative freedom of a low-contrast palette without a legal consequence, because WCAG 2.2 is referenced in procurement contracts across the EU, US, and Canada, and the browser will not bend the formula. It also does not suit the developer who relies solely on the plugin and skips the audit, because the manual review gap is where the real failures live.
The One Sentence That Makes This Page Different
A Figma accessibility plugin can flag a 2.8:1 contrast ratio on a flat color pair, but it cannot see the browser's gradient that drops the effective ratio to 2.1:1, so the developer must still run a runtime check before shipping.