Summary
This postmortem analyzes why integrating TailwindCSS 4 into StencilJS via PostCSS fails when following the official Tailwind documentation. Although both tools are mature, their configuration expectations differ in subtle but critical ways. The failure stems from a mismatch between Stencil’s build pipeline and Tailwind’s PostCSS plugin loading model.
Root Cause
The root cause is Stencil’s nonstandard PostCSS execution model, which does not automatically load PostCSS plugins from a postcss.config.mjs file the way Tailwind’s documentation assumes.
Key issues:
- Stencil does not read
postcss.config.mjsby default. - TailwindCSS 4 uses a new PostCSS plugin entrypoint (
@tailwindcss/postcss) that Stencil does not automatically detect. - CSS imports such as
@import "tailwindcss";fail because Tailwind’s processor never runs. - Stencil requires explicit PostCSS configuration inside
stencil.config.ts, not a standalone PostCSS config file.
Why This Happens in Real Systems
This class of failure is extremely common in real-world build pipelines because:
- Frameworks often wrap or override PostCSS, preventing standard plugin discovery.
- Plugin ecosystems evolve faster than framework integrations, creating version mismatches.
- Documentation assumes a default PostCSS environment, which Stencil does not provide.
- CSS tooling is highly order‑dependent, so a missing plugin silently breaks the entire chain.
Real-World Impact
When Tailwind is not actually executed inside Stencil’s pipeline:
- Utility classes do not appear in output CSS
- Components render unstyled, even though the CSS imports look correct
- Hot reload shows no errors, making debugging harder
- Developers waste hours chasing “invisible” configuration issues
Example or Code (if necessary and relevant)
Below is the correct minimal working setup for TailwindCSS 4 + StencilJS using PostCSS.
stencil.config.ts
import { Config } from '@stencil/core';
import postcss from '@stencil/postcss';
import tailwind from '@tailwindcss/postcss';
export const config: Config = {
plugins: [
postcss({
plugins: [tailwind()],
}),
],
};
postcss.config.mjs (optional, not required)
export default {
plugins: {
'@tailwindcss/postcss': {},
},
};
Component stylesheet
@import "tailwindcss";
How Senior Engineers Fix It
Experienced engineers recognize the pattern immediately and fix it by:
- Inspecting the actual build pipeline, not the documentation
- Verifying whether the framework loads PostCSS configs automatically
- Injecting Tailwind directly into Stencil’s PostCSS plugin array
- Checking plugin execution order, ensuring Tailwind runs before other transforms
- Removing redundant configs that Stencil ignores
They treat the problem as a pipeline integration issue, not a Tailwind issue.
Why Juniors Miss It
Junior engineers typically miss this because:
- They assume all frameworks load PostCSS the same way
- They trust the Tailwind documentation as universal, not realizing Stencil is an exception
- They expect errors or warnings, but Stencil fails silently
- They don’t yet know that CSS tooling is order‑sensitive
- They rarely inspect the actual compiled output, relying instead on assumptions
The gap is not about skill but about experience with build systems and plugin orchestration.