Pairing Svelte With Tailwind CSS

Svelte’s compiler-based approach means your final bundle contains vanilla JavaScript rather than a framework runtime, which keeps apps small and fast. Tailwind CSS complements that philosophy with utility-first styling that lives directly on your markup, so there’s no separate stylesheet to consult while building components.

This guide walks through wiring Tailwind into a fresh Svelte project using the official starter template. A working example is available in this GitHub repo if you want to skip straight to the code.

Why These Two Tools

Svelte compiles your source into plain JavaScript at build time. When a browser loads the resulting app, it downloads only those lightweight files instead of pulling down a UI framework library at runtime the way React or Vue apps do. That difference is why Svelte applications tend to load quickly.

Tailwind is an atomic CSS framework—each utility class applies a single style, which is the opposite of component-based frameworks like Bootstrap that ship opinionated, hard-to-override designs. Instead of inheriting a generic header style, you combine small utilities like text-sm and p-3 to build something original. The class names are descriptive, so you rarely struggle with naming custom CSS.

Tailwind’s mobile-first breakpoints (using sm, md, and lg prefixes) also make responsive styling straightforward, and its PurgeCSS integration strips out unused classes so your production CSS stays lean.

Some developers dislike seeing long chains of utility classes in HTML. If that’s a concern, you can group repeated utilities into a custom class with the @apply directive. Conversely, if you prefer ready-made component kits or are under a very tight deadline, Tailwind’s DIY approach may not fit your workflow.

Step 1: Scaffold a Svelte App

Svelte’s starter template is the fastest path to a working project. Use degit to clone it without the repository’s full Git history, then install dependencies:

npx degit sveltejs/template project-name
cd project-name
npm install

Step 2: Install Tailwind and Its Dependencies

Add Tailwind along with PostCSS and Autoprefixer as dev dependencies. PostCSS is a JavaScript-based CSS transformer with plugins for polyfilling and error checking. Autoprefixer, a PostCSS plugin, uses caniuse data to add vendor prefixes—something Tailwind does not handle on its own.

npm install tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9

 # or

yarn add tailwindcss@npm:@tailwindcss/postcss7-compat postcss@^7 autoprefixer@^9

Note that Svelte currently works with PostCSS 7, not the newer PostCSS 8 release. The command below pins that version to avoid compatibility errors:

  1. Tailwind
  2. PostCSS
  3. Autoprefixer

Step 3: Configure Tailwind

Generate a configuration file with:

npx tailwindcss init  tailwind.config.js

Open the new tailwind.config.js and add compatibility settings that handle deprecations in Tailwind 2.0:

future: {
  purgeLayersByDefault: true,
  removeDeprecatedGapUtilities: true,
},

Tailwind 2.0 purges all layers by default and replaces some old gap utilities. Setting purgeLayersByDefault and removeDeprecatedGapUtilities to true keeps those behaviors consistent in future updates.

Purge Unused Styles

Tailwind includes thousands of utility classes, and shipping all of them makes your CSS unnecessarily heavy. Configure purge so unused classes are stripped out during production builds only:

purge: {
  content: [
    "./src/**/*.svelte",
  ],
  enabled: production // disable purge in dev
},

Your finished tailwind.config.js should look like this:

const production = !process.env.ROLLUP_WATCH;
module.exports = {
  future: {
    purgeLayersByDefault: true,
    removeDeprecatedGapUtilities: true,
  },
  plugins: [

  ],
  purge: {
    content: [
     "./src/**/*.svelte",

    ],
    enabled: production // disable purge in dev
  },
};

Step 4: Wire Tailwind Into Svelte’s Build

Svelte uses Rollup.js, a module bundler created by the same person behind Svelte. Rollup consolidates source files and can lint or preprocess code during bundling. Its configuration lives in rollup.config.js.

PostCSS syntax is foreign to Svelte, so we need the sveltePreprocess package to translate it. Start by importing it in the Rollup config:

import sveltePreprocess from "svelte-preprocess";

Then add sveltePreprocess as a plugin, passing Tailwind and Autoprefixer so they run on the CSS before it reaches Svelte’s compiler:

preprocess: sveltePreprocess({
  sourceMap: !production,
  postcss: {
    plugins: [
     require("tailwindcss"), 
     require("autoprefixer"),
    ],
  },
}),

Step 5: Inject Tailwind Styles

Tailwind’s styles are brought in with the @tailwind directive, which works like an import for the framework’s CSS. Three directive sets exist, and they should be placed in a high-level component like App.svelte:

  • @tailwind base — Injects Preflight styles, largely from Normalize.css, to smooth out cross-browser inconsistencies (removing default margins, unstyling headings, etc.).
  • @tailwind components — A placeholder for reusable component styles you define. Tailwind itself ships very few components; you can omit this directive if you only use utilities.
  • @tailwind utilities — Where all utility classes are injected, including any you create.
<style global lang="postcss">
  @tailwind base;
  @tailwind components;
  @tailwind utilities;
</style>

Step 6: Build a Header With Tailwind Classes

Start with plain markup inside App.svelte’s main tag:

This is what we have so far in the browser. Tailwind gives us everything we need to customize this into something unique, like the header we’re about to create.
<nav>
  <div>
    <div>
      <a href="#">APP LOGO</a>

      <!-- Menus -->
      <div>
        <ul>
          <li>
            <a href="#">About</a>
          </li>
          <li>
            <a href="#">Services</a>
          </li>
          <li>
            <a href="#">Blog</a>
          </li>
          <li>
            <a href="#">Contact</a>
          </li>
        </ul>
      </div>

    </div>
  </div>
</nav>
What we have with zero styling whatsoever.

Then add your styling:

<nav class="bg-blue-900 shadow-lg">
  <div class="container mx-auto">
    <div class="sm:flex">
      <a href="#" class="text-white text-3xl font-bold p-3">APP LOGO</a>
      
      <!-- Menus -->
      <div class="ml-55 mt-4">
        <ul class="text-white sm:self-center text-xl">
          <li class="sm:inline-block">
            <a href="#" class="p-3 hover:text-red-900">About</a>
          </li>
          <li class="sm:inline-block">
            <a href="#" class="p-3 hover:text-red-900">Services</a>
          </li>
          <li class="sm:inline-block">
            <a href="#" class="p-3 hover:text-red-900">Blog</a>
          </li>
          <li class="sm:inline-block">
            <a href="#" class="p-3 hover:text-red-900">Contact</a>
          </li>
        </ul>
      </div>

    </div>
  </div>
</nav>

Breaking Down the Classes

The <nav> element uses bg-blue-900 for a dark blue background and shadow-lg for a large box shadow:

<nav class="bg-blue-900 shadow-lg">

The outer container is centered horizontally with mx-auto, equivalent to margin: auto:

<div class="container mx-auto">

The inner flex container uses sm:flex so the logo and links become responsive on small screens and up:

<div class="sm:flex">

The logo gets text-white for color, text-3xl for sizing (1.875rem font, 2.25rem line height), and p-3 for 0.75rem padding on all sides:

<a href="#" class="text-white text-3xl font-bold p-3">APP LOGO</a>

The navigation wrapper has ml-55—a custom class not in Tailwind’s defaults—to push the links 55% from the left:

<div class="ml-55 mt-4">

Define that custom style in your component’s <style> block. There’s also mt-4, which adds a 1rem top margin:

.ml-55 {
  margin-left: 55%;
}

The unordered list centers itself with sm:self-center, uses text-white, and sizes up with text-xl:

<ul class="text-white sm:self-center text-xl">

Each <li> uses sm:inline-block so links sit side-by-side:

<li class="sm:inline-block">

Finally, each <a> turns red on hover via hover:text-red-900:

<a href="#" class="p-3 hover:text-red-900">

Launch the dev server with:

npm run dev 

The result should look like this:

Where to Go From Here

You now have Tailwind running inside a Svelte app with PurgeCSS active for production and a responsive header built entirely from utilities. A natural next exercise is adding a sign-up form and footer to the same page. Tailwind’s official documentation covers every utility class if you want to dig deeper.