figma guide
Designing product variant selectors and swatches UI in Figma: color, size, and handoff
Design color swatches, size pickers, dropdown variant selectors, and out-of-stock states in Figma with component variants and Dev Mode specs for ecommerce PDP teams.
- Published
- Updated
- Jul 01, 2026
- Read time
- 6 min
- Level
- Beginner
Quick answer
Variant selectors live in the PDP buy box and must show the current selection, available options, and out-of-stock states without hiding the add-to-cart CTA. Use color swatches for visual attributes (hex fill + optional texture), pill or grid buttons for size and material, and dropdowns only when you have 8+ options or long labels. Always pair size with a size guide link, show price changes inline when variants affect cost, and update the gallery on selection. Start from the Figma guides hub and templates pillar.
Who this is for
- Product designers building buy boxes for apparel, beauty, furniture, and configurable SKUs.
- Design system teams standardizing swatch, pill, and dropdown variant patterns across PDP and quick view.
- Engineers implementing variant matrix logic, inventory per SKU, and URL deep links.
Selector types map
| Attribute type | Best control | Avoid when |
|---|---|---|
| Color | Circular or square swatch | More than ~12 colors without grouping |
| Size | Pill grid (XS–XXL) | Numeric dimensions with units—use dropdown |
| Material / finish | Text pills or small swatches | Single option only |
| Capacity / storage | Horizontal pill row | Labels exceed ~12 characters |
| Style / bundle tier | Radio cards with price delta | Simple yes/no—use toggle |
| 8+ options | Dropdown | Color—you lose scanability |
Verdict: design ColorSwatch, SizePill, and VariantDropdown first—they cover most DTC PDPs; combine in a single VariantSelectorGroup with consistent label + error spacing.
Buy box placement
| Block | Order (desktop) | Mobile notes |
|---|---|---|
| Title + rating | Top | Same |
| Price | Below title | Updates on variant change |
| Color swatches | First selector | Full width, wrap |
| Size pills | Second | 4–5 per row max |
| Secondary options | Dropdowns | Full width |
| Quantity | Before CTA | Stepper or dropdown |
| Add to cart | Primary CTA | Sticky bar optional |
| Size guide link | Adjacent to size label | Opens modal |
Place selectors above BNPL callouts and below hero price—never bury swatches below the fold on mobile.
ColorSwatch component
| State | Visual | Interaction |
|---|---|---|
| Default | 32–40px circle/square, 2px border | Hover ring |
| Selected | Ring + check icon or thicker border | aria-checked=true |
| Unavailable | Diagonal strike or 40% opacity | Not focusable; show tooltip “Out of stock” |
| Low stock | Optional dot badge | Tooltip “Only 2 left” |
| Multi-color | Split fill or thumbnail | For patterned fabrics |
ColorSwatch
├── Variant: shape=circle | square
├── Variant: size=sm | md | lg
├── Variant: state=default | selected | unavailable | lowStock
├── Property: colorHex=#000000
├── Property: colorLabel=Midnight Navy
└── Layers:
├── SwatchFill
├── SelectedRing
├── UnavailableStrike
└── Tooltip (optional)
Accessibility: each swatch needs a visible text label in the “Color: Midnight Navy” line above the row—not color alone. Use badges for “New color” sparingly.
SizePill component
| Element | Spec | Notes |
|---|---|---|
| Label row | ”Size” + “Size guide” link | Link opens modal or drawer |
| Pill grid | Min 44px touch target | Auto Layout horizontal wrap |
| Selected | Filled background | High contrast |
| Unavailable | Strike-through text | aria-disabled |
| Error | ”Select a size” below grid | After failed add-to-cart |
SizePillGroup
├── Variant: layout=grid | scroll
├── Property: selectedSize=M
└── Layers:
├── LabelRow
│ ├── SizeLabel
│ └── SizeGuideLink
├── PillRow (repeat SizePill)
└── InlineError
Link to size guide modal with measurement table—not a generic FAQ page.
VariantDropdown (long lists)
Use for width × length, phone model, or region-specific SKUs:
| Part | Spec |
|---|---|
| Trigger | Shows current selection + chevron |
| Menu | Max height with scroll; group headers |
| Option row | Label + optional price delta (+$20) |
| Unavailable | Grayed + “(Out of stock)” suffix |
| Search | Optional inside menu for 15+ items |
Reuse dropdown patterns—do not invent a new menu style for variants only.
Price and inventory feedback
| Event | UI response |
|---|---|
| Variant price change | Animate price swap; show compare-at if on sale |
| All variants OOS | Disable add-to-cart; show notify me |
| Low stock on selected SKU | Inline text below pills: “Only 3 left” |
| Invalid combination | Auto-select nearest available or clear dependent dropdown |
| Loading | Skeleton on price + disabled CTA |
Align pricing tokens with variant-specific sale badges on PLP cards when one color is discounted.
Gallery sync
When user picks a color, swap hero image to that variant’s primary shot:
| Pattern | Handoff note |
|---|---|
| Image index map | colorSlug → imageIds[] |
| Thumbnail strip | Filter to variant images only |
| Video | Hide or swap per variant |
| 360° view | Variant-specific asset URL |
Document in Dev Mode beside gallery component—engineers need the mapping table, not just static frames.
Quick view and PLP constraints
| Surface | Variant UI |
|---|---|
| Quick view modal | Color + size only; defer exotic options to full PDP |
| PLP card | Show 3–5 color dots max + “+4” overflow |
| Compare | Fixed variant per column—selector in header |
| Cart line item | Compact dropdown to change size/color |
Never show full pill grids on PLP cards—use swatch dots with tooltip.
Handoff checklist
| Item | Dev Mode annotation |
|---|---|
| Variant matrix | Which combinations are valid |
| Default selection | First in-stock SKU on load |
| URL param | ?color=navy&size=M deep link |
| OOS behavior | Disable vs hide vs strike |
| Price API field | Per-SKU price object |
| Gallery map | Variant → image array |
| Analytics | variant_select, size_guide_open |
| Error copy | Empty selection vs invalid combo |
Use Dev Mode checklist and interactive components for selected/hover/disabled swatch states.
Common mistakes
| Mistake | Why it hurts | Fix |
|---|---|---|
| Swatches without text label | Fails WCAG; confuses similar colors | ”Color: {name}” line always visible |
| Unavailable swatches still clickable | Frustrating dead clicks | aria-disabled + tooltip |
| Size pills too small on mobile | Mis-taps | 44px min height |
| Dropdown for 4 colors | Hides options | Use swatches |
| No size guide on apparel | Returns spike | Link beside size label |
| Price doesn’t update | Trust break | Bind price to selected SKU |
| Gallery static on color change | Wrong product shown | Image map in spec |
| Mixing pill and swatch styles per attribute | Visual noise | One control type per attribute class |
Recommended workflow
- Audit variant attributes with merchandising—color, size, material, capacity.
- Build
ColorSwatchandSizePillwith selected/unavailable/low-stock variants. - Compose
VariantSelectorGroupinside PDP buy box. - Wire price + gallery behavior notes and default SKU rules.
- Add quick view + PLP swatch dot variants at smaller sizes.
- Document matrix, URL params, and analytics in Dev Mode.
FAQ
One dropdown for “Color / Size” combined?
Avoid—split attributes so users can change size without re-opening color.
Show SKU ID to shoppers?
No—use human labels; SKU in Dev Mode only unless B2B catalog.
Pre-select first color on load?
Yes if in stock; otherwise first available variant.
Bundle variant pickers?
Per-tile dropdowns in FBT rows—reuse VariantDropdown at compact size.
Subscription frequency as a variant?
Use segmented control—see subscription UI guide.
Next steps
- Design product detail pages in Figma — buy box layout
- Design size guides and size selector UI in Figma — modal and measurement table
- Design product image gallery and zoom UI in Figma — variant image sync
- Design sticky add-to-cart bar UI in Figma — mobile CTA with variant summary
- Design back-in-stock and notify me UI in Figma — when all variants are OOS
§ Keep reading