Ecommerce UI with Tailwind CSS
Patterns for product display, cart, checkout, orders, and store navigation.
1. Product Display Patterns
Card Variants
| Variant | Key Classes | Use Case |
|---|
| Simple grid card | aspect-[3/4] w-full object-cover + text below image | Category pages, minimal listings |
| Card with details | rounded-lg border bg-white shadow-sm + price, rating, badge | Product listings, search results |
| Horizontal card | flex flex-row gap-4 + image left, details right | Cart items, wishlists, comparisons |
| Quick view overlay | group relative + opacity-0 group-hover:opacity-100 overlay CTA | Browse-and-add flows |
| Featured card | col-span-2 row-span-2 + larger image | Homepage hero products |
Image Handling
| Concern | Pattern | Classes |
|---|
| Aspect ratio | Fixed ratio container | aspect-square, aspect-[3/4], aspect-[4/3] |
| Fill behavior | Cover without distortion | object-cover w-full h-full |
| Responsive sizing | Fluid width, fixed aspect | w-full on container, aspect ratio on <img> |
| Placeholder | Background color fallback | bg-gray-100 on container |
| Hover zoom | Scale on group hover | transition-transform duration-300 group-hover:scale-105 |
| Lazy loading | Native attribute | loading="lazy" on <img> |
Price Display
| Scenario | Pattern |
|---|
| Regular price | <span class="text-lg font-semibold text-gray-900">$49.99</span> |
| Sale price | Original: line-through text-gray-500 text-sm / Sale: text-lg font-semibold text-red-600 |
| Price range | From $29.99 with text-sm text-gray-500 prefix |
| Currency symbol | Keep symbol adjacent, no wrapping: whitespace-nowrap |
Rating Display
| Element | Classes |
|---|
| Star icon (filled) | size-4 text-yellow-400 fill-current |
| Star icon (empty) | size-4 text-gray-300 fill-current |
| Half star | Clip filled star at 50% with overflow-hidden w-2 wrapper |
| Review count | text-sm text-gray-500 ml-1 next to stars |
| Container | flex items-center gap-0.5 |
2. Product List Layouts
Responsive Grid
html
1<div class="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4">
2 <!-- Product cards -->
3</div>
Layout Patterns
| Layout | Classes | When to Use |
|---|
| Grid (default) | grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6 | Category pages, search results |
| Two-column wide | grid grid-cols-1 md:grid-cols-2 gap-8 | Featured products, comparisons |
| List view | flex flex-col divide-y with horizontal cards | Detail-heavy browsing |
| Masonry-style | columns-2 lg:columns-3 gap-4 | Visual-heavy catalogs |
Loading and Pagination
| Pattern | Implementation |
|---|
| Skeleton card | animate-pulse with bg-gray-200 rounded blocks matching card layout |
| Skeleton image | aspect-[3/4] bg-gray-200 rounded-lg animate-pulse |
| Skeleton text | h-4 bg-gray-200 rounded w-3/4 animate-pulse |
| Load more button | w-full py-3 border rounded-lg text-center below grid |
| Pagination | flex items-center gap-2 with numbered buttons, active: bg-indigo-600 text-white |
| Infinite scroll | Intersection observer on sentinel div at grid end |
| Empty state | text-center py-16 with icon, heading, and CTA |
3. Category and Filtering
Sidebar Filter Panel (Desktop)
| Element | Classes |
|---|
| Panel container | w-64 shrink-0 hidden lg:block |
| Filter group | border-b py-4 with heading + options |
| Group heading | font-medium text-sm text-gray-900 mb-3 |
| Checkbox + label | flex items-center gap-2 text-sm text-gray-600 |
| Color swatch | size-6 rounded-full border-2 + ring-2 ring-offset-2 ring-indigo-500 when active |
| Price range | Two input[type=number] with w-20 in a flex gap-2 items-center row |
| Apply button | w-full mt-3 py-2 bg-indigo-600 text-white rounded-lg text-sm |
Mobile Filter (Slide-out Dialog)
| Element | Classes |
|---|
| Trigger button | lg:hidden flex items-center gap-2 border rounded-lg px-4 py-2 |
| Backdrop | fixed inset-0 bg-black/25 z-40 |
| Panel | fixed inset-y-0 right-0 w-full max-w-sm bg-white z-50 overflow-y-auto |
| Header | flex items-center justify-between px-4 py-3 border-b |
| Footer | sticky bottom-0 bg-white border-t px-4 py-3 with Apply/Clear buttons |
Active Filters and Sorting
| Element | Classes |
|---|
| Filter chip | inline-flex items-center gap-1 rounded-full bg-gray-100 px-3 py-1 text-sm |
| Remove button | size-4 text-gray-400 hover:text-gray-600 (X icon inside chip) |
| Clear all link | text-sm text-indigo-600 hover:text-indigo-800 |
| Sort dropdown | select or custom dropdown, text-sm border rounded-lg px-3 py-2 |
| Result count | text-sm text-gray-500 (e.g., "128 products") |
| Filter count badge | size-5 rounded-full bg-indigo-600 text-white text-xs flex items-center justify-center |
4. Shopping Cart
Cart Item Row
html
1<div class="flex gap-4 py-4 border-b">
2 <img class="size-20 rounded-lg object-cover shrink-0" src="..." alt="..." />
3 <div class="flex flex-1 flex-col justify-between">
4 <div class="flex justify-between">
5 <div>
6 <h3 class="text-sm font-medium text-gray-900">Product Name</h3>
7 <p class="mt-1 text-sm text-gray-500">Color / Size</p>
8 </div>
9 <p class="text-sm font-medium text-gray-900">$49.99</p>
10 </div>
11 <div class="flex items-center justify-between">
12 <!-- Quantity selector -->
13 <div class="flex items-center rounded-lg border">
14 <button class="px-3 py-1 text-gray-600">-</button>
15 <span class="px-3 py-1 border-x text-sm">1</span>
16 <button class="px-3 py-1 text-gray-600">+</button>
17 </div>
18 <button class="text-sm text-red-600 hover:text-red-800">Remove</button>
19 </div>
20 </div>
21</div>
Cart Sections
| Section | Classes | Content |
|---|
| Cart list | divide-y | Cart item rows |
| Summary panel | rounded-lg bg-gray-50 p-6 lg:w-80 lg:shrink-0 | Subtotal, shipping, tax, total |
| Summary row | flex justify-between text-sm text-gray-600 py-2 | Label + amount |
| Total row | flex justify-between text-base font-semibold text-gray-900 border-t pt-4 mt-4 | Total label + amount |
| Checkout CTA | w-full mt-6 py-3 bg-indigo-600 text-white rounded-lg font-medium | "Proceed to Checkout" |
| Continue shopping | text-sm text-indigo-600 hover:text-indigo-800 mt-4 text-center block | Link back |
Cart States
| State | Pattern |
|---|
| Empty cart | text-center py-16 with cart icon, "Your cart is empty" heading, shop CTA |
| Mini cart / drawer | fixed inset-y-0 right-0 w-full max-w-md bg-white shadow-xl z-50 |
| Cart badge | absolute -top-2 -right-2 size-5 rounded-full bg-indigo-600 text-white text-xs flex items-center justify-center |
| Updating state | opacity-50 pointer-events-none on item row during async update |
5. Checkout Flow
Progress Indicator
| Step State | Classes |
|---|
| Completed | size-8 rounded-full bg-indigo-600 text-white with check icon |
| Current | size-8 rounded-full border-2 border-indigo-600 text-indigo-600 |
| Upcoming | size-8 rounded-full border-2 border-gray-300 text-gray-400 |
| Connector (done) | h-0.5 w-full bg-indigo-600 between circles |
| Connector (pending) | h-0.5 w-full bg-gray-300 between circles |
| Container | flex items-center justify-between max-w-lg mx-auto mb-8 |
Form Layout
| Section | Structure |
|---|
| Two-column layout | grid grid-cols-1 lg:grid-cols-5 gap-8 (3 cols form + 2 cols summary) |
| Field group | space-y-4 container |
| Two-field row | grid grid-cols-2 gap-4 (first/last name, city/zip) |
| Full-width field | col-span-2 or standalone |
| Label | block text-sm font-medium text-gray-700 mb-1 |
| Input | w-full rounded-lg border border-gray-300 px-3 py-2 text-sm focus:border-indigo-500 focus:ring-1 focus:ring-indigo-500 |
| Error input | border-red-500 focus:border-red-500 focus:ring-red-500 |
| Error message | text-sm text-red-600 mt-1 |
Payment Fields
| Element | Pattern |
|---|
| Card number | Full-width input with card icon right-aligned |
| Expiry + CVC | grid grid-cols-2 gap-4 side by side |
| Card group | rounded-lg border divide-y wrapping all card fields as one visual unit |
| Saved cards | Radio group: flex items-center gap-3 p-4 border rounded-lg per card |
| Security note | flex items-center gap-2 text-sm text-gray-500 with lock icon |
Checkout Patterns
| Pattern | Implementation |
|---|
| Guest vs account | Toggle or tabs at top: flex rounded-lg border with two options |
| Order review | Summary card: item thumbnails, quantities, line totals in bg-gray-50 rounded-lg p-6 |
| Place order CTA | w-full py-3 bg-indigo-600 text-white rounded-lg font-medium text-lg |
| Terms checkbox | flex items-start gap-2 with checkbox and label text |
| Loading on submit | Button with opacity-75 cursor-not-allowed + spinner icon |
6. Order Management
Order History Table
| Viewport | Pattern |
|---|
| Desktop | Standard <table> with columns: Order #, Date, Status, Total, Actions |
| Mobile | Stacked cards: divide-y with each order as a flex flex-col gap-2 py-4 block |
| Table header | text-left text-sm font-medium text-gray-500 pb-3 border-b |
| Table cell | py-4 text-sm text-gray-900 |
Order Status Badges
| Status | Classes |
|---|
| Pending | bg-yellow-100 text-yellow-800 rounded-full px-2.5 py-0.5 text-xs font-medium |
| Processing | bg-blue-100 text-blue-800 rounded-full px-2.5 py-0.5 text-xs font-medium |
| Shipped | bg-indigo-100 text-indigo-800 rounded-full px-2.5 py-0.5 text-xs font-medium |
| Delivered | bg-green-100 text-green-800 rounded-full px-2.5 py-0.5 text-xs font-medium |
| Cancelled | bg-red-100 text-red-800 rounded-full px-2.5 py-0.5 text-xs font-medium |
| Refunded | bg-gray-100 text-gray-800 rounded-full px-2.5 py-0.5 text-xs font-medium |
Order Detail Page
| Section | Pattern |
|---|
| Status timeline | Vertical: relative pl-8 space-y-6 with absolute left-0 circles and connecting line |
| Timeline dot (done) | size-4 rounded-full bg-indigo-600 |
| Timeline dot (current) | size-4 rounded-full border-2 border-indigo-600 bg-white |
| Timeline line | absolute left-2 top-4 bottom-0 w-0.5 bg-gray-200 |
| Items list | Horizontal cards with image, name, qty, price |
| Totals section | Same pattern as cart summary |
| Shipping address | bg-gray-50 rounded-lg p-4 card |
| Invoice layout | max-w-2xl mx-auto with logo header, address block, items table, totals |
7. Pricing and Promotions
Price Patterns
| Pattern | Implementation |
|---|
| Original + sale | <span class="line-through text-gray-500 text-sm">$99.99</span> <span class="text-lg font-semibold text-red-600">$49.99</span> |
| Save amount | <span class="text-sm text-green-600 font-medium">Save $50.00 (50%)</span> |
| Per-unit price | <span class="text-xs text-gray-500">$2.50/oz</span> below main price |
Discount Badge (on Product Image)
html
1<div class="relative">
2 <img class="aspect-[3/4] w-full rounded-lg object-cover" src="..." alt="..." />
3 <span class="absolute top-2 left-2 rounded-full bg-red-600 px-2.5 py-0.5 text-xs font-semibold text-white">
4 -50%
5 </span>
6</div>
Pricing Tier Cards
| Element | Classes |
|---|
| Card container | rounded-xl border p-6 text-center |
| Featured card | border-indigo-600 ring-2 ring-indigo-600 relative with "Popular" badge |
| Price | text-4xl font-bold text-gray-900 |
| Period | text-sm text-gray-500 (e.g., "/month") |
| Feature list | space-y-3 text-sm text-gray-600 with check icons |
| CTA button | w-full mt-6 py-2.5 rounded-lg font-medium |
Promo and Incentive Sections
| Pattern | Classes |
|---|
| Full-width banner | bg-indigo-600 text-white py-3 text-center text-sm font-medium |
| Dismissable banner | Add flex items-center justify-between px-4 with close button |
| Trust icons row | grid grid-cols-2 md:grid-cols-4 gap-6 py-8 text-center |
| Trust icon item | flex flex-col items-center gap-2 text-sm text-gray-600 with icon above |
| Coupon input | flex with flex-1 rounded-l-lg border px-3 py-2 input + rounded-r-lg bg-gray-900 text-white px-4 py-2 button |
8. Store Navigation
Store Header
| Element | Classes |
|---|
| Header bar | sticky top-0 z-30 bg-white border-b |
| Inner layout | flex items-center justify-between h-16 px-4 max-w-7xl mx-auto |
| Logo | shrink-0 |
| Search bar | flex-1 max-w-lg mx-8 hidden md:block with rounded-full bg-gray-100 px-4 py-2 |
| Icon group | flex items-center gap-4 for account, wishlist, cart icons |
| Cart icon + badge | relative button with absolute -top-1.5 -right-1.5 badge |
Mega Menu
| Element | Classes |
|---|
| Trigger | group on nav item |
| Dropdown | invisible group-hover:visible opacity-0 group-hover:opacity-100 transition-all absolute left-0 w-full bg-white shadow-lg border-t |
| Inner grid | grid grid-cols-4 gap-8 max-w-7xl mx-auto p-8 |
| Column heading | font-medium text-sm text-gray-900 mb-3 |
| Column links | space-y-2 text-sm text-gray-600 |
| Featured image | rounded-lg overflow-hidden in last column |
Category Previews and Breadcrumbs
| Element | Classes |
|---|
| Category card | group relative rounded-xl overflow-hidden |
| Category image | aspect-[4/3] w-full object-cover transition-transform group-hover:scale-105 |
| Category overlay | absolute inset-0 bg-gradient-to-t from-black/60 to-transparent |
| Category label | absolute bottom-4 left-4 text-lg font-semibold text-white |
| Breadcrumb nav | flex items-center gap-2 text-sm text-gray-500 |
| Breadcrumb separator | size-4 text-gray-400 (chevron icon) |
| Breadcrumb current | text-gray-900 font-medium (last item, no link) |
9. Accessibility for Ecommerce
| Element | Requirement | Implementation |
|---|
| Product image | Descriptive alt text | alt="Red leather crossbody bag" not alt="product" |
| Decorative image | Skip for screen readers | alt="" and aria-hidden="true" |
| Sale price | Announce was/now | aria-label="Sale price $49.99, originally $99.99" on container |
| Cart update | Announce change | aria-live="polite" region for "Item added" / "Cart updated" messages |
| Cart count badge | Announce count | aria-label="Cart, 3 items" on cart button |
| Quantity selector | Label buttons | aria-label="Decrease quantity" / aria-label="Increase quantity" |
| Star rating | Text alternative | aria-label="4 out of 5 stars" on rating container |
| Filter change | Announce results | aria-live="polite" on product count ("128 results") |
| Form errors | Link to field | aria-describedby="email-error" on input, matching id on error text |
| Checkout steps | Current step | aria-current="step" on active step indicator |
| Remove from cart | Confirm action | Identify item in label: aria-label="Remove Red Bag from cart" |
| Sort dropdown | Label purpose | aria-label="Sort products by" on select element |
| Color swatch | Name the color | aria-label="Color: Navy Blue" on swatch button |
| Dialog filters | Trap focus | role="dialog" + aria-modal="true" + focus trap on mobile filter panel |
Common Mistakes
| Mistake | Fix |
|---|
| Fixed pixel image heights | Use aspect-* utilities with object-cover for responsive images |
| Cart with no empty state | Always handle zero items with illustration and CTA |
Price without whitespace-nowrap | Currency and amount should not wrap to separate lines |
| Filter panel always visible on mobile | Hide with hidden lg:block, use dialog for mobile |
| No loading state during cart updates | Show opacity-50 pointer-events-none or skeleton on async actions |
| Checkout form in single column | Use grid grid-cols-2 gap-4 for name, city/zip, expiry/CVC pairs |
| Status badges with only color | Add text labels; color alone fails WCAG |
Missing aria-live on cart | Cart count and summary changes must announce to screen readers |
| Mega menu not keyboard-navigable | Ensure focus management and Escape key closes the menu |
| Discount badge over product text | Position badge on image (absolute top-2 left-2), not over card text |
MCP Component Library
The frontend-components MCP server provides ecommerce-related components:
- HyperUI (
hyperui): Product cards, product collections, pricing tables, forms, badges, stats
- DaisyUI (
daisyui): Card, badge, stat, table, modal, rating, countdown class references
- FlyonUI (
flyonui): Card, badge, stat, table CSS components + datatable JS plugin
Ecommerce search: search_components(query: "product", framework: "hyperui") or search_components(query: "pricing") for pricing components across all libraries.