How to Scope Tailwind CSS Styles (Including Preflight)

Updated

5 min read

How to Scope Tailwind CSS Styles (Including Preflight)

Here's a short guide on how to scope Tailwind CSS styles, including preflight styles. I'll share 3 methods for scoping Tailwind styles, depending on your needs.

Why might you want to scope Tailwind CSS styles?

Let's say you have an existing or legacy website that you're working on.

This website uses traditional stylesheets and perhaps BEM naming conventions.

But now, you want to hop on the Tailwind train because of its developer experience, speed, and lack of the class naming problem.

If you were to simply add Tailwind CSS to your existing website, the preflight base styles may overwrite your existing styles, or Tailwind classes may conflict with your existing classes.

Instead of applying Tailwind to your entire site, you'd want to scope it to certain pages or components.

How to Scope Tailwind CSS Styles

Method 1. PostCSS

The first method to scope scope Tailwind styles is using a PostCSS plugin.

Note

PostCSS is a "CSS post-processor," often used in conjunction with Tailwind CSS. If you're using Next.js for example, PostCSS is already included in the build pipeline.

First, install postcss-nested:

npm i -D postcss postcss-nested

Then add the plugin to your postcss.config.js:

javascript// postcss.config.js

module.exports = {
    plugins: [
      require('tailwindcss'),
      require('autoprefixer'),
      require("postcss-nested"),
    ],
  };

The postcss-nested plugin will unwrap nested styles, similar to a Sass or SCSS syntax.

Once installed, you can modify your main.css like so:

css/* main.css (or global.css) */

.tailwind {
    @tailwind base;
    @tailwind components;
    @tailwind utilities;
}

Now, Tailwind classes will be scoped to a parent element with the .tailwind classname. This will prevent Tailwind styles from affecting the rest of your site.

Method 2. CSS Modules

The second method for scoping Tailwind styles involves using CSS Modules.

Note

This method isn't as flexible as the PostCSS method, because it requires refactoring your code, as we'll see.

But it is convenient, because Next.js and Create React App support CSS Modules out of the box.

To start, we may have a component like:

javascript// Button.tsx

export default Button() {
  return (
    <button className="px-2 py-1 text-base text-gray-500 border border-solid border-gray-200"></button>
  );
}

To use CSS modules to scope these Tailwind classes, we simply need to create a CSS file with the same name as the component file, but with a .module.css extension and use the @apply directive:

css/* Button.module.css */

.button {
  @apply px-2 py-1 text-base text-gray-500 border border-solid border-gray-200;
}

Now we can refactor our component to use the CSS module:

javascript// Button.tsx

import styles from "./Button.module.css"; // import the CSS module

export default Button() {
  return (
    <button className={styles.button}></button>
  );
}

When we build our project, the CSS module will be transformed into a unique classname, scoped to the component.

So classes like px-2 or text-base won't conflict with other classes in your project.

Method 3. Tailwind CSS Prefix

The final method for scoping Tailwind styles is to use the prefix option in your tailwind.config.js.

This method also requires refactoring your code, but it's a simple way to scope Tailwind classes.

Simply update your tailwind.config.js to include a custom prefix:

javascript// tailwind.config.js

/** @type {import('tailwindcss').Config} */
module.exports = {
  prefix: 'tw-',
}

Now all Tailwind classes will be automatically generated with a tw- prefix.

html<button class="tw-px-2 tw-py-1 tw-text-base tw-text-gray-500 tw-border tw-border-solid tw-border-gray-200"></button>

Method 4. Scope Tailwind Preflight Styles

In the examples above, all Tailwind styles would be scoped to the specified classname.

But what if you only want to scope the Tailwind preflight styles?

Note

Preflight styles (the base styles that reset margins, unstyle headings/lists, etc.) are injected into "@tailwind base".

Maybe you want Tailwind utility classes (e.g. text-blue-500) to be applied globally in your project, but the Tailwind preflight to be scoped.

First, disable preflight styles by modifying your tailwind.config.js:

javascript/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
    "./src/**/*.{ts,tsx}",
    // ...
  ],
  theme: {
    extend: {},
  },
  plugins: [],
  important: true,
  corePlugins: {
    preflight: false, // disable preflight styles
  },
}

Next, modify your main.css like so:

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

.tailwind {
    /* Here we will paste in preflight.css */
}

Now we'll use a bit of a hack, which is copy/pasting the preflight.css file contents into our scoped selector.

Navigate to node_modules > tailwindcss > lib > css > preflight.css.

Copy the contents of preflight.css and paste them into the scoped selector in your main.css as shown above.

Here's a gist which also contains the styles for your convenience.

And that's it! Now your preflight styles will be scoped to any .tailwind parent elements, while all other Tailwind CSS styles will be applied globally.

Wrapping Up

You may want to scope Tailwind CSS styles to avoid conflicts or overwriting existing legacy classes.

To scope Tailwind classes, including preflight styles, you have 3 methods at your disposal:

  1. Use PostCSS and postcss-nested
  2. Use CSS Modules with .module.css files
  3. Use the prefix option in your tailwind.config.js

And if you only want to scope preflight styles, you can disable preflight in your tailwind.config.js and copy/paste the contents of preflight.css into a scoped selector in your main.css.

I hope this guide was helpful! As always if you have any questions or feedback, feel free to reach out.

Ryan Chiang

Meet the Author

Ryan Chiang

Hello, I'm Ryan. I build things and write about them. This is my blog of my learnings, tutorials, and whatever else I feel like writing about.
See what I'm building →.

Thanks for reading! If you want a heads up when I write a new blog post, you can subscribe below:

2024

2023

© 2023 Ryan Chiang|ryanschiang.com