Styling with utility classes
Building complex components from a constrained set of primitive utilities.
Overview
You style things with Sprig by combining many single-purpose presentational classes (utility classes) directly in your markup:
<div class="mx-auto flex max-w-sm items-center gap-x-4 rounded-xl bg-white p-6 shadow-lg outline outline-black/5">
<img class="size-12 shrink-0" src="/img/logo.svg" alt="Parcelpost logo" />
<div>
<div class="text-xl font-medium text-black">Parcelpost</div>
<p class="text-gray-500">Your package is out for delivery.</p>
</div>
</div>For example, in the UI above we've used:
The display and padding utilities (
flex,shrink-0andp-6) to control the overall layoutThe
max-widthand margin utilities (max-w-smandmx-auto) to constrain the card width and centre it horizontallyThe
background-color,border-radiusandbox-shadowutilities to style the card's appearanceThe font-size and font-weight utilities to style the card text
Why not just use inline styles?
A common reaction to this approach is wondering, "isn't this just inline styles?" In some ways it is — you're applying styles directly to elements instead of assigning them a class name. But using utility classes has many important advantages:
Designing with constraints — utilities pick from a predefined design system, which makes it much easier to build visually consistent UIs.
Hover, focus and other states — inline styles can't target states like hover or focus, but Sprig's state variants make it easy.
Media queries — you can't use media queries in inline styles, but you can use Sprig's responsive variants.
Thinking in utility classes
Styling hover and focus states
To style an element on states like hover or focus, prefix any utility with the state you want to target:
<button class="bg-teal-600 hover:bg-teal-700 focus:outline-2 focus:outline-offset-2 focus:outline-teal-600">
Save changes
</button>Media queries and breakpoints
Just like hover and focus states, you can style elements at different breakpoints by prefixing any utility with the breakpoint where you want that style to apply:
<div class="grid grid-cols-2 sm:grid-cols-3">
<!-- ... -->
</div>Using arbitrary values
Many utilities in Sprig are driven by theme variables, like bg-teal-500, text-xl and shadow-md. When you need a one-off value, use square brackets:
<button class="bg-[#316ff6] ...">Sign in with Fernbook</button>Managing duplication
When you build entire projects with just utility classes, you'll inevitably find yourself repeating certain patterns. Most of the time this isn't a problem — use loops, multi-cursor editing, or extract a component.
Using components
If you need to reuse some styles across multiple files, the best strategy is to create a component if you're using a front-end framework like React, Svelte or Vue.
Managing style conflicts
Conflicting utility classes
When you add two classes that target the same CSS property, the class that appears later in the stylesheet wins.
In general, you should never add two conflicting classes to the same element — only ever add the one you actually want to take effect.