When I run the build
script in my svelte kit tailwind project, with Tailwind v4, it add every single tailwind color. I only use one single tailwind color, so I'd like to remove them.
I spent a while searching online and asking LLMs, and nothing has an answer for tailwind v4 which is config-less.
Here's my app.css
@import 'tailwindcss';
@theme {
--color-brand-red: #f00;
}
@utility container {
padding-inline: 1rem;
margin-inline: auto;
}
Here's my package.json:
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check . && eslint ."
},
"devDependencies": {
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@sveltejs/adapter-auto": "^4.0.0",
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/vite": "^4.0.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^2.46.1",
"globals": "^15.14.0",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^4.0.0",
"typescript": "^5.0.0",
"typescript-eslint": "^8.20.0",
"vite": "^6.0.0"
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
},
"dependencies": {
"lucide-svelte": "^0.475.0"
}
Yet when I run pnpm build
I get a css file with:
/*! tailwindcss v4.0.6 | MIT License | */@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-serif:ui-serif,Geia,Cambria,"Times New Roman",Times,serif;--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(.971 .013 17.38);--color-red-100:oklch(.936 .032 17.717);--color-red-200:oklch(.885 .062 18.334);--color-red-300:oklch(.808 .114 19.571);--color-red-400:oklch(.704 .191 22.216);--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-red-700:oklch(.505 .213 27.518);--color-red-800:oklch(.444 .177 26.899);--color-red-900:oklch(.396 .141 25.723);--color-red-950:oklch(.258 .092 26.042);--color-orange-50:oklch(.98 .016 73.684);--color-orange-100:oklch(.954 .038 75.164);--color-orange-200:oklch(.901 .076 70.697);--color-orange-300:oklch(.837 .128 66.29);--color-orange-400:oklch(.75 .183 55.934);--color-orange-500:oklch(.705 .213 47.604);--color-orange-600:oklch(.646 .222 41.116);--color-orange-700:oklch(.553 .195 38.402);--color-orange-800:oklch(.47 .157 37.304);--color-orange-900:oklch(.408 .123 38.172);--color-orange-950:oklch(.266 .079 36.259);--color-amber-50:oklch(.987 .022 95.277);--color-amber-100:oklch(.962 .059 95.617);--color-amber-200:oklch(.924 .12 95.746);--color-amber-300:oklch(.879 .169 91.605);--color-amber-400:oklch(.828 .189 84.429);--color-amber-500:oklch(.769 .188 70.08);--color-amber-600:oklch(.666 .179 58.318);--color-amber-700:oklch(.555 .163 48.998);--color-amber-800:oklch(.473 .137 46.201);--color-amber-900:oklch(.414 .112 45.904);--color-amber-950:oklch(.279 .077 45.635);--color-yellow-50:oklch(.987 .026 102.212);--color-yellow-100:oklch(.973 .071 103.193);--color-yellow-200:oklch(.945 .129 101.54);
And so on. This file is 28kb and I have very few unique tailwind classes I'm using.
I searched their official docs and they only have docs on this for v2 it seems. Is there a way to edit my app.css
to remove all unused colors? Thanks.
When I run the build
script in my svelte kit tailwind project, with Tailwind v4, it add every single tailwind color. I only use one single tailwind color, so I'd like to remove them.
I spent a while searching online and asking LLMs, and nothing has an answer for tailwind v4 which is config-less.
Here's my app.css
@import 'tailwindcss';
@theme {
--color-brand-red: #f00;
}
@utility container {
padding-inline: 1rem;
margin-inline: auto;
}
Here's my package.json:
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"prepare": "svelte-kit sync || echo ''",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"format": "prettier --write .",
"lint": "prettier --check . && eslint ."
},
"devDependencies": {
"@eslint/compat": "^1.2.5",
"@eslint/js": "^9.18.0",
"@sveltejs/adapter-auto": "^4.0.0",
"@sveltejs/kit": "^2.16.0",
"@sveltejs/vite-plugin-svelte": "^5.0.0",
"@tailwindcss/vite": "^4.0.0",
"eslint": "^9.18.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-svelte": "^2.46.1",
"globals": "^15.14.0",
"prettier": "^3.4.2",
"prettier-plugin-svelte": "^3.3.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"svelte": "^5.0.0",
"svelte-check": "^4.0.0",
"tailwindcss": "^4.0.0",
"typescript": "^5.0.0",
"typescript-eslint": "^8.20.0",
"vite": "^6.0.0"
},
"pnpm": {
"onlyBuiltDependencies": [
"esbuild"
]
},
"dependencies": {
"lucide-svelte": "^0.475.0"
}
Yet when I run pnpm build
I get a css file with:
/*! tailwindcss v4.0.6 | MIT License | https://tailwindcss */@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-serif:ui-serif,Geia,Cambria,"Times New Roman",Times,serif;--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--color-red-50:oklch(.971 .013 17.38);--color-red-100:oklch(.936 .032 17.717);--color-red-200:oklch(.885 .062 18.334);--color-red-300:oklch(.808 .114 19.571);--color-red-400:oklch(.704 .191 22.216);--color-red-500:oklch(.637 .237 25.331);--color-red-600:oklch(.577 .245 27.325);--color-red-700:oklch(.505 .213 27.518);--color-red-800:oklch(.444 .177 26.899);--color-red-900:oklch(.396 .141 25.723);--color-red-950:oklch(.258 .092 26.042);--color-orange-50:oklch(.98 .016 73.684);--color-orange-100:oklch(.954 .038 75.164);--color-orange-200:oklch(.901 .076 70.697);--color-orange-300:oklch(.837 .128 66.29);--color-orange-400:oklch(.75 .183 55.934);--color-orange-500:oklch(.705 .213 47.604);--color-orange-600:oklch(.646 .222 41.116);--color-orange-700:oklch(.553 .195 38.402);--color-orange-800:oklch(.47 .157 37.304);--color-orange-900:oklch(.408 .123 38.172);--color-orange-950:oklch(.266 .079 36.259);--color-amber-50:oklch(.987 .022 95.277);--color-amber-100:oklch(.962 .059 95.617);--color-amber-200:oklch(.924 .12 95.746);--color-amber-300:oklch(.879 .169 91.605);--color-amber-400:oklch(.828 .189 84.429);--color-amber-500:oklch(.769 .188 70.08);--color-amber-600:oklch(.666 .179 58.318);--color-amber-700:oklch(.555 .163 48.998);--color-amber-800:oklch(.473 .137 46.201);--color-amber-900:oklch(.414 .112 45.904);--color-amber-950:oklch(.279 .077 45.635);--color-yellow-50:oklch(.987 .026 102.212);--color-yellow-100:oklch(.973 .071 103.193);--color-yellow-200:oklch(.945 .129 101.54);
And so on. This file is 28kb and I have very few unique tailwind classes I'm using.
I searched their official docs and they only have docs on this for v2 it seems. Is there a way to edit my app.css
to remove all unused colors? Thanks.
2 Answers
Reset to default 1My previous tests without Vite
The question is only interesting to me because TailwindCSS doesn't even include unused variables and classes in the first place. So if the goal is to remove "unused" variables, I believe that was solved long ago. There was a bug in TailwindCSS v4 that left them in, but it was quickly fixed, probably in v4.0.5.
It definitely works well in the CLI and with PostCSS. I looked into this in more depth during a native conversion. See:
- Convert TailwindCSS to native CSS by v4 engine
--color-*: initial
, why it's a half-finished solution
I was surprised to find that the issue hasn't been solved in Vite yet. That's probably why you brought up the question. I think the answer you provided doesn't actually solve the problem; it just hides it. Your solution effectively disables the default classes, but if you still add 20 colors and only end up using 3, the build will still include all 20 colors.
Workaround solution to ensure compression: PurgeCSS
I would find it worth reporting the bug. In the meantime, use the PurgeCSS plugin to ensure that all unused variables and classes are removed from the output.
- Get started TailwindCSS with Vite - TailwindCSS v4 Docs
- Get started PurgeCSS by PostCSS - PurgeCSS Docs
Dependencies
npm install tailwindcss @tailwindcss/vite postcss @fullhuman/postcss-purgecss
Configuration
vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import tailwindcss from '@tailwindcss/vite'
import { purgeCSSPlugin } from '@fullhuman/postcss-purgecss'
// Custom PostCSS plugin to remove comments
const removeCommentRules = (root: any) => {
root.walkComments((comment: any) => {
comment.remove()
})
}
// https://vite.dev/config/
export default defineConfig({
plugins: [
vue(), // I know you're using Svelte, so naturally, replace the relevant configurations, but the important part is really just PurgeCSS.
tailwindcss(),
],
css: {
postcss: {
plugins: [
purgeCSSPlugin({
content: [
'./**/*.html',
'./**/*.js',
'./**/*.jsx',
'./**/*.ts',
'./**/*.tsx',
],
defaultExtractor: content => content.match(/[\w-/:.\[\]\(\)_\[\]]+(?<!:)/g) || [],
variables: true, // Remove unused CSS variables
keyframes: true, // Remove unused animations
fontFace: true, // Remove unused font faces
}),
removeCommentRules,
]
}
}
})
style.css
@import 'tailwindcss';
/* ... */
Test
npm run build
The result went from 18KB to 4KB. This can be further optimized if you don't need other parts in the output, as mentioned in the linked TailwindCSS to nativeCSS post.
Tested steps
- Disabling automatic source detection with
source(none)
-> Not a good result (18kb with unused variables) - Excluding files and directories from automatic source detection with
.gitignore
-> Not a good result (18kb with unused variables) - Using
@tailwindcss/postcss
plugin instead of the more compatible vite plugin -> Not a good result (18kb with unused variables) - Using
@tailwindcss/postcss
plugin andpurgecss
-> not recommended for Vue projects, would work without Vite (Specific error due to Vue; It probably would have worked in a native JavaScript Vite project; But it's no coincidence that we have a Vite-specific plugin from TailwindCSS.) - Using
@tailwindcss/vite
plugin andpurgecss
-> successful (4kb without unused variables)
v4-related content
tailwindlabs/tailwindcss
PR #16211 - fix: only expose used CSS variable - GitHub- Automatic Source Detection - StackOverflow
- Setting your base path:
@import "tailwindcss" source("../src");
- TailwindCSS v4 Docs - Disable automatic detection:
@import "tailwindcss" source(none);
- TailwindCSS v4 Docs - Unused classes and variables are included in the native CSS output of Tailwind - StackOverflow
Why can't exclude files from TailwindCSS when using Vite?
When using
@tailwindcss/vite
, Tailwind uses the Vite module graph to scan code for class names, rather than the file system huelistics (when not using@tailwindcss/vite
). Thus these other class names might be appearing in some compiled code.You may be able to switch to the file-based scanning in Vite once
tailwindlabs/tailwindcss PR #16425
is in.
Thanks for @Wongjn!
I figured it out. Add:
--color-*: initial;
above the custom defined colors
https://tailwindcss/docs/theme#overriding-the-default-theme