UI styling shapes the storefront’s look and feel, including layout, spacing, colors, typography, and interactive states. It provides a consistent, accessible, and responsive shopping experience for your storefront across devices.
Technology Stack
Storefront Next uses Tailwind CSS (v4) for utility-first styling and shadcn/ui patterns, and Radix UI for headless accessible components.
Here are the Tailwind-related dependencies in this package.
Dependency
Version
Purpose
tailwindcss
4.x.x+
Utility-first CSS framework
@radix-ui/*
Various
Headless UI primitives
class-variance-authority
0.7.1
Component variant management
clsx
2.1.1
Conditional class composition
tailwind-merge
3.4.0
Tailwind class conflict resolution
Global Styles and CSS Variables
The global and theme styles are in src/theme/ only. The entry point is src/theme/index.css, with tokens split across src/theme/tokens/, base resets in src/theme/base.css, and component overrides in src/theme/overrides/.
Hardcoded Tailwind color utilities like bg-red and text-green are blocked via an ESLint rule. Use semantic tokens (for example, bg-primary, text-foreground) or CSS variable classes instead.
Reusing Styles: When to Extract
Tailwind’s utility-first approach means most styling lives inline in JSX. Before extracting a reusable abstraction, read the official guide on managing reuse — it covers multi-cursor editing, loops, and component extraction as the preferred strategies before reaching for CSS abstractions.
Use a React component (the default choice) when:
The pattern involves markup structure—multiple elements, slots, children
There is logic, state, or event handling
It accepts props that change behavior or content
It composes other components (shadcn, Radix, etc.)
Use a CSS component class (@layer components in src/theme/base.css) only when:
The pattern is pure layout/styling—padding, max-width, centering, typography presets
There is no logic, state, or props—just a bag of CSS properties
It needs to be applied to many different HTML elements across the codebase (divs, sections, wrappers)
Utilities need to override it in specific contexts (the components layer is lower specificity than utilities)
Example: section-container—consolidates px-4 sm:px-8 lg:px-16 max-w-screen-2xl mx-auto into one class, used by 30+ files. A page can add max-w-4xl alongside it and the utility wins.
Rule of thumb: if you can express it as a single className string with no JSX children, it’s a CSS class. If it renders elements or accepts props, it’s a React component.
1/* React component — has structure, props, and children */2function CategoryBanner({ title, image }: CategoryBannerProps) {3 return (4 <div className="section-container">5 <img src={image} alt="" />6 <h1>{title}</h1>7 </div>8 );9}
Don’t use @utility for multi-property compositions that need to be overridable. The utility layer has the highest specificity, so any override attempt (e.g., adding max-w-4xl alongside a @utility class) would lose. Use @layer components instead.