The best CSS framework depends on how you build. Tailwind suits teams who style in markup with utility classes, Bootstrap gives ready-made components with optional JavaScript, Bulma is components without JavaScript, Pico styles plain semantic HTML, UnoCSS is an on-demand utility engine, and modern plain CSS now covers most needs alone.
| Option | Style of writing |
|---|---|
| Tailwind CSS | Utility classes in the markup, build step |
| Bootstrap | Component classes plus a utility layer |
| Bulma | Component classes, CSS only |
| Pico CSS | Styles bare HTML elements, very few classes |
| UnoCSS | Utility engine with presets, build step |
| Plain CSS | Your own classes, custom properties, nesting |
Updated
Comparison posts usually list features. This one writes the same small pricing card in all six options so you can read the markup side by side, then compares how each is customised, whether it ships JavaScript and what licence it uses. A short picker at the top suggests a starting point from four questions.
Licences are from each project's repository. Sizes are left out on purpose, because they depend on version, build settings and, for utility engines, on which classes your pages use.
| Option | Approach | JavaScript | Licence | Customisation | Build step |
|---|---|---|---|---|---|
| Tailwind CSS | Utility-first | None at runtime | MIT | Theme variables in CSS (v4 @theme), arbitrary values | Yes, CLI or bundler plugin |
| Bootstrap 5 | Components plus utilities | Optional bundle for modals, dropdowns, collapse, tooltips | MIT | Sass variables, CSS custom properties | No for CDN use, yes for Sass |
| Bulma | Components | None shipped | MIT | Sass variables and CSS custom properties | No for CDN use |
| Pico CSS | Classless or minimal classes | None shipped | MIT | CSS custom properties, colour themes | No |
| UnoCSS | Atomic engine with presets | None at runtime (optional runtime mode) | MIT | Presets, rules and shortcuts in config | Yes, normally |
| Plain CSS | Your own classes | None | Yours | Anything | No |
Every version below shows the same content: a plan name, a price, three features and a button. Compare where the styling decisions live.
All styling is in utility classes. Hover and focus states sit next to the base style.
<div class="max-w-xs rounded-2xl border border-slate-200 bg-white p-6 shadow-sm">
<h3 class="text-sm font-semibold uppercase tracking-wide text-slate-500">Pro</h3>
<p class="mt-2 text-4xl font-bold text-slate-900">$19<span class="text-base font-normal text-slate-500">/mo</span></p>
<ul class="mt-4 space-y-2 text-slate-700">
<li>Unlimited projects</li><li>Custom domain</li><li>Email support</li>
</ul>
<a href="#" class="mt-6 block rounded-lg bg-blue-600 px-4 py-2 text-center font-semibold text-white hover:bg-blue-700 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600">Choose Pro</a>
</div>The card component provides the frame; utilities such as text-center and w-100 fill the gaps.
<div class="card text-center" style="max-width: 20rem">
<div class="card-header text-uppercase fw-semibold">Pro</div>
<div class="card-body">
<p class="display-6 fw-bold">$19<small class="fs-6 text-body-secondary">/mo</small></p>
<ul class="list-unstyled">
<li>Unlimited projects</li><li>Custom domain</li><li>Email support</li>
</ul>
<a href="#" class="btn btn-primary w-100">Choose Pro</a>
</div>
</div>Bulma names parts of the card explicitly and uses is- and has- modifiers for variants.
<div class="card" style="max-width: 20rem">
<header class="card-header"><p class="card-header-title">Pro</p></header>
<div class="card-content">
<p class="title is-2">$19<span class="is-size-6 has-text-grey">/mo</span></p>
<div class="content"><ul>
<li>Unlimited projects</li><li>Custom domain</li><li>Email support</li>
</ul></div>
<a href="#" class="button is-primary is-fullwidth">Choose Pro</a>
</div>
</div>No card class at all. Pico styles article as a card and a link with role=button as a button.
<article>
<header><strong>Pro</strong></header>
<h3>$19<small>/mo</small></h3>
<ul>
<li>Unlimited projects</li><li>Custom domain</li><li>Email support</li>
</ul>
<footer><a href="#" role="button">Choose Pro</a></footer>
</article>With the Wind and Attributify presets, utilities can be grouped into attributes. Plain Tailwind-style classes also work.
<div max-w-xs rounded-2xl border="~ slate-200" bg-white p-6 shadow-sm>
<h3 text="sm slate-500" font-semibold uppercase>Pro</h3>
<p mt-2 text="4xl slate-900" font-bold>$19<span text="base slate-500" font-normal>/mo</span></p>
<ul mt-4 space-y-2 text-slate-700>
<li>Unlimited projects</li><li>Custom domain</li><li>Email support</li>
</ul>
<a href="#" mt-6 block rounded-lg bg="blue-600 hover:blue-700" px-4 py-2 text="center white" font-semibold>Choose Pro</a>
</div>Custom properties hold the design tokens and native nesting keeps the rules together. Edit the variables to retheme it.
<style>
.plan {
--accent: #2563eb; --radius: 16px; --ink: #0f172a;
max-width: 18rem; padding: 1.5rem; border: 1px solid #e2e8f0;
border-radius: var(--radius); font-family: system-ui, sans-serif; color: var(--ink);
& h3 { margin: 0; font-size: .8rem; letter-spacing: .08em; text-transform: uppercase; color: #64748b; }
& .price { margin: .5rem 0 1rem; font-size: 2.4rem; font-weight: 700;
& small { font-size: 1rem; font-weight: 400; color: #64748b; } }
& ul { padding-left: 1.1rem; line-height: 1.8; }
& a { display: block; margin-top: 1rem; padding: .6rem; border-radius: 10px;
background: var(--accent); color: #fff; text-align: center; font-weight: 600; text-decoration: none;
&:hover { filter: brightness(.92); }
&:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; } }
}
</style>
<div class="plan">
<h3>Pro</h3>
<p class="price">$19<small>/mo</small></p>
<ul><li>Unlimited projects</li><li>Custom domain</li><li>Email support</li></ul>
<a href="#">Choose Pro</a>
</div>
Utility frameworks give you one class per property, so a card is described by a dozen small classes in the HTML. Component frameworks give you a card class that bundles those decisions. Utilities make one-off designs fast and keep CSS from growing; components make a conventional look fast and keep markup short.
Classless frameworks like Pico go further in the component direction: the article element itself looks like a card. That is lovely for content sites and limiting when the design departs from the default.
Choose Tailwind or UnoCSS for an app with its own design system and a component layer in JavaScript. Choose Bootstrap when you need dropdowns, modals and forms working today and a conventional look is fine. Choose Bulma when you want that component style but bring your own JavaScript.
Choose Pico for documentation, prototypes and small sites written mostly as plain HTML. Choose plain CSS when the site is small, the design is bespoke, or you want zero dependencies to keep up to date.
There is no single winner. Tailwind is the common pick for component-based apps built with React, Vue or Svelte. Bootstrap remains a quick route to a conventional admin or marketing layout. Pico suits documents and small sites, and plain CSS is enough for many simple projects.
UnoCSS is the closest, with a Tailwind-compatible preset and extra modes such as attributify. If you want fewer classes in the markup, Pico CSS or plain CSS with custom properties are the opposite approach. Bootstrap's utility classes cover part of the same ground.
Bulma gives a similar component vocabulary with no JavaScript at all. Foundation is another component framework with its own grid. For a lighter result, Pico styles semantic HTML, and Tailwind lets you build components from utilities instead of overriding defaults.
Not always. Grid, flexbox, custom properties, clamp(), container queries and native nesting now cover layout, theming and responsive type. A framework still saves time on consistent spacing scales, form styling and team conventions.
Yes. Tailwind CSS, Bootstrap, Bulma, Pico CSS and UnoCSS are all released under the MIT licence, which allows commercial use as long as the copyright notice stays with the code. Paid add-ons such as theme kits have their own terms.
Related: Bootstrap 5 examples, CSS variables guide, Modern CSS features, Flexbox and grid cheat sheet, HTML page generator.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.