figma guide
Designing compare products UI in Figma: tables, sticky headers, and handoff
Design product comparison tables, sticky attribute columns, add-to-compare chips, and mobile compare drawers in Figma with variants and Dev Mode specs for ecommerce.
- Published
- Updated
- Jun 22, 2026
- Read time
- 7 min
- Level
- Beginner
Quick answer
Compare UI connects PLP selection, a dedicated comparison page, and optional mini compare bar—use one CompareProductColumn per product and CompareAttributeRow for spec alignment across columns. Build CompareCheckbox on product cards, a sticky CompareBar (“Compare 2 of 4”), and a CompareTable with category-grouped rows (Overview, Dimensions, Warranty). Cap at 3–4 products on desktop and 2 on mobile; model empty slots, remove column, and highlight-differences toggle. Pair with PDP, tables, and badges. Start from the Figma guides hub.
Who this is for
- Product designers shipping electronics, appliances, B2B catalog, and spec-heavy retail where side-by-side decisions drive conversion.
- Design system teams aligning compare patterns across PLP, search results, and PDP.
- Engineers implementing compare session storage, attribute normalization, and responsive column collapse.
Compare surfaces
| Surface | Goal | Key components |
|---|---|---|
| PLP / search card | Add to compare | CompareCheckbox, compare count badge |
| PDP | Add from detail page | CompareButton text + checkbox variant |
| Sticky compare bar | Navigate while browsing | CompareBar with thumbnails |
| Compare page (desktop) | Full attribute matrix | CompareTable, CompareProductColumn |
| Compare drawer (mobile) | Swipeable columns | CompareDrawer, horizontal scroll |
| Empty compare | No products selected | Empty state + PLP CTA |
Verdict: attribute rows must be data-driven in spec—design row templates (label column + N product cells), not one-off frames per product pair that break when a third item is added.
CompareProductColumn header
| Part | Purpose | Spec tip |
|---|---|---|
| Remove (×) | Drop from compare | Top-right icon button |
| Thumbnail | Product image | 120px; link to PDP |
| Title | Product name | 2-line clamp |
| Price | Current price | Sale + was price if applicable |
| Rating | Social proof | Compact stars + count |
| Primary CTA | Add to cart | Full width under header |
| Secondary | View details | Text link |
CompareProductColumn
├── Variant: slot=filled | empty
├── Variant: breakpoint=desktop | mobile
├── Property: productId (string)
└── Layers:
├── RemoveButton
├── ProductHeader (thumb + title + price + rating)
├── AddToCartButton
└── AttributeCells (mirrored row IDs)
Empty slot shows dashed border card: “Add another product” with search or browse CTA.
CompareAttributeRow structure
| Row type | Example | Cell content |
|---|---|---|
| Text | Color | ”Midnight Black” |
| Boolean | Waterproof | ✓ / ✗ icons with a11y labels |
| Numeric + unit | Weight | ”1.2 kg” |
| List | Included accessories | Bulleted mini list |
| Link | Manual PDF | ”Download” link |
| Unavailable | — | ”—” em dash, muted |
CompareAttributeRow
├── Property: attributeId (string)
├── Property: category (overview | specs | shipping)
├── Property: highlightDiff (boolean)
└── Layers:
├── RowLabel (sticky left column desktop)
└── Cell[] (one per CompareProductColumn)
Group rows under section headers: “General,” “Technical specifications,” “Shipping & returns”—use accordion sections on mobile to reduce scroll.
Sticky compare bar
Shown when ≥1 product in compare tray and user navigates away from compare page.
| Element | Spec |
|---|---|
| Thumbnails | 40px, max 4, +N overflow badge |
| Label | ”Compare (3)“ |
| Clear all | Text button |
| CTA | ”Compare now” → compare page |
| Position | Fixed bottom mobile; top below nav desktop optional |
CompareBar
├── Variant: visible | hidden
├── Property: count (0-4)
├── Property: productThumbs (array)
└── z-index: above PLP filters, below [modals](/designing-modals-and-dialogs-in-figma-overlays-and-handoff/)
When count hits max (4), toast: “Remove an item to compare more products.”
PLP and PDP entry points
| Entry | Control | Max behavior |
|---|---|---|
| PLP grid card | Checkbox “Compare” | Disabled at max with tooltip |
| PLP list row | Icon toggle | Same |
| PDP below title | ”Add to compare” link | Toggle on/off state |
| Wishlist row | Optional compare icon | Don’t merge wishlist + compare state |
CompareCheckbox states: unchecked, checked, disabled-max, loading.
On product listing cards, place compare control away from wishlist heart to prevent mis-taps—bottom-left vs top-right corners.
Highlight differences toggle
| State | Row styling |
|---|---|
| Off | All rows equal weight |
| On | Rows where all values identical → collapsed or hidden |
| On | Rows with mismatch → subtle background highlight on differing cells |
Toggle sits top-right of compare page: switch “Highlight differences only.”
Engineering note: normalization matters—“Yes” vs “yes” vs ✓ should not false-highlight; spec string equality rules in Dev Mode.
Desktop compare table layout
ComparePageDesktop
├── PageTitle: "Compare products"
├── Toolbar: HighlightDiffToggle | Print | Share link
├── CompareTable
│ ├── StickyHeaderRow (product columns stick on vertical scroll)
│ ├── Section: Overview
│ │ └── CompareAttributeRow × n
│ ├── Section: Specifications
│ │ └── CompareAttributeRow × n
│ └── Section: Shipping
│ └── CompareAttributeRow × n
├── EmptyColumnSlot (if < max products)
└── BackToPLP link
Left label column width: 200–240px fixed; product columns share remaining width equally (3-col) or horizontal scroll (4-col).
Use layout grids for row height consistency—attribute cells in the same row must equal height per auto layout “fill container.”
Mobile compare patterns
| Pattern | When to use |
|---|---|
| Horizontal scroll columns | 2 products visible; peek third |
| Product picker tabs | Switch active pair in 3+ compare set |
| Full-screen drawer | From sticky bar “Compare now” |
| Stacked cards | Low-spec categories only—avoid for 20+ rows |
Sticky CompareProductColumn header on horizontal scroll—product image and ATC stay visible while specs scroll.
Collapse long text attributes with “Show more” link inside cell.
Add to cart from compare
| Scenario | UX |
|---|---|
| Single winner obvious | One primary ATC per column |
| Multi-buy bundle | Not compare’s job—link to PDP |
| Out of stock column | Disabled ATC + badge “Out of stock” |
| Variant required | ATC opens modal variant picker |
After add, optional toast with link to cart—do not navigate away from compare unless user chooses.
Dev Mode handoff checklist
| Spec | Document |
|---|---|
| Max compare count | 4 desktop, 2 recommended mobile |
| Session persistence | localStorage vs account-backed |
| Attribute schema | JSON example with attributeId, type, category |
| Icon set | check, x, dash for boolean cells |
| Empty cell token | ”—” character + muted color variable |
| Analytics | compare_add, compare_remove, compare_view, compare_atc |
| SEO | Compare page noindex if session-only (note for PM) |
Cross-link table component patterns for sortable spec sources on admin side.
Common mistakes
| Mistake | Why it hurts | Fix |
|---|---|---|
| Static 2-product mock only | Breaks when adding third | Column + row component model |
| Misaligned attribute rows | Unreadable comparison | Shared row component, equal heights |
| Compare on every SKU variant | Tray explosion | Compare at parent product level |
| No max limit | Overwhelming table | Cap at 4 with disabled add |
| Identical columns not collapsible | Noise | Highlight differences toggle |
| Missing empty compare state | Dead end | CTA back to PLP categories |
Recommended workflow
- Define compare-eligible categories with PM (electronics yes, fashion often no).
- Build
CompareProductColumnheader with remove, price, rating, ATC. - Create
CompareAttributeRowwith text, boolean, and unavailable variants. - Add
CompareCheckboxto PLP card component set. - Design
CompareBarsticky tray and max-reached toast. - Lay out desktop
CompareTablewith 3 filled + 1 empty column. - Design mobile horizontal scroll with sticky mini headers.
- Prototype add/remove, highlight diff toggle, and out-of-stock column.
FAQ
Compare vs wishlist?
Different jobs—wishlist is save for later; compare is decision support. Allow both on PDP; separate icons and state.
Variant-level compare (size/color)?
Default to parent product in tray; if user compared from specific variant PDP, pass variant ID to ATC only—not separate columns per size.
Print compare page?
Optional toolbar icon generates print stylesheet—design simplified B&W table frame without sticky chrome.
Share compare link?
Deep link with product IDs query param—design shared view read-only without edit controls; note loading skeleton state.
Faceted search filters with compare?
Compare tray persists across filter changes—products removed from results stay in tray until user removes them; show bar badge if item unavailable.
Next steps
- Design product listing and grid UI in Figma — PLP cards and compare entry
- Design product detail pages in Figma — specs source for attribute rows
- Figma tables and data UI — row alignment patterns
- Design rating and review UI in Figma — header social proof
- Design empty states in Figma — zero products in compare
§ Keep reading