Tailwind CSS
CVA works great with Tailwind CSS, but does not require it. You can use CVA with any utility-class library, or none at all. If you are using Tailwind, the sections below walk through IntelliSense setup, conflict resolution, and the Prettier plugin.IntelliSense
Tailwind’s language server supports aclassFunctions option that enables autocompletion and hover previews inside any function you name — including cva and cx.
- VS Code
- Zed
- Neovim
- WebStorm
Install the extension
Install the Tailwind CSS IntelliSense extension from the VS Code Marketplace.
Add classFunctions to settings.json
Open your
settings.json and add:.vscode/settings.json
Handling style conflicts
Tailwind applies styles based on the order classes appear in your stylesheet, not the order they appear in theclass attribute. This means two conflicting utilities — for example p-2 and p-4 — will not resolve predictably when merged at runtime.
CVA’s variant API is designed to minimise these situations, but they can still occur when a consumer passes extra classes via the class or className prop.
The tailwind-merge package resolves these conflicts by keeping only the last conflicting utility in the string.
Global setup with defineConfig
The cleanest approach is to configure tailwind-merge once using defineConfig and re-export the resulting cva, cx, and compose from a single module. Every component that imports from that module gets conflict resolution for free.
lib/utils.ts
cva directly:
components/button.ts
Per-component setup
If you prefer to applytailwind-merge only to specific components, wrap the CVA call manually:
components/button.ts
Prettier plugin
prettier-plugin-tailwindcss automatically sorts Tailwind classes. It supports the same classFunctions option as the language server, so you can configure it to sort classes inside cva and cx calls:
.prettierrc
The Prettier plugin option is named
tailwindFunctions, not classFunctions. Check the plugin documentation for the current option name.