A Figma plugin that finds accessibility problems in your designs: text with too little contrast against its background, and buttons or icons that are too small to tap. Select a frame, press Check, and every problem shows up in a list. Click an issue to jump straight to that layer.
For every text layer in the selection, the plugin compares the text colour with the colour behind it and calculates the contrast ratio, using the WCAG relative luminance and contrast ratio formulas.
| Text | Minimum ratio |
|---|---|
| Normal text | 4.5 : 1 |
| Large text: 24px or more, or 18.66px or more and bold (weight 700+) | 3 : 1 |
Each issue shows the measured ratio and the ratio it needs, for example 2.85:1, needs 4.5:1.
Layers whose name contains button, btn or icon (any capitalisation) are treated as tappable and checked by size:
| Size | Result |
|---|---|
| Smaller than 24 × 24 | Fail (WCAG 2.2 target size minimum) |
| Smaller than 44 × 44 | Warning (Apple's recommended touch target) |
- Issues are grouped into Contrast and Tap targets, with a total at the top.
- Clicking an issue selects the layer on the canvas and zooms to it.
- Text layers the plugin can't check reliably are counted and listed as "not checked" (see below), so nothing is silently ignored.
- The panel follows Figma's light and dark theme, works with the keyboard, and respects "reduce motion". Its own colours pass WCAG AA.
- Collect text layers. The plugin walks the layer tree recursively, including groups and nested frames, and records each text layer's size, weight and colour.
- Find the background. From each text layer it walks up through its parent containers until it finds one with a visible solid fill. That fill is used as the background.
- Check contrast. Both colours are converted to relative luminance and compared against the AA thresholds above.
- Check tap targets. A second walk through the tree checks the width and height of every layer named like a button or icon.
All checks run locally inside Figma. The plugin makes no network requests (networkAccess: none).
These are deliberate simplifications, worth knowing before you rely on the results:
- The background comes from parent containers, not from pixels. Text that sits on top of a shape without being inside it is compared with the container behind both, not with the shape.
- Images and gradients behind text aren't supported. If the nearest filled container uses an image or gradient, it isn't used as the background.
- Fill opacity is ignored. A 20% opacity dark fill is treated as solid dark, even though it looks light on screen.
- Some text is skipped: text with mixed font sizes or weights, text with a gradient or image fill, and text with no solid background behind it at all. The skipped count tells you how many layers to check by eye.
- Tap targets are found by layer name. A button named "Rectangle 5" won't be checked, and a layer like "Iconography header" can be flagged by mistake.
You need Node.js and the Figma desktop app.
git clone https://github.com/develop212/accessibility-checker.git
cd accessibility-checker
npm install
npm run buildThen in Figma: Plugins → Development → Import plugin from manifest… and choose manifest.json from this folder.
While working on the code, run npm run watch to rebuild on every save, and npm run lint to check the code.
| File | What it does |
|---|---|
code.ts |
Runs inside Figma: collects text layers, finds backgrounds, handles messages from the panel, selects and zooms to layers |
contrast.ts |
Relative luminance, contrast ratio and the AA pass/fail rule |
taptargets.ts |
Finds buttons and icons by name and checks their size |
ui.html |
The plugin panel: results list, empty states and styling |
manifest.json |
Plugin settings for Figma |
The TypeScript files are combined into a single code.js by npm run build (see outFile in tsconfig.json), because Figma loads one script file.
The contrast approach was informed by Figma-Contrast by Roman Nurik.
