tutorial

How to Use WindiCSS in a Vue Project

"3 years ago"/assets/windi-css.823f748f.png

Windi CSS is a next-generation utility-first CSS framework.

Installation

Create a Vue project and install the packages.

pnpm create vite vue-3-windi -- --template vue
cd vue-3-windi
pnpm i -D vite-plugin-windicss windicss
pnpm create vite vue-3-windi -- --template vue
cd vue-3-windi
pnpm i -D vite-plugin-windicss windicss

Configuration

  1. Register the plugin in vite.config.js.
import { defineConfig } from "vite"
import Vue from "@vitejs/plugin-vue"
import WindiCSS from "vite-plugin-windicss"

export default defineConfig({
  plugins: [Vue(), WindiCSS()]
})
import { defineConfig } from "vite"
import Vue from "@vitejs/plugin-vue"
import WindiCSS from "vite-plugin-windicss"

export default defineConfig({
  plugins: [Vue(), WindiCSS()]
})
  1. Create windi.config.js in the root. This is the config file for this site.
import { defineConfig } from "vite-plugin-windicss"

export default defineConfig({
  preflight: false,
  attributify: true,
  transformCSS: "pre",

  theme: {
    fontFamily: {
      sans: ["Fira Sans", "sans-serif"],
      mono: ["Fira Code", "sans-serif"]
    },

    colors: {
      blue: "#268bd2",
      cyan: "#2aa198",
      green: "#859900",
      magenta: "#d33682",
      orange: "#cb4b16",
      red: "#dc322f",
      violet: "#6c71c4",
      yellow: "#b58900"
    }
  }
})
import { defineConfig } from "vite-plugin-windicss"

export default defineConfig({
  preflight: false,
  attributify: true,
  transformCSS: "pre",

  theme: {
    fontFamily: {
      sans: ["Fira Sans", "sans-serif"],
      mono: ["Fira Code", "sans-serif"]
    },

    colors: {
      blue: "#268bd2",
      cyan: "#2aa198",
      green: "#859900",
      magenta: "#d33682",
      orange: "#cb4b16",
      red: "#dc322f",
      violet: "#6c71c4",
      yellow: "#b58900"
    }
  }
})
pnpm i sanitize.css
pnpm i sanitize.css
  1. Create main.css in src for the global style, including the fonts. Here is a snippet:
@import url("https://fonts.googleapis.com/css2?family=Fira+Code&family=Fira+Sans:wght@300;400;500&display=swap");

/* Variables */

html:not(.dark) {
  --background: #fdf6e3;
  --highlights: #eee8d5;
  --primary: #657b83;
  --secondary: #93a1a1;
  --emphasis: #586e75;
}

html.dark {
  --background: #002b36;
  --highlights: #073642;
  --primary: #839496;
  --secondary: #586e75;
  --emphasis: #93a1a1;
}

/* General */

::selection {
  @apply bg-$highlights;
}
@import url("https://fonts.googleapis.com/css2?family=Fira+Code&family=Fira+Sans:wght@300;400;500&display=swap");

/* Variables */

html:not(.dark) {
  --background: #fdf6e3;
  --highlights: #eee8d5;
  --primary: #657b83;
  --secondary: #93a1a1;
  --emphasis: #586e75;
}

html.dark {
  --background: #002b36;
  --highlights: #073642;
  --primary: #839496;
  --secondary: #586e75;
  --emphasis: #93a1a1;
}

/* General */

::selection {
  @apply bg-$highlights;
}
  1. Import everything in src/main.js. For sanitize.css’ available stylesheets, check the repo.
import { createApp } from "vue"
import App from "./App.vue"

import "sanitize.css"
import "sanitize.css/forms.css"
import "sanitize.css/assets.css"

import "virtual:windi.css"

import "./main.css"

const app = createApp(App)

app.mount("#app")
import { createApp } from "vue"
import App from "./App.vue"

import "sanitize.css"
import "sanitize.css/forms.css"
import "sanitize.css/assets.css"

import "virtual:windi.css"

import "./main.css"

const app = createApp(App)

app.mount("#app")

Usage

Look for the utilities and start putting the classes. You can also look for them in Tailwind’s documentation if you prefer their docs (like me).

Here is an example from this site (/index.html).

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Yasmin ZY</title>
    <link rel="icon" href="/favicon.ico" />
  </head>

  <body>
    <div
      id="app"
      class="bg-$background font-sans min-h-screen text-$primary leading-relaxed w-full grid grid-rows-[auto,1fr,auto] overflow-hidden"></div>

    <script type="module" src="/src/main.js"></script>
  </body>
</html>
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Yasmin ZY</title>
    <link rel="icon" href="/favicon.ico" />
  </head>

  <body>
    <div
      id="app"
      class="bg-$background font-sans min-h-screen text-$primary leading-relaxed w-full grid grid-rows-[auto,1fr,auto] overflow-hidden"></div>

    <script type="module" src="/src/main.js"></script>
  </body>
</html>
  • $ in bg- and text- tells Windi that background and primary are CSS variables.
  • Windi has several grid template rows classes, but there is not one for the values auto 1fr auto. Fortunately, Windi has a feature called auto-infer so I can just write grid-rows-[auto,1fr,auto].

Another feature I use often is the @apply directive. Here is another code snippet from this website.

.shiki-container {
  @apply border-solid border-$highlights rounded-lg border-4 mb-4 leading-normal py-2 px-4;
}
.shiki-container {
  @apply border-solid border-$highlights rounded-lg border-4 mb-4 leading-normal py-2 px-4;
}

Tips

This is for VSCode users:

  1. Install the WindiCSS IntelliSense extension. Ctrl+P and paste this:
ext install voorjaar.windicss-intellisense
ext install voorjaar.windicss-intellisense
  1. Turn on the sortOnSave setting.
"windicss.sortOnSave": true
"windicss.sortOnSave": true

Just be careful when you have autosave, it can move your class before you finish writing it.