I added a new timeline to the About page of a theme I was working on, deployed it, and opened the live page. It was a mess: the timeline dots overlapped the year labels, and the vertical line meant to connect them was gone entirely. Locally, everything had looked correct.
The code passed php -l. It passed code review — the class names "looked right." But in production, these classes did nothing:
<div class="relative pl-16">
<span class="absolute left-[20px] w-[2px] h-full bg-neutral-300"></span>
<span class="absolute left-[14px] h-7 w-7 rounded-full bg-black"></span>
<span class="text-sm text-neutral-500">2024</span>
</div>pl-16, left-[20px], w-[2px], h-7 — all valid Tailwind. So why no effect?
Root cause: Tailwind is compiled at build time, not in the browser
This is what I missed. The theme bundles a precompiled tailwind-compiled.css file. Tailwind is not computed in the browser — no CDN JIT, no runtime scanner. That CSS file is a static snapshot of every utility class that existed the last time someone ran the compiler.
The consequence is blunt: any class not already present in tailwind-compiled.css does nothing. The browser sees class="pl-16", looks for .pl-16 in the stylesheet, doesn't find it, and stays silent. No error, no warning — the class just has no effect.
That's why the dots overlapped (without pl-16 there's no left padding to push the content over) and the vertical line disappeared (w-[2px] and left-[20px] were never compiled, so the span had no width and was invisible).
Second symptom: a footer logo blew up to full container width
The same deploy had a downstream bug that briefly confused me. I added a footer logo with a brand-new h-7 class:
<img src="/logo.svg" class="h-7" alt="Logo">What should have been 28px (h-7) instead blew up to the full container width — around 1200px. The cause was two things combined:
h-7wasn't in the compiled file, so my requested height was ignored.- Tailwind's preflight (which is in the compiled file) sets
img { max-width: 100%; height: auto; }. That reset overrides the HTMLwidth/heightattributes on the image, so it stretched to fill its container.
So the image lost the height I asked for but still got the reset that expanded it. Worst of both worlds.
The fix: recompile before deploy, then verify
The real fix is treating recompilation as a mandatory build step, not an optional one:
npx @tailwindcss/cli -i assets/css/input.css -o assets/css/tailwind-compiled.cssThen prove the new class actually made it into the output before uploading:
grep -n "pl-16" assets/css/tailwind-compiled.css
grep -n "h-7" assets/css/tailwind-compiled.cssIf grep finds nothing, the class isn't there — and the deploy will break exactly as before. Finally, make sure tailwind-compiled.css is in your upload list. More than once I recompiled correctly and then forgot to upload the CSS file, so the server kept serving the old version.
For one-off images like the footer logo, there's a shortcut that sidesteps the compile dependency entirely — inline styles:
<img src="/logo.svg"
style="height:32px;width:auto;display:block"
alt="Logo">Inline styles have higher specificity than preflight and don't depend on any compiled utility class at all. For a critical element or two, this is more robust than hoping the right class got compiled in.
Checklist for "my Tailwind classes don't work in production"
- Check whether the theme uses a precompiled Tailwind stylesheet. If there's a bundled
tailwind-compiled.css(or similar), Tailwind isn't computed in the browser. grepthe missing class in the compiled file. Not found = that's your bug.- Recompile:
npx @tailwindcss/cli -i input.css -o tailwind-compiled.css. grepagain to confirm the class now exists.- Add the compiled CSS file to your upload list — recompiling isn't enough if the file never ships.
- For images, watch out for preflight.
img { max-width:100%; height:auto }can override your attributes; use inline styles for critical ones.
Lesson
With a precompiled Tailwind stylesheet, a new class only exists if you recompiled. "It's in the JSX/PHP" guarantees nothing — the browser never sees your JSX/PHP, only that static CSS file. A green php -l and a passing code review won't catch this, because the bug isn't in the source code — it's in the build step you skipped. Make recompile-then-grep part of the deploy, not an afterthought.
