This episode covers optimizing Tailwind CSS performance: efficient content configuration for JIT, critical CSS and split CSS techniques to reduce render-blocking, and analyzing bundle size with source-map-explorer and other analyzers.

Tailwind is already economical by default: JIT only generates classes that are used. But in large projects, the quality of your content configuration and serving strategy still decides the outcome. Episode 14 covers performance optimization: efficient content, critical CSS, split CSS, and bundle size analysis.
Every kilobyte of CSS delays first render. Our goal: make sure the CSS you ship is only what that page needs, at the right time, and measurable over time so it doesn't silently balloon.
JIT scans the files in content and generates every class it finds. Content that's too broad — for example including node_modules or the whole repo — slows the build and can produce unwanted classes. Always narrow it:
module.exports = {
content: [
"./index.html",
"./src/**/*.{html,js,ts,jsx,tsx}",
"./src/**/*.{vue,svelte,astro}",
],
};One source of class names is enough. Don't include dist or node_modules files:
node_modules/** -> jangan
dist/** -> jangan
src/**/*.map -> janganThe glob pattern ./src/**/*.{html,js,ts,jsx,tsx} is a good example: narrow, clear, and covering all files that contain markup.
Above-the-fold CSS is delivered first so first paint is fast. A common approach: inline critical CSS in the head and load the rest asynchronously:
<style>/* critical CSS yang di-inline */</style>
<link rel="stylesheet" href="/css/rest.css" media="print" onload="this.media='all'" />media="print" prevents the browser from blocking render on files it doesn't need yet, then onload switches it to all once loaded. This drastically reduces render-blocking.
For SPAs or multi-page sites, split CSS per route/bundle. Utilities only used on the admin page shouldn't be shipped to the public page. In frameworks like Next.js, per-page CSS imports are split automatically; in frameworkless projects, run separate builds:
npx tailwindcss -i src/styles.css -o dist/public.css --content ./public/**/*.html
npx tailwindcss -i src/admin.css -o dist/admin.css --content ./admin/**/*.htmlEach page only receives CSS for the classes it actually uses.
Size you don't measure can't be optimized. Analysis tools:
--analyze flag to see which utilities contribute most.@next/bundle-analyzer for frameworks.Example of using the analyze flag:
npx tailwindcss -i src/styles.css -o dist/output.css --analyzeIts output shows the largest utilities — usually because of variant combinations like hover:, md:, and dark: that multiply declarations.
Tip
Watch out for utilities generated in large quantities because of variant combinations. A single text-xs in markup can become dozens of CSS lines after multiplying across variants and breakpoints. Limit the variants you actually use.
Optimization isn't a one-time event. Every new feature can add utilities, variants, or arbitrary values that were never imagined when the initial config was written. So make measurement part of your workflow, not an exception done just before release.
A few habits that keep CSS lean in a growing project:
--analyze periodically, for example each release, and record the output size as a baseline you can compare between versions.With regular measurement, CSS growth becomes a conscious decision rather than invisible accumulation. The team knows when to tidy up old utilities, when a new utility is worth adding, and when split CSS needs reworking because usage patterns changed. Whenever the team successfully cuts size, record the reason so that good habit can be replicated elsewhere.
As a guideline, a healthy target is keeping total CSS under the budget threshold and pages not waiting on a large stylesheet before first render.
Both numbers can be monitored automatically; once monitoring is running, optimization is no longer a guess but a data-driven decision.
Episode 14 sharpened performance: narrow content keeps JIT efficient, critical CSS and split CSS reduce render-blocking, and analysis tools keep size growth in view.
Key takeaways:
content to files that actually contain class names.node_modules or build directories in content.--analyze shows the largest utilities in the output.Next, in episode 15, we'll cover component API patterns — introducing class-variance-authority for variant-based components, the utility wrapper pattern using clsx and tailwind-merge, and testing class output in unit tests.