Skip to main content
ASoc
Comparison

Nuxt vs Bootstrap: A Framework and a Stylesheet, Priced on a Real Build

Nuxt builds the pages, Bootstrap styles them, so they are not rivals. The styling options under Nuxt, with one measured build: 1 CSS file, 14.7 KiB gzipped.

The ASoc Team8 min read

Nuxt and Bootstrap are not competitors. Nuxt is a Vue framework: it routes, renders on the server and builds the site. Bootstrap is a stylesheet with a grid and ready-made components: it builds nothing. You can run Nuxt with Bootstrap, with Tailwind, or with neither. The real question is which styling layer to put under Nuxt, and this post prices that choice against a real build.

We do not ship Nuxt here. This storefront is Next.js, so every Nuxt statement below is about the framework in general and none is a measurement. What we can measure is the other half: what a utility-first stylesheet costs in a production build, how a Bootstrap-style .container is expressed without Bootstrap, and one trap in the toolchain that Nuxt users hit too. If you want the framework-versus-framework angle instead, read Next.js vs Nuxt. For the same split with a different framework, see Gatsby vs Bootstrap and React vs Bootstrap.

The two jobs, restated for Nuxt

NuxtBootstrap
RoleApplication framework on Vue and NitroCSS framework (Sass source, optional JS)
Generates pages from filesYesNo
Server rendering or static outputYesNo
Provides a grid and componentsNo (Nuxt has none built in)Yes
Ships JavaScriptYes, the Vue runtime and your appOptional, for modals, dropdowns and the like
Can replace the otherNoNo

So "Nuxt vs Bootstrap" really means one of three questions:

  1. Should I build with Nuxt, or with something else that generates pages (Next.js, Astro, plain Vue)?
  2. Should I style with Bootstrap, or with something else (Tailwind, a Vue UI kit, hand-written CSS)?
  3. Do I need a Vue binding for Bootstrap's interactive parts?

Questions 1 and 3 have framework-specific answers. Question 2 is where we have evidence.

The styling options under Nuxt

OptionWhat you getWhat it costs
Bootstrap via CSS importGrid, utilities, components, familiar markupClass soup is replaced by a fixed visual identity you override with Sass variables
Bootstrap with a Vue bindingComponents as Vue elements, no manual JS wiringA second dependency. The original BootstrapVue targets Vue 2 and Bootstrap 4; Vue 3 projects use the separate bootstrap-vue-next
Tailwind CSS aloneUtilities and a token system, no componentsYou write the components
Nuxt UIVue components built on TailwindA component library to learn and upgrade
Hand-written CSSFull control, smallest outputEvery component, forever

The trade is the one every framework faces. Bootstrap gives you a finished look in an afternoon and a recognisable one for years. Tailwind gives you a blank canvas with a token system. For a marketing site where design is the product, the second tends to win. For an internal admin tool where nobody will look twice, the first often does.

What a utility-first stylesheet actually costs

The usual objection to Tailwind is "all those classes bloat the HTML". The stylesheet side of the ledger is easier to measure. This storefront's production build has 894 prerendered pages (111 product pages, 373 posts and the rest) and one CSS file:

MeasureValue
CSS files in .next/static/chunks/1
Size on disk85,437 bytes (83.4 KiB)
Gzipped (gzip -9)15,051 bytes (14.7 KiB)
Source filesrc/app/globals.css, 133 lines
Colour token lines in that file38

Tailwind v4 generates CSS only for the utilities that appear in the source, so the file grows with what you use rather than with the framework's size. That is a property of the generator, and it is why a site with 111 product templates still ships one stylesheet. We have not measured a Bootstrap build of this storefront, so we make no size claim about it. You can check yours the same way: build, then gzip -9 < file.css | wc -c.

The whole configuration is CSS. There is no tailwind.config.js:

/* src/app/globals.css */
@import "tailwindcss";

/* Class-based dark mode (toggled by adding `dark` to <html>) */
@custom-variant dark (&:where(.dark, .dark *));

@theme {
  --font-sans: var(--font-outfit), ui-sans-serif, system-ui, sans-serif;

  /* Brand / primary scale */
  --color-primary: #465fff;
  --color-primary-25: #f2f7ff;
  --color-primary-50: #ecf3ff;
}

Every token declared under @theme becomes a utility (bg-primary, text-primary-50). The Bootstrap equivalent is overriding Sass variables before importing the library, which requires a Sass build step. In a Nuxt project that is one more dependency (sass) and one more place a variable can silently fail to apply.

Where the grid went

People pick Bootstrap partly for .container. It is a few lines of CSS, and this repo writes its own in the same file:

.container {
  width: 100%;
  margin-inline: auto;
  padding-inline: 1rem;
}
@media (min-width: 768px) {
  .container {
    max-width: 768px;
  }
}
@media (min-width: 1536px) {
  .container {
    max-width: 1536px;
    padding-inline: 3rem;
  }
}

The full rule has seven media queries between 425px and 1536px: six max-width steps and one padding change. Bootstrap 5's own container steps at its breakpoints are 540, 720, 960, 1140 and 1320 pixels. The point is not that one set is better. It is that "I need Bootstrap for the grid" is rarely true any more: CSS grid and flexbox, which Tailwind exposes as grid and flex utilities, cover the same layouts, and a container is a one-time paste. The atoms layer wraps it once as src/components/atoms/Container.tsx so no page repeats it.

The trap that follows you into Nuxt

One defect from this repo's history is relevant to any Tailwind v4 setup on a modern bundler. The project notes record it plainly: Tailwind v4 with Turbopack does not hot-reload @theme changes. You add --color-brand-500 to the file, save, and bg-brand-500 silently does nothing until the dev server restarts. The fix that shipped is a rule, not code: restart the dev server after editing tokens.

The shape of that failure matters for Nuxt. Nuxt runs on Vite, a different bundler, so the exact symptom may differ, but the class of problem is the same: a theme file is read at startup by one process, and the dev server's watcher does not treat it as a source file. When a utility class "does nothing" after you add a token, restart before you debug anything else. Bootstrap's Sass variables have an equivalent: a variable defined after @import "bootstrap" has no effect, because Sass resolves them in order.

Dark mode, since both tools offer it

Bootstrap 5.3 added colour modes driven by a data-bs-theme attribute. Tailwind's approach, shown above, is a custom variant keyed to a .dark class on <html>. Either way the hard part is the flash of the wrong theme before hydration. This repo sets the class from an inline script in src/app/layout.tsx that reads localStorage before first paint and defaults to light. Dark mode in Next.js without the flash walks through it; in Nuxt the same job is done in a head script or the colour-mode module, and the principle is identical: decide before the framework boots.

A decision rule

If you...Choose
Want a finished look quickly and your team knows BootstrapNuxt with Bootstrap CSS, and Sass variables for branding
Need Bootstrap's modals and dropdowns as Vue componentsNuxt plus bootstrap-vue-next, after checking its Vue 3 support level
Care about a bespoke design and small, generated CSSNuxt with Tailwind, or a Tailwind-based kit
Do not already use VueReconsider Nuxt first; see Next.js vs Vue
Are choosing for a landing page, not an appA prebuilt template; the framework matters less than the finished front end

Troubleshooting

SymptomCauseFix
A new Tailwind token does nothingTheme file not hot-reloadedRestart the dev server
Bootstrap theme colours ignoredVariables set after the importOverride Sass variables before @import "bootstrap"
Bootstrap modal will not openBootstrap's JS is not loaded or initialisedLoad the bundle on the client only, or use a Vue binding
Hydration mismatch after adding Bootstrap JSLibrary touches the DOM during server renderRun it in a client-only plugin
Dark theme flashes on loadTheme applied after paintSet it from an inline head script
Two CSS frameworks fightBootstrap reboot and Tailwind preflight both reset elementsUse one, or scope Bootstrap to a container

Frequently asked questions

Can I use Bootstrap with Nuxt? Yes. Import its CSS, or its Sass for theming, in your Nuxt config or a plugin. For interactive components use a Vue binding designed for your Vue version rather than raw Bootstrap JS, which manipulates the DOM directly.

Is Nuxt better than Bootstrap? The question compares different things. Nuxt generates and serves pages. Bootstrap styles them. A Nuxt project can use Bootstrap, so choosing one never rules out the other.

Should I use Tailwind or Bootstrap with Nuxt? Bootstrap if you want finished components fast and accept a recognisable look. Tailwind if you want a bespoke design and CSS generated only for what you use. The build above ships 14.7 KiB gzipped from a 133-line config, which is a Tailwind result, not a promise about your project.

Is Nuxt UI an alternative to Bootstrap? Yes, in the component-library role. It is a Vue component set built on Tailwind, so it pairs with the Tailwind option rather than replacing the framework.

Start from a finished front end

If the real goal is a finished landing page, the framework-and-stylesheet debate is the part you can skip. ASoc Quill, ASoc Rally and ASoc Rank are Next.js and Tailwind landing sets with the container, tokens and dark mode already wired.

Browse the sets: Next.js landing page templates and Tailwind landing page templates.

Keep reading

Comparison7 min read

One-Time Payment vs Subscription: What the Webhook Handler Has to Know

Our entitlement engine is 75 lines with two status states; our LemonSqueezy webhook recognizes two event names. That's not a shortcut — it's the real cost gap between the two pricing models.

Read more
Comparison8 min read

Playwright vs Vitest: Why This Repo Runs Both for Unrelated Jobs

Vitest is a committed dependency gating 305 tests on every push. Playwright is deliberately not a dependency at all — installed ad hoc for a script that runs a few times a year.

Read more
Comparison9 min read

Qwik vs. Next.js: Resumability vs. Not Shipping the Component

Qwik ships near-zero JS through resumability; this site's RSC split already does that for 9 of 10 home-page sections. Where the real cost still lands: one accordion.

Read more