Why Tailwind CSS fits a WordPress theme workflow

Tailwind CSS replaces hand-written site CSS with pre-made utility classes like hidden and uppercase. Unlike older frameworks such as Bootstrap or Foundation, it ships no opinionated visual design—just a CSS reset. That blank-slate approach keeps output lightweight while preserving full design freedom.

There is no production-ready “standard” Tailwind stylesheet to drop in from a CDN; including every utility class would produce an impractically large file. The Play CDN offered by Tailwind is fine for prototyping but intentionally unsuitable for production builds. In practice you always compile a project-specific subset of classes.

Two Tailwind behaviors matter most inside WordPress:

  • Class detection is build-time. Tailwind scans your project files and emits only utilities it finds. Any class used in the editor but nowhere in theme templates must be declared in advance—via a safelist in tailwind.config.js, comments listing classes next to custom block code, or a dedicated source file.
  • Preflight reset is aggressive. Tailwind’s built-in reset can conflict with styles owned by plugins, the admin area, or other parts of WordPress that expect theme CSS to behave conservatively.

For those reasons Tailwind suits full theme development far better than plugin or admin styling. When the theme output is the primary stylesheet, Preflight is an asset, not a liability. Full-site editing’s Global Styles likely will not interoperate with Tailwind, but other block-editor features can be adopted piecemeal alongside it.

A minimal theme with Tailwind

WordPress requires only two files for a minimal theme: style.css and index.php. Here the stylesheet is generated from Tailwind, and a basic template displays a single post:

<!doctype html>
<html lang="en">
  <head>
    <?php wp_head(); ?>
    <link rel="stylesheet" href="<?php echo get_stylesheet_uri(); ?>" type="text/css" media="all" />
  </head>
  <body>
    <?php
    if ( have_posts() ) {
      while ( have_posts() ) {
        the_post();
        the_title( '<h1 class="entry-title">', '</h1>' );
        ?>
        <div class="entry-content">
          <?php the_content(); ?>
        </div>
        <?php
      }
    }
    ?>
  </body>
</html>

The markup intentionally omits production necessities—pagination, thumbnails, proper enqueuing—but is enough to verify the integration. The Tailwind side needs three files: package.json, tailwind.config.js, and an input CSS file.

Start in the theme directory with npm installed, then initialize the project and install Tailwind:

echo {} > ./package.json
npm install tailwindcss --save-dev

Generate the configuration file:

npx tailwindcss init

Point Tailwind’s content scanner at theme PHP files:

module.exports = {
  content: ["./**/*.php"],
  theme: {
    extend: {},
  },
  plugins: [],
}

Sites using Composer should also exclude the vendor directory with a pattern such as "!**/vendor/**". Create an input file, e.g., tailwind.css, containing the required WordPress theme header and Tailwind directives:

/*!
Theme Name: WordPress + Tailwind
*/

@tailwind base;
@tailwind components;
@tailwind utilities;

The header comment lets WordPress recognize the theme; the three @tailwind directives pull in Tailwind’s base, components, and utilities layers. Finally, run the CLI:

npx tailwindcss -i ./tailwind.css -o ./style.css --watch

The output style.css rebuilds whenever a PHP file adds or removes a utility class. That is the smallest workable setup; next is integrating Tailwind into an existing, fully featured theme.

Retrofitting an existing theme

Adding Tailwind to a theme with existing vanilla CSS serves two purposes: experimenting with Tailwind components inside a styled theme, or gradually converting a theme away from hand-written CSS. Twenty Twenty-One is a better test subject than Twenty Twenty-Two: the latter’s full-site editing focus makes it a poor fit for a Tailwind pass.

After installing Twenty Twenty-One in a development environment, the steps are:

  1. Enter the theme directory in a terminal.
  2. Install Tailwind without creating a new package.json—the theme already has one:
npm install tailwindcss --save-dev
  1. Add a Tailwind configuration file:
npx tailwindcss init
  1. Copy the existing style.css to tailwind.css and prepend the @tailwind directives.
/* The WordPress theme file header goes here. */

@tailwind base;

/* All of the existing CSS goes here. */

@tailwind components;
@tailwind utilities;

Position the base layer directly after the theme header so the header stays recognizable while the reset lands as early as possible. Existing theme CSS comes next so it overrides the reset; components and utilities sit last because they should win specificity ties.

Compile with the same CLI command:

npx tailwindcss -i ./tailwind.css -o ./style.css --watch

Rendering differences versus the original theme will appear, caused by the reset going further than classic theme CSS expects. In Twenty Twenty-One the only necessary fix was restoring text-decoration-line: underline on a elements. Then the header banner component from Tailwind UI can be pasted into header.php right after the “Skip to content” link:

Showing a Tailwind CSS component on the front end of a WordPress theme.

To let utility classes override higher-specificity theme rules, enable important utilities in the configuration:

module.exports = {
  important: true,
  content: ["./**/*.php"],
  theme: {
    extend: {},
  },
  plugins: [],
}

The important option is not usually enabled in production builds, but powering through a legacy theme conversion is precisely where it earns its keep. With a no-underline utility on the learn-more link and bg-transparent plus border-0 on the dismiss button, the component sits cleanly inside the theme’s look.

A faster starting point

New themes will follow the minimal example’s pattern but typically wrap the CLI in npm scripts for separate watch, development, and production builds—and possibly a dedicated editor build. Two ready-made options exist for teams wanting more scaffolding:

  • _tw, a Tailwind-optimized WordPress starter theme inspired by Underscores, generates a theme with Tailwind wired in from the start and no opinionated styles.
  • Sage, for teams already adopting Laravel Blade templates, offers an official Tailwind setup guide.

Whichever route fits, the practical takeaway is unchanged: committing editor utility classes in advance is required, and Tailwind’s reset will demand small fixes to legacy CSS. The payoff is faster theming with styles that stay small by construction.