Tailwind CSS v3 + HTML Static - Class Obfuscation Guide ​
Overview ​
This guide covers class obfuscation for static HTML projects using Tailwind CSS v3. This approach uses tailwindcss-patch for class extraction and unplugin-tailwindcss-mangle for obfuscation.
Architecture ​
tailwind.config.js → tailwindcss-patch → .tw-patch/tw-class-list.json
↓
src/*.html → Vite build → unplugin-tailwindcss-mangle → dist/
src/*.css (obfuscated)Dependencies ​
json
{
"dependencies": {
"autoprefixer": "^10.4.20",
"postcss": "^8.4.49",
"tailwindcss": "^3.4.17",
"vite": "^6.0.5"
},
"devDependencies": {
"tailwindcss-patch": "^3.0.1",
"unplugin-tailwindcss-mangle": "^5.0.0"
}
}Configuration Files ​
tailwind.config.js ​
javascript
export default {
content: ["./src/**/*.{html,js,ts,jsx,tsx}"],
darkMode: "class",
theme: {
extend: {
colors: {
primary: "#3b82f6",
secondary: "#8b5cf6",
},
},
},
plugins: [],
};postcss.config.js ​
javascript
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
};tailwindcss-mangle.config.ts ​
typescript
import { defineConfig } from "@tailwindcss-mangle/config";
export default defineConfig({
registry: {
output: {
file: ".tw-patch/tw-class-list.json",
},
},
transformer: {
registry: {
file: ".tw-patch/tw-class-list.json",
},
generator: {
classPrefix: "tw-",
},
},
});vite.config.js ​
javascript
import { defineConfig } from "vite";
import { resolve } from "path";
import tailwindcssMangle from "unplugin-tailwindcss-mangle/vite";
export default defineConfig(({ mode }) => ({
root: "src",
plugins: [mode === "production" && tailwindcssMangle()].filter(Boolean),
build: {
outDir: "../dist",
emptyOutDir: true,
rollupOptions: {
input: {
main: resolve(__dirname, "src/index.html"),
about: resolve(__dirname, "src/about.html"),
},
},
},
}));CSS File (src/styles.css) ​
css
@tailwind base;
@tailwind components;
@tailwind utilities;
@layer components {
.btn {
@apply rounded-lg px-4 py-2 font-medium transition-colors;
}
.btn-primary {
@apply bg-primary hover:bg-primary/90 text-white;
}
}Package.json Scripts ​
json
{
"scripts": {
"postinstall": "tw-patch install",
"dev": "vite",
"build": "tw-patch extract && vite build",
"extract-classes": "tw-patch extract"
}
}Build Process ​
- postinstall:
tw-patch installpatches the Tailwind package to enable class extraction - extract:
tw-patch extractscans your files and generates.tw-patch/tw-class-list.json - build: Vite builds the project, and
unplugin-tailwindcss-manglereplaces classes
Result ​
Before (Development) ​
html
<div class="rounded-lg bg-blue-500 p-4 text-white hover:bg-blue-700">Button</div>After (Production) ​
html
<div class="tw-a tw-b tw-c tw-d tw-e">Button</div>Troubleshooting ​
Classes not being obfuscated ​
- Check that
.tw-patch/tw-class-list.jsonexists and contains your classes - Ensure you're building in production mode:
npm run build(notvite builddirectly) - Verify
tailwindcss-mangle.config.tspoints to the correct JSON file
Some classes missing ​
- Ensure all HTML files are listed in
tailwind.config.jscontent paths - Check for dynamic class construction (not supported)
- Verify CSS
@applydirectives are being scanned
Limitations ​
- Only static classes are obfuscated
- Dynamic class construction (
bg-${color}-500) will NOT work - Third-party component classes are not obfuscated