Figma Variables vs Styles: Web Content Accessibility Guidelines (WCAG) 2.2 — 4.5:1 Use Variables

Premium Deals
Mighty Travels Premium
Travel in style,
save up to 90%

On flights and hotels worldwide by booking the best deals when they appear.

See Deals

Sponsored

TakeawayDetail
Bind every normal text color to a Figma Variable, not a Style.A Style stores one fixed color value; a Variable can represent scoped, mode-switchable color tokens.
Require a minimum contrast ratio of 4.5:1 for normal text.Compute the WCAG 2.2 AA contrast ratio for each text-color Variable against its actual background.
Recalculate contrast whenever a text color or its background changes.Every changed Variable value or background pairing must be audited against the 4.5:1 threshold.
Audit every mode independently.Each scoped or mode-switchable Variable must meet the 4.5:1 AA ratio in every mode where the text color is used.

This guide explains how to audit Figma Variables against the WCAG 2.2 AA contrast threshold of 4.5:1 for normal text. It defines a Variable-first rule for managing text colors across scoped modes and changing value or background pairings.

Figma Variables vs Styles

Styles vs Variables: How Compliance Drifts

A Figma Style stores a single color value and applies that same value wherever it is selected. That makes a style convenient for reuse, but it also freezes the color across every context in which the style appears. The result is a predictable compliance drift: one swatch can be approved in one setting and become illegible in another. A color that works on the default canvas is not automatically safe on every card, panel, or tinted background.

For example, #767676 has a contrast ratio of approximately 4.54:1 against white, meeting the 4.5:1 requirement for normal text. Against a tinted gray surface such as #888888, the same color produces only about 3.83:1 and fails that requirement. The color did not change; the surface did. This is why checking a text Style against one background is insufficient. The check must be repeated for every distinct text-color and surface-color pairing in which the Style is used.

A Figma Variable handles this contextual difference differently. A Variable can be scoped specifically to text fill and assigned light and dark modes, allowing the foreground token to resolve to different values in different contexts. Contrast can then be validated once for each relevant Variable pair in each mode, rather than separately for every artboard that consumes the same token. If the surface color is also represented by a Variable, the audit can follow those semantic pairings and reveal the exact combination that needs correction.

WCAG.com’s Designers resource identifies color contrast and considerations for how and when color is used as part of accessible design. That is the appropriate responsibility for a design-system team: contrast is not a property of a swatch alone, but a relationship between foreground and background. Styles hide that relationship behind a reusable value; Variables preserve the contextual inputs needed to evaluate it.

The practical rule is to bind every text-color decision to a Variable, not a Style, and calculate its normal-text contrast against the corresponding surface Variable in each mode. Treat 4.5:1 as the audit threshold, record the resolved values for every mode pair, and repeat the calculation whenever either the text-color Variable or its paired surface Variable changes. This turns contrast from a one-time artboard inspection into a checkable, repeatable control over the system’s actual context-dependent combinations.

Styles vs Variables: How Compliance Drifts — Figma Variables vs Styles

The Evidence: What WCAG Actually Requires

WCAG.com describes itself as a central resource for understanding and applying the W3C Web Content Accessibility Guidelines (WCAG), and it connects those guidelines to four major accessibility regimes: the Americans with Disabilities Act (ADA), Section 508, the Accessibility for Ontarians with Disabilities Act (AODA), and EN 301 549. The practical significance is that the sourced WCAG 2.2 AA contrast requirement converges across those regimes: normal text must meet a contrast ratio of at least 4.5:1, while large text is subject to a 3:1 minimum. The compliance check should therefore begin with one authoritative threshold rather than four separately maintained legal interpretations.

For a Figma team, the corresponding rule is straightforward: every decision that assigns a text color must resolve to a Figma Variable, and that Variable’s value must be evaluated against the applicable WCAG threshold. This applies to semantic tokens such as body text, muted text, link text, headings, captions, and text placed on colored or image backgrounds. If a text color is defined only as a local fill or component property, treat it as unresolved until its source Variable is identified.

WCAG.com’s guidance for designers makes the relevance explicit: considerations including when and how to use color, color contrast, and link styling affect whether users can properly interact with content. The same interaction layer that Variables govern includes readability, state recognition, and discoverability. A practical review should therefore inspect each mode, including light and dark modes, and ask whether the foreground Variable still passes the contrast check against the background Variable assigned in that mode. A passing result in one mode is not evidence for another.

The Mozilla Foundation also publishes accessibility guidelines for designing websites for everyone. Its guidance should be used as a practical design checkpoint alongside WCAG, not as a substitute for the formal conformance criterion. During design review, select each text and background Variable pair, calculate the contrast ratio with a verified WCAG method, and record the result in the Variable documentation. Any pair below the applicable threshold requires a color, weight, or size decision before the design can be approved.

Use the final check as a release gate: confirm that every text-color decision has a named Variable source, evaluate every foreground–background pair in every active mode, and attach the calculated ratio to the audit record. This creates a traceable answer to a basic stakeholder question: which Variable produced this text color, where was it evaluated, and does it meet the governing WCAG 2.2 AA requirement?

The Evidence: What WCAG Actually Requires — Figma Variables vs Styles

Options Compared: Styles, Variables, Hybrid

Option A — Styles only is reasonable for a five-screen prototype because it offers a simple, reusable swatch without the overhead of a full token model. Its limitation appears when the product grows: every new background or surface requires another manual contrast check for the same text style. The loser condition is explicit—Styles alone are not suitable for any multi-mode product, because a team would have to discover, evaluate, and correct every affected text/background pairing individually.

Option B — Variables bound to the text-fill scope is the winner for teams shipping both light and dark surfaces. Create semantic variables such as text/primary and surface/background, then assign separate values for each mode. The practical check is to evaluate every text variable against every applicable surface variable in that mode, record the resulting contrast ratio, and require at least 4.5:1 for normal text. WCAG.com’s guidance for designers emphasizes that color contrast and other color considerations affect whether users can perceive and interact with content, so this check belongs in the design workflow rather than in a final handoff review.

Option Best fit Required check Decision
Styles only Five-screen prototype Recheck the text color whenever its background changes Loser for any multi-mode product
Scoped Variables per mode Products with light and dark surfaces Validate each mode-specific text/surface pair at 4.5:1 or better for normal text Winner
Hybrid Styles aliasing Variables Migration from an established style library Audit every alias, including its resolved value in each mode Acceptable only when the alias layer is audited

Option C — Hybrid can reduce migration friction by preserving familiar legacy swatches while adding an alias layer over Variables. Treat the alias as part of the compliance surface, not as harmless plumbing. Open each style, resolve its variable, identify the applicable mode, and check the resulting text/background combination. An unaudited alias is the hybrid approach’s named loser condition: it can silently preserve or reintroduce drift while appearing standardized.

Use one operational rule across all three options: every text-color decision must resolve to a Figma Variable rather than to a standalone Style value. Re-run the check whenever either variable value changes, and keep the ratio result attached to the relevant variable pair. This creates a reviewable trail for each mode without asking designers to infer whether a familiar swatch still works on a newly introduced surface.

Figma Variables vs Styles, photo 2

Auditing a Variable Set for 4.5:1

Step 1: Export the relevant Figma Variable collection as JSON. For every valid combination of a text variable and a background variable—including each mode in which the pair can appear—record the resolved hex values. Figma does not natively surface WCAG contrast ratios, so calculate each result independently. Convert each hex channel to a normalized value from 0 to 1, then linearize it: use channel / 12.92 when the channel is 0.04045 or lower; otherwise use ((channel + 0.055) / 1.055) ^ 2.4. Calculate relative luminance as 0.2126R + 0.7152G + 0.0722B. Next, identify the lighter and darker luminance values and calculate (lighter + 0.05) / (darker + 0.05). Compare the result with 4.5:1 for normal text.

Use a calculator, script, or browser-based contrast checker rather than judging the pair by eye. A ratio such as 21:1 for black text on white is easy to recognize as high contrast, but borderline results are not reliably distinguishable by sight. If a token resolves through aliases, calculate with the final resolved values for that mode, not the alias name. Keep the calculation method consistent across the entire collection so results remain comparable.

Text token Text hex Background token and surface Background hex Computed ratio Result
Body text, light mode #000000 Page background, light mode #FFFFFF 21:1 Pass

Step 2: Log every text/background pair in a token-audit table, as shown above. Include the token names, resolved hex values, mode or surface, computed ratio, and pass/fail result so another teammate can reproduce the check. A pass at 4.5:1 or higher records the normal-text result; if a pair is intended only for large text, label that separately rather than silently applying the normal-text result. WCAG.com’s Authors section emphasizes that accessibility work must continue beyond design into authoring and handoff. The audit table creates an explicit handoff artifact rather than leaving compliance as visual judgment.

Step 3: Re-run the audit whenever a variable’s value, alias, mode assignment, or intended background changes, and before releasing updated design-system guidance. Export the collection again, recalculate every affected pair, and update the logged ratio and result. If a change produces a failing normal-text pair, revise the variable value or surface mapping before handoff. This step-by-step method makes the audit reproducible, exposes calculations that cannot be verified reliably by eye, and keeps the logged record synchronized with the Variables that shipped.

Auditing a Variable Set for 4.5:1 — Figma Variables vs Styles

What the Evidence Does Not Establish

WCAG.com confirms that WCAG is the W3C’s framework for digital accessibility, while Mozilla’s accessibility guidance explains the relationship between WCAG and related laws and standards. These sources establish the authority and scope of the guidelines, but they do not establish that a Figma plugin calculates contrast correctly. Before trusting a plugin’s ratio, independently reproduce its result with your own luminance calculation: convert the variable’s foreground and background values to relative luminance, calculate the contrast ratio, and compare that result with the tool. If the values disagree, use the independently computed result and investigate the plugin.

The limits table below separates what the available sources sources confirm from what each design team must verify. Treat it as an audit boundary, not as evidence that every token pair must pass the same test in every context.

What the sources confirm What the team must verify When the rule breaks
WCAG is a W3C accessibility standard, and WCAG.com and Mozilla provide guidance about applying it. Whether a specific Figma plugin computes relative luminance and contrast ratios correctly. The normal-text contrast rule does not apply to every visual element.
Contrast requirements have defined exceptions rather than applying indiscriminately to all text and graphics. Whether a token is used for ordinary text, large text, inactive UI, a logo, or decoration. Logos, inactive user-interface components, and decorative text are exempt from the applicable contrast minimum.
Large text is evaluated under a different criterion from normal text. Whether the rendered text meets the exact size and weight conditions for large-text treatment. A label does not qualify merely because it appears prominent; verify the text-size and weight conditions.
Accessibility guidance is contextual. The actual foreground variable, background variable, mode, opacity, and rendered state for each use. A passing token pair can fail after a variable value, background, or mode changes.

Check the exemption list on WCAG.com before flagging a token pair as a failure. A color used only in a logo may be outside the text-contrast requirement, and the same can be true for inactive interface text or decorative text. Document the exemption and its applicable use instead of silently changing the token or treating the exemption as evidence that every use of that color is safe.

Classify text before evaluating it. The 4.5:1 threshold applies to normal text; large text is governed by the lower 3:1 threshold. For example, CSS text at 24 points qualifies as large, as does text at 18 points when it is bold. Confirm the rendered size and weight rather than inferring the classification from a component’s name.

Finally, bind each text-color decision to a Figma Variable and recheck the ratio whenever that variable’s value changes, its mode changes, or it is paired with a different background. This check must include the pair actually rendered, including relevant opacity and state. Neither the standard nor a plugin can certify a token in isolation: the defensible result comes from verifying the applicable threshold or exemption, the current variable combination, and the contrast calculation.

What the Evidence Does Not Establish — Figma Variables vs Styles

One Gray, Two Surfaces

Start with the three variables that determine the first contrast test: color/text-primary, surface/canvas, and surface/tint. For each pairing, convert the foreground and background colors to sRGB values, then calculate each color’s relative luminance by applying the WCAG relative-luminance formula to its red, green, and blue channels. After linearizing the channels, use L = 0.2126R + 0.7152G + 0.0722B, and calculate the contrast ratio as (lighter luminance + 0.05) ÷ (darker luminance + 0.05).

Do not reuse the result from one background for another. The audit needs three checkpoints: first, calculate the ratio for color/text-primary on surface/canvas; second, recompute color/text-primary on surface/tint; third, resolve the dark-mode alias for the text variable and validate that aliased value against the appropriate dark-mode surface. The third check is a separate row because an alias can change the value being tested even when the token name remains the same.

Variable pair Mode or surface Observed ratio Minimum Pass/Fail Reviewer/date
color/text-primary + surface/canvas Light canvas Record measured value 4.5:1 Pass / Fail Enter reviewer and date
color/text-primary + surface/tint Light tint Record measured value 4.5:1 Pass / Fail Enter reviewer and date
color/text-primary alias + dark surface variable Dark mode Record measured value 4.5:1 Pass / Fail Enter reviewer and date

Use this worksheet as the concrete token-audit artifact: it preserves the named variable pair, the mode or surface, the observed figure, and the pass/fail result instead of reducing the review to a visual approval. A blank or estimated ratio is not a passing result; the cell must contain the value obtained from the luminance calculation. For example, #767676 on #FFFFFF resolves to approximately 4.54:1 and passes, while the same text on a tinted surface such as #888888 resolves to only about 3.83:1 and fails. If a pair fails, adjust the relevant variable value and rerun the calculation for every affected surface.

The second checkpoint is the release gate most likely to be skipped. Assuming that a gray passed on the canvas means it will also pass on the tint can ship a failing text-background combination: #767676 meets 4.5:1 against white but drops to about 3.83:1 against #888888. Recording all three figures makes that assumption visible and gives the team a specific row to correct before handoff.

Worked Example: Run the Numbers

This illustration uses a hypothetical product audit dated January 15, 2026. The parties are the product design team, which owns the Figma library, and an accessibility reviewer, who approves text-color decisions. The scenario is a documentation site with a light mode and a dark mode. The relevant Variable set contains text/default, surface/default, text/dark, and surface/dark. The light-mode values are #767676 and #FFFFFF; the dark-mode values are #FFFFFF and #000000. WCAG.com’s design guidance identifies color contrast as an important consideration in accessible design.

The calculation starts with the WCAG relative-luminance formula. For #767676, each sRGB channel is 118/255, or approximately 0.462745. Applying the linearization rule gives a relative luminance of approximately 0.181164. White has a relative luminance of 1.000000. The contrast ratio is therefore (1.000000 + 0.05) ÷ (0.181164 + 0.05), which equals approximately 4.54:1. Because the measured result exceeds the 4.5:1 threshold for normal text, the light-mode pairing passes this check.

ModeTextBackgroundCalculationResult
Light#767676#FFFFFF1.05 ÷ 0.2311644.54:1 — pass
Dark#FFFFFF#0000001.05 ÷ 0.0521.00:1 — pass

The dark-mode calculation is simpler: white has a relative luminance of 1.000000, while black has a relative luminance of 0.000000. Their ratio is (1.000000 + 0.05) ÷ (0.000000 + 0.05) = 21.00:1. Thus, both mode-specific pairs in this illustrative Variable set pass the normal-text threshold. The reviewer records the two ratios, the tested Variable values, the audit date, and the passing decision for each mode.

For this example, the winner is the Variable-based pairing of text/default = #767676 with surface/default = #FFFFFF, alongside the 21.00:1 dark-mode pairing. The light-mode decision has little margin: the break-even trigger occurs when the text value becomes lighter than the allowed threshold. For example, #777777 produces a relative luminance of approximately 0.184475 and a ratio of 1.05 ÷ 0.234475 ≈ 4.48:1, below the required 4.5:1. Any later value change to text/default or surface/default therefore requires the ratio to be recalculated before that change is accepted.

Decision Rules: When Variables Win

Rule 1: If a color token appears on more than one surface background, make it a Variable, not a Style. Check every text-color token against the complete set of surfaces on which it appears. A token used on a light card and a dark panel must be evaluated in both contexts; a single Style value cannot represent those mode-specific values safely. The practical test is simple: if the same semantic token needs different foreground values across surfaces, it belongs in a Variable collection with a value mapped for each relevant mode.

Rule 2: If the product ships dark mode or plans to do so by the applicable WCAG 2.2 conformance deadlines, build mode-mapped Variables now. WCAG.com identifies the ADA, Section 508, and European Accessibility Act as distinct accessibility regimes, so teams should check the relevant ADA and EAA dates on that site rather than assume one universal deadline. Compare those dates with the product roadmap. If dark mode is shipped, committed, or scheduled before the applicable conformance milestone, define light and dark values together. Retrofitting a Style-based system after that point would require a second pass over every affected text color and surface pairing.

Rule 3: If a text token fails 4.5:1 in any mode, change the token value; do not override it at the component level. Run the contrast check against every mode and background combination, including hover, active, disabled, selected, and error states where the token remains readable text. Record the foreground, background, mode, ratio, and result for each pairing. A component-level override may make the failing instance look corrected, but it leaves the underlying token invalid and creates a new value that must be audited separately.

Rule 4: If a Variable’s value or its surface background changes, recompute the ratio before the change is released. Treat the audit as a release check, not a one-time design review. WCAG.com’s design guidance specifically identifies color contrast as a consideration in accessible design, while its broader resources connect WCAG conformance to multiple regulatory regimes. Therefore, every changed Variable-to-background pairing requires a fresh calculation and a logged result. A passing ratio from a previous value does not validate its replacement.

Rule 5: If a text color still lives in a Style when a second surface or mode is introduced, migrate that color to a Variable and re-audit it. This is the explicit migration trigger: the arrival of another surface or mode. At that moment, convert the Style into a semantic Variable, assign the mode-specific value, replace component references with the Variable, and verify the result in every affected context. The canonical rule is to bind every text-color decision to a Figma Variable whose mode-specific value has been computed against the WCAG 2.2 4.5:1 threshold for normal text, with the ratio audited whenever the Variable value or surface changes.

What to do next

StepActionWhy it matters
1Review every normal-text color decision and bind it to a Figma Variable rather than a Style.Variables provide scoped, mode-switchable color tokens, while Styles retain a fixed color value.
2For each text-color Variable, identify its actual background and calculate the WCAG 2.2 contrast ratio.Contrast must be evaluated for the real color pairing used in the design.
3Check each pairing against the 4.5:1 AA threshold for normal text and resolve any pairing that falls below it.Every text-color Variable must support accessible normal-text contrast.
4Audit each mode independently, including every mode in which the Variable’s text color is used.A mode can change the text color or background and alter the contrast result.
5Add a review whenever a Variable value or its background pairing changes, and recalculate the ratio for all affected modes.The audit belongs to the token and its background pairing, not to each place where the Variable is applied.

Frequently Asked Questions

Why should normal text colors be bound to Figma Variables instead of Styles?

A Variable can represent scoped, mode-switchable color tokens, while a Style stores one fixed color value that can become illegible in another context.

What contrast ratio must each normal text-color Variable meet?

Each text-color Variable must meet a minimum contrast ratio of 4.5:1 against its actual background.

When must contrast be recalculated during a design audit?

Contrast must be recalculated whenever a text color or its background changes.

What must happen after a Variable value or background pairing changes?

Every changed Variable value or background pairing must be audited against the 4.5:1 threshold.

How should a Variable be checked when it is used in multiple modes?

Each mode must be audited independently, and the Variable must meet the 4.5:1 AA ratio in every mode where the text color is used.

Does a text color that passes on the default canvas automatically pass on cards, panels, or tinted backgrounds?

No, because a color that works on the default canvas is not automatically safe on every card, panel, or tinted background.

Quick answers

What should every normal text color be bound to instead of a Style?Bind every normal text color to a Figma Variable.
How does a Figma Variable differ from a Style for text colors?A Style stores one fixed color value, while a Variable can represent scoped, mode-switchable color tokens.
Against what should each text-color Variable be checked?Compute the WCAG 2.2 AA contrast ratio for each text-color Variable against its actual background.
When should contrast be recalculated?Recalculate contrast whenever a text color or its background changes.
How should scoped or mode-switchable Variables be audited across modes?Audit every mode independently, and require each Variable to meet the AA ratio in every mode where the text color is used.

Also worth reading: Brand-Voice Drift: Score Your AI Content, Gate Below 90: Brand-Voice Drift: Score Your AI · Quorum Mechanism Cuts Brand Approval 40%: Forrester Data: Quorum Mechanism Cuts Brand Approval · Brand-Safety Queueing: Why the 48-Hour Intake SLA Holds Up: Brand-Safety Queueing: Why the 48-Hour

Premium Deals
Mighty Travels Premium
Travel in style,
save up to 90%

On flights and hotels worldwide by booking the best deals when they appear.

See Deals

Sponsored

Research Methodology & Editorial Standards

We begin by defining the specific objectives the reader needs to accomplish. Primary product documentation and authoritative secondary sources are assembled into a verified research corpus; drafting occurs only after this foundation is in place.

Every quantitative claim is subjected to dual-source verification. Any figure that cannot be independently corroborated is either qualified or omitted.

Published · Last reviewed · Owned by the Kimamani editorial desk (About, Contact, Privacy).

Related answers