Tailwind or own CSS: which approach to choose

How Tailwind and own CSS differ: twelve criteria, which approach for which project, one card built both ways with measured file sizes, six rules of order and common mistakes.

Stack and technologies Updated

In short

Tailwind and your own CSS lead to the same result in the browser — the difference is in where the styles live and who maintains them. Tailwind puts styles into the markup as short ready-made classes: fast to start, one vocabulary for the whole team, but long class strings and a build step. Your own CSS keeps styles in separate files on a token system: clean markup, no dependency on a tool and full use of modern CSS, but it needs discipline so the files do not turn into a dump. Choose Tailwind when the project will be maintained by a team that already works with it; choose your own CSS on tokens when the design is unique and the project should not depend on a framework.

In short: which one to choose

The decisive question is not taste but who will change the styles in a year. If the project goes to an in-house team that writes in Tailwind, building it in Tailwind saves them weeks: they open the markup and see a familiar vocabulary. If the studio maintains the project or the design has to be unique, own CSS on tokens gives cleaner markup, smaller files and no dependency on the next major version of a tool.

Both approaches rest on the same foundation — design tokens. In Tailwind 4 they live in the @theme block and become CSS variables; in own CSS they are CSS variables from the start. Whoever keeps colours, spacing and fonts in one place wins with either tool.

  • Your team works in Tailwind — Tailwind
  • Unique design, long life — own CSS
  • Either way — tokens first

Tailwind and own CSS: a detailed comparison

Twelve criteria side by side. File sizes were measured on the same card built both ways.

CriterionTailwindOwn CSS
Where the styles live classes in the markup separate files by component
Markup long class strings short names by meaning
Start of a project very fast, the scale is ready tokens are set up first
Tokens in @theme, become CSS variables CSS variables from the start
Consistency held by the scale held by tokens and discipline
CSS for one card 7.1 KB, 2.3 KB gzip 0.9 KB, 0.4 KB gzip
Growth with the site slow, classes are reused with each component
Modern CSS through variants: @container, has-[…] directly, all of it
Build required optional
Unique design possible, fights the scale natural
A new developer knows the vocabulary already learns the project’s system
Dependence on the tool and its versions on the browser only

Which approach for which project

Ten typical situations with a recommendation and the reason.

SituationTakeWhy
The project goes to your team on Tailwind Tailwind they maintain it in their own vocabulary
Admin panel or internal tool Tailwind many standard screens, speed matters more than uniqueness
Prototype for a test Tailwind the ready scale saves days
Corporate site with its own style Own CSS the design is not built from a standard scale
Premium brand, a lot of motion Own CSS animation and details are easier to write directly
Site without a build step Own CSS Tailwind needs a build
Design system for several products Own CSS on tokens the tokens outlive any framework
React application either both work; the team decides
Email templates Own CSS mail clients need inline styles anyway
An existing project what it is already in two systems in one project are worse than either

One card, two approaches

The same product card built in Tailwind 4 and in own CSS with the same tokens. Both builds were opened in a browser and look identical.

Tailwind: the tokens

In Tailwind 4 the settings moved from a JavaScript file into CSS.

app.css
@import "tailwindcss";

/* Project tokens: Tailwind 4 turns them into CSS variables
   and into classes such as text-ink, bg-ink, border-line */
@theme {
  --color-ink: #171817;
  --color-muted: #5f625f;
  --color-line: #e2e3e1;
}

Tailwind: the card

Every style is a class in the markup; hover and focus are variants of the same classes.

card.html
<article class="max-w-sm rounded-lg border border-line bg-white p-6">
  <h3 class="text-lg font-semibold tracking-tight text-ink">Oak table</h3>
  <p class="mt-2 text-sm text-muted">Solid oak, 160 × 90 cm</p>
  <a href="/catalog/oak-table"
     class="mt-6 inline-flex min-h-11 items-center rounded-md bg-ink px-5
            text-sm font-medium text-white transition-colors hover:bg-ink/80
            focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">
    Details
  </a>
</article>

Own CSS: the card

The markup says what the element is; how it looks is decided in the stylesheet.

card.html
<article class="card">
  <h3 class="card__title">Oak table</h3>
  <p class="card__text">Solid oak, 160 × 90 cm</p>
  <a class="card__link" href="/catalog/oak-table">Details</a>
</article>

Own CSS: tokens and the component

The same tokens as CSS variables and one component. Minified, it is 0.9 KB — Tailwind’s file for this card is 7.1 KB, about half of it the style reset.

card.css
/* Project tokens: colours, spacing and radii in one place */
:root {
  --color-ink: #171817;
  --color-muted: #5f625f;
  --color-line: #e2e3e1;
  --space-2: 0.5rem;
  --space-6: 1.5rem;
  --radius: 0.5rem;
}

/* The component: class names say what it is, not how it looks */
.card {
  box-sizing: border-box;
  max-width: 24rem;
  padding: var(--space-6);
  border: 1px solid var(--color-line);
  border-radius: var(--radius);
  background: #fff;
}
.card__title {
  margin: 0;
  font-size: 1.125rem;
  font-weight: 600;
  letter-spacing: -0.025em;
  color: var(--color-ink);
}
.card__text {
  margin: var(--space-2) 0 0;
  font-size: 0.875rem;
  color: var(--color-muted);
}
.card__link {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;
  margin-top: var(--space-6);
  padding: 0 1.25rem;
  border-radius: 0.375rem;
  background: var(--color-ink);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 500;
  text-decoration: none;
  transition: background-color 0.15s;
}
.card__link:hover {
  background: color-mix(in oklab, var(--color-ink) 80%, transparent);
}
.card__link:focus-visible {
  outline: 2px solid var(--color-ink);
  outline-offset: 2px;
}

How to keep either approach clean

Both approaches degrade the same way — through exceptions. Six rules that stop it.

  1. 01

    Tokens first

    Colours, spacing, radii and fonts are set before the first component, in one place.

  2. 02

    Components in templates

    In Tailwind a repeated card is a template or a component, not a copied string of classes.

  3. 03

    Few arbitrary values

    Every p-[13px] breaks the scale; a missing step is added to the tokens.

  4. 04

    @apply sparingly

    Rebuilding classic CSS out of @apply gets the costs of both approaches and the benefits of neither.

  5. 05

    Names by meaning

    In own CSS .card__title, not .bold-black-text — the look will change, the meaning will not.

  6. 06

    Layers instead of !important

    @layer sets the order of resets, components and exceptions, so specificity wars do not start.

Common mistakes when choosing

  1. Tailwind as a design

    The default scale without own tokens makes the site look like thousands of others.

  2. Own CSS without a system

    Values in every rule instead of tokens — in a year nobody knows which grey is right.

  3. Two systems in one project

    Half in utilities, half in own files — every change has to be searched for in both.

  4. Choosing for the size

    A few kilobytes of CSS rarely decide speed — images, fonts and scripts weigh far more.

  5. Classes built from strings

    Tailwind finds only whole class names in the code; bg-${color} silently disappears from the build.

  6. Forgetting the next major version

    Moving from Tailwind 3 to 4 changed the configuration — a framework needs updating time in the plan.

Questions about Tailwind and own CSS

Is Tailwind better than plain CSS?

Neither is better: Tailwind is faster to start and easier to hand to a team, own CSS gives cleaner markup and no dependency.

Does Tailwind slow the site down?

No: the build keeps only the classes in use, and on a large site the file stays small.

What changed in Tailwind 4?

The settings moved into CSS (@theme), tokens became CSS variables, and the build got much faster.

Is it hard to move from Tailwind to own CSS?

It means rewriting the markup of every component — so the choice is made at the start.

Does the choice affect SEO?

No: search engines and AI assistants read the HTML structure and the text, not the class names.

Can Tailwind use container queries?

Yes, since version 4 they are built in: @container on the parent and @md: on the children.

What about Bootstrap?

It gives ready components with a recognisable look — suitable for internal tools, rarely for a site with its own style.

Online form

Discuss
the layout

I build on my own token system, and use Tailwind when the project will be maintained by your team and they work with it. Tell me about the project — I answer within one working day.

Or write to [email protected]