Updated
—
5 min read
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.
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.
The first method to scope scope Tailwind styles is using a PostCSS plugin.
NotePostCSS 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.
The second method for scoping Tailwind styles involves using CSS Modules.
NoteThis 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.
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>
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?
NotePreflight 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.
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:
postcss-nested
.module.css
filesprefix
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.
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: