Unused CSS classes are included in the output.css when converting Tailwind classes to native CSS.
The error occurs when using Tailwind CLI.
The error occurs when using PostCSS & TailwindCSS together.
Example file:
@import "tailwindcss";
<div class="text-center text-red-500 font-bold text-[2rem] lg:text-[4rem] lg:text-left md:hover:first:text-blue-500 space-y-6">
Hello, World!
</div>
Result in both cases (2763 lines):
@layer theme {
:root, :host {
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
--color-red-500: oklch(.637 .237 25.331);
--color-blue-500: oklch(.623 .214 259.815);
--spacing: .25rem;
--font-weight-bold: 700;
--ease-in: cubic-bezier(.4, 0, 1, 1);
--ease-out: cubic-bezier(0, 0, .2, 1);
--ease-in-out: cubic-bezier(.4, 0, .2, 1);
--default-transition-duration: .15s;
--default-transition-timing-function: cubic-bezier(.4, 0, .2, 1);
--default-font-family: var(--font-sans);
--default-font-feature-settings: var(--font-sans--font-feature-settings);
--default-font-variation-settings: var(--font-sans--font-variation-settings);
--default-mono-font-family: var(--font-mono);
--default-mono-font-feature-settings: var(--font-mono--font-feature-settings);
--default-mono-font-variation-settings: var(--font-mono--font-variation-settings);
}
}
@layer base, components;
@layer utilities {
*, :after, :before, ::backdrop {
box-sizing: border-box;
border: 0 solid;
margin: 0;
padding: 0;
}
::file-selector-button {
box-sizing: border-box;
border: 0 solid;
margin: 0;
padding: 0;
}
/* ... */
.\@container, .\@container-\[inline-size\] {
container-type: inline-size;
}
.pointer-events-auto {
pointer-events: auto;
}
/* ... */
.not-sr-only {
clip: auto;
white-space: normal;
width: auto;
height: auto;
margin: 0;
padding: 0;
position: static;
overflow: visible;
}
}
Built on top of modern-normalize, Preflight is a set of base styles for Tailwind projects that are designed to smooth over cross-browser inconsistencies and make it easier for you to work within the constraints of your design system.
The documentation lists all the validated CSS settings that the preflight.css injects into the output.
This configuration by default adds extra CSS settings to the result. This is not bad, but if it's not needed, you should remove the preflight.css
from the multiple lines of code injected by @import "tailwindcss";
.
/* instead of @import "tailwindcss"; */
@layer theme, base, components, utilities;
@import "tailwindcss/theme.css" layer(theme);
/* @import "tailwindcss/preflight.css" layer(base); # remove this for disable preflight */
@import "tailwindcss/utilities.css" layer(utilities);
For the TailwindCSS v4 engine, we do not need to specify the sources we use. It automatically finds them. However, it may also search in the node_modules
folder, where it can "incorrectly" detect classes that it assumes we are using. This is how unused classes can end up in the output.
The detection, however, takes into account the rules listed in the .gitignore
file and ignores the paths that are blocked there. Therefore, it is always a good idea to create a .gitignore
and block node_modules
in it:
/node_modules/
But you can still specify individual sources using the @source
directive.
When importing tailwindcss
, you have the option to specify the source. You can provide a specific source, or use "none"
to exclude everything. Later, you can expand the list of sources with the @source
directive.
@import "tailwindcss" source(none);
@source "../admin";
@source "../shared";
@import "tailwindcss" source("../src");
- TailwindCSS v4 Docs@import "tailwindcss" source(none);
- TailwindCSS v4 DocsUse at least version v4.0.5 to ensure that only unused CSS variables are included in the output after the fix in the next PR.
@theme static
directiveWhile CSS variables written inside @theme { ... }
will only be included in the output if they are used, we have the option to use @theme static { ... }
, where variables written inside will always be statically included in the output.
Extra: Make sure that the file where you declare the @theme
variables is also excluded from discovery. I did this in a JS file for PostCSS, and it ended up in the TailwindCSS discovery process, which detected that I was using the CSS variable and kept it in the final result.
@theme
directive - TailwindCSS v4 Docs