tailwind.config.js
@apply
/ @screen
directives transforms (also works for Vue SFC's <style>
)bg-gray-200 hover:(bg-gray-100 text-red-300)
Check out the speed comparison between Windi CSS and Tailwind CSS on Vite.
Install the package:
npm i -D vite-plugin-windicss windicss
Then, install the plugin in your Vite configuration:
import WindiCSS from 'vite-plugin-windicss'
export default {
plugins: [
WindiCSS(),
],
}
And finally, import virtual:windi.css
in your Vite entries:
import 'virtual:windi.css'
That's it! Starting using classes utilities or CSS directives in your app, and enjoy the speed! ⚡️
If you are migrating from Tailwind CSS, also check out the Migration section
Enable TypeScript for your windi.config.js
? Sure, why not?
Rename it to windi.config.ts
and things just work!
import { defineConfig } from 'windicss/helpers'
import formsPlugin from 'windicss/plugin/forms'
export default defineConfig({
darkMode: 'class',
safelist: 'p-3 p-4 p-5',
theme: {
extend: {
colors: {
teal: {
100: '#096',
},
},
},
},
plugins: [formsPlugin],
})
It will automatically enable Pug support for .pug
and Vue SFC when dependency pug
is found in the workspace.
It might be a common practice when you use the purge-based Tailwind where you have all the classes in your browser and you can try how things work by directly changing the classes in DevTools. While you might think this is some kind of limitation of "on-demand" where the DevTools don't know those you haven't used in your source code yet.
But unfortunately, we are here to BREAK the limitation 😎 See the video demo.
Just add the following line to your main entry
import 'virtual:windi-devtools'
It will be enabled automatically for you, have fun!
Oh, and don't worry about the final bundle, in production build virtual:windi-devtools
will be an empty module and you don't have to do anything about it 😃
⚠️ Please use it with caution, under the hood we use MutationObserver to detect the class changes. Which means not only your manual changes but also the changes made by your scripts will be detected and included in the stylesheet. This could cause some misalignment between dev and the production build when using dynamically constructed classes (false-positive). We recommended adding your dynamic parts to the
safelist
or setup UI regression tests for your production build if possible.
Preflight is enabled on-demand. If you'd like to completely disable it, you can configure it as below
import { defineConfig } from 'vite-plugin-windicss'
export default defineConfig({
preflight: false,
})
By default, we scan your source code statically and find all the usages of the utilities then generated corresponding CSS on-demand. However, there is some limitation that utilities that decided in the runtime can not be matched efficiently, for example
<!-- will not be detected -->
<div className={`p-${size}`}>
For that, you will need to specify the possible combinations in the safelist
options of windi.config.ts
.
import { defineConfig } from 'vite-plugin-windicss'
export default defineConfig({
safelist: 'p-1 p-2 p-3 p-4',
})
Or you can do it this way
import { defineConfig } from 'vite-plugin-windicss'
function range(size, startAt = 1) {
return Array.from(Array(size).keys()).map(i => i + startAt)
}
export default defineConfig({
safelist: [
range(3).map(i => `p-${i}`), // p-1 to p-3
range(10).map(i => `mt-${i}`), // mt-1 to mt-10
],
})
On server start, vite-plugin-windicss
will scan your source code and extract the utility usages. By default, only files under src/
with extensions vue, html, mdx, pug, jsx, tsx
will be included. If you want to enable scanning for other file types of locations, you can configure it via:
import { defineConfig } from 'windicss/helpers'
export default defineConfig({
extract: {
include: ['src/**/*.{vue,html,jsx,tsx}'],
exclude: ['node_modules', '.git'],
},
})
Or in plugin options:
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
WindiCSS({
scan: {
dirs: ['.'], // all files in the cwd
fileExtensions: ['vue', 'js', 'ts'], // also enabled scanning for js/ts
},
}),
],
})
Enabled it by
export default {
attributify: true,
}
And use them as you would like:
<button
bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
text="sm white"
font="mono light"
p="y-2 x-4"
border="2 rounded blue-200"
>
Button
</button>
If you are concerned about naming confliction, you can add custom prefix to attributify mode by:
export default {
attributify: {
prefix: 'w:',
},
}
<button
w:bg="blue-400 hover:blue-500 dark:blue-500 dark:hover:blue-600"
w:text="sm white"
w:font="mono light"
w:p="y-2 x-4"
w:border="2 rounded blue-200"
>
Button
</button>
Be aware, alias entries need to be prefixed with * when used, eg:
<div class="*hstack">
See this release post for the difference between shortcuts and alias.
export default {
alias: {
'hstack': 'flex items-center',
'vstack': 'flex flex-col',
'icon': 'w-6 h-6 fill-current',
'app': 'text-red',
'app-border': 'border-gray-200 dark:border-dark-300',
},
}
Supported from v0.14.x
By default, importing virtual:windi.css
will import all the three layers with the order base - components - utilities
. If you want to have better controls over the orders, you can separate them by:
- import 'virtual:windi.css'
+ import 'virtual:windi-base.css'
+ import 'virtual:windi-components.css'
+ import 'virtual:windi-utilities.css'
You can also make your custom css been able to be overridden by certain layers:
import 'virtual:windi-base.css'
import 'virtual:windi-components.css'
+ import './my-style.css'
import 'virtual:windi-utilities.css'
See options.ts for more configuration reference.
You will need to set transformCSS: 'pre'
to get Scoped Style work.
@media
directive with scoped style can only works with css
postcss
scss
but not sass
, less
nor stylus
See examples for react, vue and vue with pug sample projects, or Vitesse
Install plugin with npm i -D vite-plugin-windicss
and edit the vite.config.js
file:
import { sveltekit } from '@sveltejs/kit/vite';
+ import WindiCSS from 'vite-plugin-windicss'
/** @type {import('vite').UserConfig} */
const config = {
plugins: [
sveltekit(),
+ WindiCSS()
]
};
export default config;
Add import "virtual:windi.css"
to the top of your +layout.svelte
file:
<script>
import "virtual:windi.css"
// if you want to enable windi devtools
import { browser } from "$app/env";
if (browser) import("virtual:windi-devtools")
// ...
</script>
<!-- ...rest of +layout.svelte -->