figma guide
Designing product listing and grid UI in Figma: filters, sort, and handoff
Design PLP grids, list views, filters, sort controls, and skeleton loading in Figma with reusable components, responsive breakpoints, and Dev Mode specs for ecommerce.
- Published
- Updated
- Jun 18, 2026
- Read time
- 7 min
- Level
- Beginner
Quick answer
A product listing page (PLP) is a layout system: filter rail + toolbar (result count, sort, view toggle) + responsive product grid built from one ProductCard component—not a page full of one-off frames. Build ProductCard with image, title, price, optional rating, and badges; wrap cards in a grid with 2/3/4 columns by breakpoint. Pair filters with search UI, sliders, and chips for active filter pills. Start from the Figma guides hub.
Who this is for
- Product designers shipping category pages, search results, and collection landing pages.
- Design system teams aligning card density, filter patterns, and grid breakpoints across storefronts.
- Engineers implementing URL-driven filters, infinite scroll vs pagination, and responsive column counts.
PLP anatomy
| Zone | Purpose | Key components |
|---|---|---|
| Header / breadcrumb | Context and hierarchy | Breadcrumb, H1, optional hero |
| Filter rail | Narrow results | FilterGroup, checkboxes, sliders |
| Toolbar | Control view | Result count, SortDropdown, grid/list toggle |
| Product grid | Browse inventory | ProductGrid + ProductCard instances |
| Empty / error | No matches | Empty state |
| Pagination / load more | Navigate results | Pagination or infinite scroll note |
Verdict: design desktop filter sidebar and mobile filter sheet as two layouts of the same filter model, not two unrelated UIs that diverge after launch.
ProductCard component
Reuse the card patterns guide—PLP cards are a specialized variant, not a new shape language.
| Part | Purpose | Spec tip |
|---|---|---|
| Image | Product thumbnail | 1:1 or 4:5 aspect; export @2x |
| Badges | Sale, New, Low stock | Top-left overlay; max 2 visible |
| Title | Product name | 2-line clamp |
| Price | Current + compare-at | PriceDisplay sm/md |
| Rating | Aggregate score | RatingDisplay compact |
| Swatches (optional) | Color variants | Row of 4–6 dots + “+3” |
| Quick action (optional) | Add to cart, wishlist | Icon button; document hover vs always-visible |
ProductCard
├── Variant: layout=grid | list
├── Variant: density=compact | comfortable
├── Variant: state=default | hover | focus | disabled | skeleton
├── Property: showRating (boolean)
├── Property: showSwatches (boolean)
└── Layers:
├── Media (image + badges)
├── Content (title, price, rating)
└── Actions (optional)
Use vertical auto layout for grid cards; switch to horizontal auto layout for list view with a fixed image column width.
Grid vs list view
| View | Columns (desktop) | Best for | Card layout |
|---|---|---|---|
| Grid | 3–4 | Fashion, home, visual catalogs | Vertical stack |
| Grid compact | 4–5 | Grocery, parts, high SKU count | Smaller image, shorter title |
| List | 1 | Spec-heavy B2B, comparison shopping | Horizontal row |
| Masonry | Variable | Lookbooks (rare in design systems) | Document as exception |
| Breakpoint | Grid columns | Gutter | Notes |
|---|---|---|---|
| Mobile (<640px) | 2 | 12–16px | Filter opens in full-screen sheet |
| Tablet (640–1024px) | 2–3 | 16–20px | Collapsible filter drawer |
| Desktop (1024px+) | 3–4 | 20–24px | Persistent filter sidebar |
Document column math in Dev Mode: cardWidth = (container - (columns - 1) * gutter) / columns. Pair with responsive frames and layout grids.
Filters and sort
Filter groups
| Filter type | Control | Example |
|---|---|---|
| Category | Tree or checkboxes | Apparel → Shirts |
| Price range | Dual-handle slider | $25–$100 |
| Brand | Checkbox list + search | Nike, Adidas… |
| Size / color | Chips or swatches | S, M, L |
| Rating | Star threshold | 4★ & up |
| Availability | Toggle | In stock only |
FilterPanel
├── Variant: placement=sidebar | sheet | horizontal-bar
├── Layer: ActiveFilters (chip row)
├── Layer: FilterGroups (accordion)
└── Layer: Footer (Clear all, Apply on mobile)
On mobile, Apply commits filter changes; on desktop, live update is common—note the expected behavior so engineers do not guess.
Sort dropdown
Use the dropdown menu component with a single-select pattern:
| Option | Label example |
|---|---|
| Featured | Featured |
| Price low → high | Price: Low to High |
| Price high → low | Price: High to Low |
| Newest | Newest |
| Rating | Top Rated |
| Best selling | Best Selling |
Show the active sort in the toolbar label (Sort: Price: Low to High). Include a result count (128 products) beside sort—reduces disorientation when filters change.
Active filter chips
When filters apply, show removable chips above the grid:
[Price: $25–$100 ×] [Brand: Nike ×] [Clear all]
Chip remove updates URL params in production; prototype with interactive components swapping visibility on the chip row.
Loading, empty, and error states
| State | Grid behavior | Supporting UI |
|---|---|---|
| Initial load | Skeleton cards | 8–12 placeholders |
| Filter refresh | Dim grid + skeleton overlay | Keep filter panel interactive |
| Empty results | Hide grid | Empty illustration + “Clear filters” CTA |
| Partial error | Show cached results + inline alert | Retry action |
| End of catalog | Stop infinite scroll | ”You’ve seen it all” message |
Never show a blank white grid during loading—skeleton cards preserve layout and reduce cumulative layout shift.
Toolbar and view toggle
PLPToolbar
├── Layer: ResultCount
├── Layer: Spacer
├── Layer: SortDropdown
└── Layer: ViewToggle (grid | list icons)
| Control | Accessibility | Handoff note |
|---|---|---|
| View toggle | aria-pressed on active icon | Persist preference in localStorage |
| Sort | Labelled combobox or menu | URL param ?sort=price_asc |
| Filter button (mobile) | Opens sheet with focus trap | Badge count of active filters |
Link mobile filter entry to modal/sheet patterns—full-screen sheet with sticky Apply/Clear footer.
Promotional rows and merchandising
Category pages often mix editorial content with the grid:
| Module | Placement | Design note |
|---|---|---|
| Hero banner | Above grid | Full-width; do not break filter model |
| Promo tile | In-grid slot (position 5) | Same row height as cards or span 2 columns |
| Collection carousel | Above or below grid | Horizontal scroll; separate from PLP grid |
| SEO copy block | Below pagination | Collapsible on mobile |
Document grid slot overrides in Dev Mode: “Tile at index 4 spans 2 columns on desktop only.”
Handoff checklist
| Item | Dev Mode annotation |
|---|---|
| Column count per breakpoint | 2 / 3 / 4 with pixel gutters |
| Card min/max width | Prevents broken grids on ultrawide |
| Image aspect ratio | 1:1 vs 4:5—do not mix without variant |
| Filter apply behavior | Live vs Apply button |
| Sort default | Featured unless URL overrides |
| Pagination vs infinite scroll | One pattern per page type |
| Empty state CTA | Links to parent category or clear filters |
| Skeleton count | Minimum rows to fill viewport |
Run through Dev Mode checklist before handoff. Link PLP cards to PDP frames via prototype connections for stakeholder walkthroughs.
Common mistakes
| Mistake | Why it hurts | Fix |
|---|---|---|
| Unique card per product | Unmaintainable catalog | One ProductCard with properties |
| Filters that reset scroll | Frustrating browse | Preserve scroll or show count change |
| Missing list view | B2B buyers need specs | Add layout=list variant early |
| 5-column desktop grid | Cards too narrow for price + rating | Cap at 4; use compact density instead |
| Sort without visible label | Users lose context | Show active sort in toolbar |
| No skeleton loading | Layout jump on slow networks | 8+ skeleton cards matching grid |
Recommended workflow
- Define
ProductCardwith grid and list variants; bind price, rating, and badge components. - Build filter model as reusable groups; mirror sidebar (desktop) and sheet (mobile).
- Lay out responsive grid with constraints and auto layout rows.
- Add toolbar with sort, count, and view toggle.
- Design empty, skeleton, and error states before stakeholder review.
- Prototype filter chip removal and mobile sheet open/close.
- Annotate breakpoint columns and filter behavior in Dev Mode.
FAQ
How many products should I show per page?
24–48 is a common default for grid PLPs; B2B list views often use 10–20 with pagination. Match skeleton count to the first page load, not the full catalog.
Should filters live in a sidebar or horizontal bar?
Sidebar for 5+ filter dimensions (fashion, marketplace). Horizontal chip bar for 2–3 quick filters (grocery, small catalogs). Design both if mobile uses a sheet.
Grid or list as default?
Grid for visual categories; list for spec-heavy SKUs. Default the view toggle to grid but persist user choice.
How do PLP cards link to PDP?
One click target on the card (image + title); secondary actions (wishlist, quick add) stop propagation—document hit areas in Dev Mode. See product detail page patterns for the destination layout.
Next steps
- Design product detail pages in Figma — gallery, variants, add to cart
- Design search UI in Figma — query + filter overlap
- Design cards in Figma — shared card anatomy
- Figma templates hub — starter ecommerce layouts
§ Keep reading