Loading...
Loading...
Build a mobile-first storefront with thumb-friendly navigation, sticky add-to-cart buttons, and touch-optimized components for high mobile conversion
npx skill4agent add finsilabs/awesome-ecommerce-skills responsive-storefront| Platform | Recommended Approach | Why |
|---|---|---|
| Shopify | Use a mobile-first OS2.0 theme (Dawn, Sense, Craft) — all are responsive by default; configure mobile layout in Theme Editor | Dawn scores 90+ on mobile PageSpeed out of the box; the Theme Editor exposes mobile-specific layout controls |
| WooCommerce | Use a mobile-first WooCommerce theme (Astra, Kadence, or Flatsome) — all include responsive breakpoints and mobile cart drawer built in | Astra and Kadence score well on Core Web Vitals; Flatsome has built-in sticky header and mobile menu without plugins |
| BigCommerce | Use Cornerstone theme which is mobile-first by design; configure breakpoints in Theme Editor | Cornerstone is BigCommerce's reference theme and passes Google's mobile usability tests |
| Custom / Headless | Write mobile-first CSS with | Full control over all breakpoints and touch interactions; see patterns below |
/* tokens.css */
:root {
--space-sm: 0.5rem;
--space-md: 1rem;
--space-lg: 1.5rem;
--touch-target: 44px; /* WCAG 2.5.5 minimum tap target */
--content-max-width: 1200px;
}
/* Breakpoints: sm=640px, md=768px, lg=1024px */
/* Write base styles for mobile, add min-width queries for larger screens */.product-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(min(160px, 100%), 1fr));
gap: var(--space-md);
padding: var(--space-md);
}
@media (min-width: 640px) {
.product-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}
@media (min-width: 1024px) {
.product-grid { grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: var(--space-lg); }
}
/* Minimum 44px touch target on product card CTA */
.product-card__cta { min-height: var(--touch-target); display: flex; align-items: center; }export function StickyBuyBar({ product, onAddToCart }) {
const [visible, setVisible] = useState(false);
useEffect(() => {
const primaryBtn = document.getElementById('main-add-to-cart');
if (!primaryBtn) return;
const obs = new IntersectionObserver(([e]) => setVisible(!e.isIntersecting));
obs.observe(primaryBtn);
return () => obs.disconnect();
}, []);
return (
<div className={`sticky-buy-bar ${visible ? 'visible' : ''}`} aria-hidden={!visible}>
<img src={product.image} alt="" width="40" height="40" />
<span>{product.name}</span>
<span>${product.price}</span>
<button onClick={onAddToCart} tabIndex={visible ? 0 : -1}>Add to Cart</button>
</div>
);
}.sticky-buy-bar {
position: fixed; bottom: 0; left: 0; right: 0;
background: #fff; border-top: 1px solid #e2e8f0;
transform: translateY(100%); transition: transform 0.2s ease; z-index: 50;
padding-bottom: env(safe-area-inset-bottom); /* iPhone home indicator */
display: flex; align-items: center; gap: 0.5rem; padding: 0.75rem 1rem;
}
.sticky-buy-bar.visible { transform: translateY(0); }.cart-drawer {
position: fixed; right: 0; top: 0; bottom: 0;
width: min(400px, 100vw); background: #fff;
transform: translateX(100%); transition: transform 0.3s ease;
overflow-y: auto; overscroll-behavior: contain;
}
@media (max-width: 640px) {
.cart-drawer {
top: auto; width: 100vw; height: 85vh;
transform: translateY(100%); border-radius: 16px 16px 0 0;
}
.cart-drawer.open { transform: translateY(0); }
}
.cart-drawer.open { transform: translateX(0); }
/* Checkout button stays within thumb reach */
.cart-checkout-btn {
position: sticky; bottom: 0; background: #fff;
padding: var(--space-md);
padding-bottom: calc(var(--space-md) + env(safe-area-inset-bottom));
}button, a, input[type="checkbox"], input[type="radio"], select, [role="button"] {
min-height: var(--touch-target);
min-width: var(--touch-target);
}min-widthenv(safe-area-inset-bottom)overscroll-behavior: contain100dvh100vh100vh<body>| Problem | Solution |
|---|---|
| Sticky buy bar obscures footer or checkout button | Hide the bar when the footer or checkout button enters the viewport using IntersectionObserver |
| iOS Safari layout jumps when toolbar appears | Use |
| Font too small to read without pinch-zooming | Set |
| Cart drawer body scroll | Apply |
| Product images load slowly on mobile | Specify |