Skip to content

Front end

Tailwind CSS

Utility classes for styling interfaces, used on nearly every build so styles sit next to the markup, not in a parallel stylesheet.

Tailwind is a set of small single-purpose CSS classes, one per declaration, applied directly in markup, with a build step that emits only the classes actually found in your files. The trade is explicit: your HTML gets noisier and your stylesheet nearly disappears. What you buy is the end of the naming problem, and the end of the growing file of dead selectors nobody dares delete.

How we use it

It is on almost everything. Objectify uses it across a dense admin interface where a data explorer, a schema designer and a SQL editor all need to feel like one product. DMARC Engine and Jonosakti are both on version 4, which moved configuration out of a JavaScript file and into CSS. @Heartbeat uses it for a light and dark theme plus a separate mobile navigation, which is the case utilities handle well: the variants for theme and breakpoint sit on the element rather than in a media query somewhere else.

The rest follow the same pattern: ClassProfile, 360nutri on a phone-first camera flow, Starterflare, Linked Corporate through the PostCSS plugin, Consonas alongside Vue, and Taxcare Accountancy where it sits under a component layer of the shadcn kind. That last one is the arrangement we prefer on any project big enough to have a designer: utilities underneath, a small set of named components on top, so a button is defined once.

What it costs you

Read a line of markup with eighteen classes on it and you are reading a stylesheet inline, at the least convenient moment. It is genuinely worse to review in a diff, because a spacing change and a colour change look identical in the noise, and it punishes copy and paste: the same card duplicated four times is four places to change. Without a component layer this is the failure mode, and it arrives around month three.

The scanner is literal. It searches your source for class-shaped strings, so a class name assembled at runtime, text-${colour}-500, simply is not generated, and the fix is a lookup table of complete class names. Every team hits this once.

The version 3 to version 4 move is the current gotcha. The engine changed, configuration moved into CSS, some utility names changed and the PostCSS plugin was repackaged. Doing it on a large project is a real afternoon, sometimes more, and we have builds on both sides of that line, which is exactly the situation described in dependency rot. Design tokens also need enforcing by people: nothing stops a developer writing an arbitrary value in square brackets and putting a nineteenth grey into the product.

When we would choose something else

For a component library meant to be consumed by other teams, shipping utility classes exports your build configuration along with your components, and scoped CSS or CSS modules is the kinder choice. For a page that is a few hundred bytes of text, a hand-written stylesheet with a dozen rules beats a build step.

Where the requirement is behaviour rather than appearance, keyboard handling, focus traps, correct ARIA, no styling system helps, and we combine it with the primitives described on accessible UI components. And where a project has an existing design system in plain CSS that people are happy with, we leave it alone: converting a working stylesheet to utilities is billable hours that produce no change a user can see.

Where we have used it

Every build below lists this in its stack, so the claim is checkable.