Figma Component Variants: When One Master Component Beats Twenty Copies
Component Variants collapse sprawling per-state components into one master with explicit properties. Here's how they work with auto-layout and libraries, a concrete button example, and where they break down.
21 Nov 2025, 07:54 UTC

If you've ever inherited a Figma file with Button/Primary/Large/Hover, Button/Primary/Large/Default, Button/Primary/Medium/Hover… you know the failure mode. Every state is a separate component, a color change means editing a dozen of them, and sooner or later one copy drifts out of sync. Component Variants exist to collapse that sprawl into a single master component whose states are switched from a dropdown instead of hunted down in the assets panel.
The thesis of this piece is simple: variants pay for themselves when a component has a small, well-defined set of axes (size, intent, interaction state), and they actively hurt when you treat them as a dumping ground for every conceivable permutation.
What a variant actually is
A variant set is one master component containing multiple child components, differentiated by named properties. Instead of naming layers with slash-separated conventions, you define explicit properties like Size=Large, Intent=Primary, State=Hover. Anyone placing an instance picks values from dropdowns in the right-hand properties panel — no detached instances, no layer surgery.
Two things follow from this. First, updates happen in one place: change the corner radius on the master and every instance in every file using the library reflects it. Second, the property names become a shared vocabulary between design and engineering, which matters more than it sounds.
Variants plus auto-layout: responsive states for free
Variants compose well with auto-layout, Figma's constraint system that makes frames resize and reflow based on their content. A button variant built with auto-layout will grow when the label text changes from "Save" to "Save and continue" — in every state, without touching padding manually. This is the difference between a component that survives real content and one that only works in the mock it was drawn for.
The caution: deeply nested auto-layout inside variants can produce surprising shifts during iteration, because a padding change at one level cascades through hugging and filling behaviors at others. Keep nesting shallow and test each variant with its longest realistic content before publishing.
A worked example: a button with two axes
Here's a concrete setup you can reproduce in any Figma file:
- Draw a button with auto-layout (horizontal padding 16, vertical 8, corner radius 6). Select it and choose Create component (Ctrl/Cmd+Alt+K).
- With the component selected, click Add variant in the right-hand panel. Figma wraps it in a variant set with a dashed purple border.
- Duplicate until you have four variants. In the Variants panel, define two properties:
Intent(Primary, Secondary) andState(Default, Hover). - Style each: Primary/Default gets a filled brand background, Secondary/Default an outline, and the Hover states a darker fill or shadow.
- Publish the file as a team library (requires edit access; from the assets panel, choose the publish icon).
In a consuming file, enable the library, drag in the button, and switch Intent and State from the instance's properties panel. To verify the structure survives the trip to code, use Figma's Dev Mode or export the file JSON via the REST API: the instance's componentProperties should list Intent and State with their current values. That mapping is what lets a developer translate Intent=Primary directly into a CSS custom property or a styled-component prop without guessing from layer names.
The trade-off: variant explosion is real
Variants multiply fast. Three sizes × three intents × four states is 36 variants in one master component. Beyond rendering overhead in large files, the real cost is cognitive: designers scrolling a 36-cell grid to find the state they need to edit, and reviewers unable to tell which permutations are actually used. A practical ceiling is two or three axes with a handful of values each. If a permutation is rare — say, a destructive button that only ever appears large — consider splitting it into its own component rather than adding an axis value that exists for one cell.
There's also a library hygiene issue: variant property names must match across files when you sync or migrate libraries. Renaming Intent to Variant in the source library can break instance overrides downstream, and Figma won't always warn you loudly. Treat property names like a public API — version changes deliberately.
Where to start
Pick your most-duplicated component — usually a button or input — and count its copies. If there are more than four, convert them into one variant set with explicit properties, publish it, and delete the old copies. Then check one consuming file: place an instance, switch every property value, and confirm nothing detaches or breaks. That fifteen-minute exercise will tell you more about whether variants fit your system than any amount of theory.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.