If Tailwind CSS IntelliSense isn’t working in your VS Code setup — no autocomplete, no hover previews, no color swatches — it’s almost never that the extension is “broken.” It’s usually that it can’t find your config, or it doesn’t know your file type counts as something it should scan. I’ve hit this on a fairly standard Turborepo setup and also on a single Astro project, and the causes were completely different both times.
Let’s go through why this happens and the actual fixes, not just “reinstall the extension” which, spoiler, rarely does anything.
Quick Answer
- Check that
tailwind.config.js(or.ts,.cjs) is detected — in monorepos it often isn’t, because the extension looks relative to the open folder - Add
tailwindCSS.experimental.configFileif you’ve got a non-standard config location - Register custom file extensions under
tailwindCSS.includeLanguages(Astro, MDX, Vue, custom.tsxwrappers) - If you’re using
clsx,cva, or similar, add them totailwindCSS.classAttributes/ class regex settings - In multi-root workspaces, settings need to live per-folder, not just at the workspace root — this one catches people constantly
Why Tailwind IntelliSense Fails
There’s rarely one single cause. From what I’ve seen, it’s usually one of these, sometimes stacked on top of each other.
1. The extension can’t locate your Tailwind config. By default, the extension looks for tailwind.config.js (or .cjs, .ts, .mjs) somewhere in the workspace, walking up from the file you’re editing. In a monorepo with an apps/ and packages/ structure, your config might live two or three directories away from the component you’re working in, and the extension just doesn’t walk that far by default in some setups.
2. VS Code doesn’t recognize the file’s language ID. This is a big one for anyone using Astro, MDX, Vue SFCs, or custom wrapper components. Tailwind IntelliSense only scans languages it’s told to scan. If your .astro files are somehow being treated as plain text or an unrecognized language ID (which happens more than you’d think with certain VS Code + extension version combos), Tailwind IntelliSense silently ignores them.
3. node_modules isn’t installed, or isn’t installed where the extension expects. The extension actually needs to resolve your local Tailwind install to read your config and generate suggestions. In a monorepo using workspaces (pnpm, yarn, npm workspaces), the actual Tailwind package might be hoisted to the root node_modules, and depending on how the extension resolves modules, that can trip things up — especially with pnpm’s stricter, non-flat node_modules structure.
4. Custom class helper functions aren’t recognized. If you’re wrapping classes in clsx(), cva(), cn(), or a custom utility, IntelliSense won’t autocomplete inside those calls unless you tell it to look there. Out of the box it recognizes className and class attributes — anything wrapped in a function call needs an explicit regex or attribute config.
5. Workspace settings not applying per-folder in multi-root setups. If you’ve got a multi-root workspace (multiple folders open in one VS Code window, common in monorepos), settings defined at the top-level workspace file don’t always cascade the way people expect. Each folder can need its own scoped settings.
Common Scenarios
- Turborepo / Nx monorepo — config detection issues are the most common complaint here, since the Tailwind config often lives in a shared package, not each app folder
- Astro projects — usually a
files.associationsorincludeLanguagesissue, since.astroisn’t natively recognized without help - Vue 3 with
<script setup>— sometimes works fine in<template>but not inside dynamically bound classes - Projects using
cva(class-variance-authority) — almost always aclassAttributes/ class regex config gap - pnpm workspaces — module resolution quirks show up more here than with npm or yarn due to pnpm’s stricter node_modules layout
Technical Comparison: Common Causes and Fixes
| Cause | Symptom | Fix | Reliability |
|---|---|---|---|
| Config not found in monorepo | No suggestions anywhere in a sub-package | Set tailwindCSS.experimental.configFile | High |
| Unrecognized file type | Works in .tsx but not .astro/.vue/.mdx | Add to includeLanguages and files.associations | High |
| pnpm hoisting issue | Extension loads but gives no suggestions, no errors | Reinstall in strict mode or add root node_modules alias | Medium — sometimes structural |
Custom class wrapper (cva, clsx) | Class names outside className="" don’t autocomplete | Add classAttributes/classRegex entries | High |
| Multi-root workspace scoping | Works in one folder, not another in same window | Duplicate settings per folder or use .vscode/settings.json inside each | High |
Step-by-Step Fixes
Step 1: Point IntelliSense Directly at Your Config
If your tailwind.config.js lives somewhere non-standard (common in monorepos), tell the extension explicitly in .vscode/settings.json:
json
{
"tailwindCSS.experimental.configFile": "packages/ui/tailwind.config.js"
}If you’ve got multiple configs for multiple apps in the same monorepo, you can map them:
json
{
"tailwindCSS.experimental.configFile": {
"apps/web/tailwind.config.js": "apps/web/**",
"apps/admin/tailwind.config.js": "apps/admin/**"
}
}This one setting alone solves a surprising number of “IntelliSense just doesn’t work” complaints in monorepos.
Step 2: Register Custom Languages
For Astro, Vue, MDX, or anything not natively supported out of the box:
json
{
"tailwindCSS.includeLanguages": {
"astro": "html",
"vue": "html",
"mdx": "markdown"
}
}And make sure VS Code itself recognizes the file extension in the first place:
json
{
"files.associations": {
"*.astro": "astro"
}
}If the Astro (or Vue) extension is installed and up to date, this is usually enough. If it’s not installed at all, that’s your actual problem — Tailwind IntelliSense piggybacks on the base language support, it doesn’t replace it.
Step 3: Fix Custom Class Wrapper Recognition
For cva, clsx, cn, or similar:
json
{
"tailwindCSS.classAttributes": ["class", "className", "ngClass"],
"tailwindCSS.experimental.classRegex": [
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
]
}Regex configs here are genuinely fiddly, and I won’t pretend I got this right on the first try — it took a couple of rounds of tweaking to get cva‘s multi-line variant objects to actually match. Your specific wrapper function’s structure might need a slightly different pattern.
Step 4: Verify Module Resolution in pnpm Workspaces
Check that Tailwind is actually resolvable from the package you’re editing, not just hoisted at the monorepo root:
bash
cd apps/web
node -e "console.log(require.resolve('tailwindcss'))"If this throws instead of returning a path, that’s your problem — the extension is running into the same resolution failure. Adding Tailwind as an explicit dependency in that specific package (even if it’s also at the root) usually clears it up.
Step 5: Scope Settings Correctly in Multi-Root Workspaces
If you’re working across multiple folders in one VS Code window, put settings inside each folder’s own .vscode/settings.json, not only in the .code-workspace file. The workspace-level file doesn’t always cascade cleanly per-folder for extension-specific config, and this inconsistency is honestly one of the more annoying parts of the whole multi-root workspace model.
What Actually Worked For Me
On the Turborepo project, my first move was reinstalling the extension, restarting VS Code, clearing the extension cache — none of it did anything, which in hindsight makes sense since none of that touches config resolution at all. That’s on me for not checking the obvious thing first.
The actual fix was setting tailwindCSS.experimental.configFile explicitly, because the config lived in a shared packages/config folder and the extension had no way of finding it by walking up from apps/web/src/components. Five minutes, one setting, done.
On the Astro project, it was a completely different problem — genuinely just that files.associations wasn’t set, so VS Code didn’t know .astro files were HTML-like at all, and Tailwind IntelliSense had nothing to hook into. Not a Tailwind problem at its core, more a “VS Code doesn’t know what this file is” problem that happened to manifest as missing Tailwind suggestions.
Advanced Fixes and Edge Cases
Check the Output panel for the Tailwind CSS extension. View → Output, then select “Tailwind CSS IntelliSense” from the dropdown. It logs config detection attempts and will tell you outright if it can’t find a config or if it found multiple conflicting ones — this is honestly underused as a debugging step.
Watch for conflicting Tailwind versions across a monorepo. If one package uses Tailwind v3 and another uses v4 syntax (which changed configuration significantly), IntelliSense can get confused about which feature set to suggest, especially if module resolution picks up the wrong version due to hoisting.
Restart the Tailwind CSS server directly, not just VS Code. Command Palette → “Tailwind CSS: Restart IntelliSense Server” — this is faster than a full VS Code restart and fixes stale config caching more often than you’d expect.
Prevention Tips
- Keep a documented
.vscode/settings.jsonper monorepo package if configs genuinely live in different places — don’t rely on everyone rediscoveringexperimental.configFileindependently - Standardize on one class-wrapper pattern (
cva,clsx, or plain strings) per project so the regex config only has to cover one shape - Pin Tailwind versions consistently across a monorepo unless you have a real reason not to
- Install language extensions (Astro, Vue, Svelte) before assuming Tailwind IntelliSense itself is broken — it depends on those
FAQ
Why does Tailwind IntelliSense work in one app of my monorepo but not another? Usually a config path issue specific to that app — check whether experimental.configFile needs a per-app mapping.
Do I need to restart VS Code after changing these settings? Not always. Restarting the IntelliSense server via the command palette is usually enough and faster.
Does this affect Tailwind actually compiling, or just the editor suggestions? Just the editor. Your build pipeline (PostCSS, Vite, whatever) is separate and unaffected by IntelliSense config.
Will upgrading to Tailwind v4 fix IntelliSense issues? Not by itself, and it might introduce new ones if your monorepo has mixed versions during a migration.
Is this different in JetBrains IDEs? Yes, WebStorm and other JetBrains IDEs have their own Tailwind plugin with a different config detection mechanism entirely — this article is VS Code specific.
Editor’s Opinion
Nine times out of ten this comes down to the extension not being able to find your config or not knowing what your file type actually is, not some deep bug in the extension itself. Check the Output panel before doing anything drastic — it usually tells you exactly what’s going wrong if you bother to look. And in a monorepo, just assume you’ll need to point it at your config manually, because auto-detection wasn’t really built with three levels of nested packages in mind.
