Setting Up UnoCSS with Sveltekit

Setting Up UnoCSS with Sveltekit

If you like Tailwind CSS then you will love UnoCSS, due to its incredible performance, easy customizability, pre-packaged icon sets and its extensive devtools inspector.

Why UnoCSS?

To me, the best ideally atomic CSS should be invisible. Once learned, it should be intuitive and analogous to know the others. It’s invisible when it works as you expect and could become frustrating when it doesn’t.

– Anthony Fu, creator of UnoCSS

Just as Anthony wishes for such an invisible framework, he and his team actually builds one.

UnoCSS is an on-demand atomic css engine. It generates the classes on demand when it detects them in your source.

One of the distinctive features that differentiates UnoCSS from other utility frameworks such as Tailwind CSS and Windi CSS is its ability to generate necessary classes without using a parser. For example: Tailwind CSS uses Postcss AST ( Abstract Syntax Tree ) under the hood.

And Tachyons packages the entire css file. Hmm…

Instead UnoCSS has its own engine which uses regex to detect patterns in the source code. Classes are generated only for matched patterns, making development faster and HMR seamless since the code goes through a single pass. Furthermore in production unused classes are stripped away automatically. ( In Tailwind CSS, PurgeCSS can be used for this procedure. )

UnoCSS is more like a framework creator than a framework. At the core of UnoCSS, different presets are used for working with different features, i.e. you can make your own presets by defining your own regex rules. By default, utility classes from Tailwind CSS, Tachyons, Bootstrap and Windi CSS are included in the default preset.

Initialising SvelteKit

You know the drill. Making a new SvelteKit project is easy as copying the following command, pasting it in the terminal and pressing Enter.

npm create svelte@latest app-name && cd app-name && npm i
<div>
	<p>Hey</p>
</div>

Setting up UnoCSS

The main juice of this article is here. Once you have initialised the project with the above command, you can install UnoCSS and configure it.

1. Installation

npm i -D unocss

2. Pluggin' in the plugin

Paste this code in vite.config.ts. It essentially installs UnoCSS into your Vite server.

// vite.config.ts
import type { UserConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import UnoCSS from 'unocss/vite';

const config = {
	plugins: [UnoCSS(), sveltekit()]
};

3. Configuration

This is the part where we configure UnoCSS to meet our needs. For this purpose, create a new file named uno.config.ts in the root directory of your project. And paste the following code there.

// uno.config.ts

import {
  defineConfig,

  // presets
  presetAttributify,
  presetUno,
  presetWind,
  presetWebFonts,
  presetTypography,
  presetIcons,

  // transformers
  transformerAttributifyJsx,
} from 'unocss';

export default defineConfig({
  // ...UnoCSS options
  presets: [
    presetUno(),
    presetAttributify(),
    presetWind(),
    presetWebFonts({
      provider: 'bunny',
      fonts: {
        base: 'Inter:400,500,600,700,800,900',
      },
    }),
    presetTypography(),
    presetIcons(
  ],
  transformers: [
    transformerAttributifyJsx()
  ],
  theme: {
    colors: {
      'primary': '#6259E3',
      'text': '#050505',
      'bg': '#F7F7F7',
    },
  },
  preflights: [
    {
      getCSS: ({ theme }) => {
        const t = theme as any;

        return `
          body {
            --c-primary: ${t.colors.primary};
            --c-text: ${t.colors.text};
            --c-bg: ${t.colors.bg};
          }
          html {
            scroll-behavior: smooth;
            height: 100%;
          }
        `;
      },
    }
  ],
});

It contains the necessary options to get you started such as

  • 3 basic colors: Primary, Text and Background
  • Basic styles for <html>
  • Inter font from bunny font provider is loaded
  • Attributify mode enabled for good DX.

4. Importing UnoCSS into the root layout

Finally, import UnoCSS into your website’s entry point.

<!-- src/routes/+layout.svelte -->
<script lang="ts">
	import 'uno.css';
	import '@unocss/reset/tailwind.css';
</script>

<!-- ... other stuff -->

And that’s it. Now, you can use UnoCSS in your project.

Configuration in detail

svelte-scoped

The default mode of the UnoCSS Vite plugin ( the one we are using ) is called global. In this mode, all the styles are put into one single css file. This doesn’t make much difference if you are making a small project, but as it scales with many different pages with their own styles… The bundle size will get quite large.

Inorder to mitigate this performance issue, another mode called svelte-scoped can be used. By using this mode, we tell UnoCSS that we want component and route specific styles to be included in the component/route <style> itself.

  1. Install
npm i -D @unocss/svelte-scoped
  1. Add the plugin

Paste it in your vite.config.ts

// vite.config.ts
import { defineConfig } from 'vite';
import { sveltekit } from '@sveltejs/kit/vite';
import UnoCSS from '@unocss/svelte-scoped/vite';

export default defineConfig({
	plugins: [
		UnoCSS({
			// style reset here
			injectReset: '@unocss/reset/tailwind.css'
			// ...other Svelte Scoped options
		}),
		sveltekit()
	]
});
  1. Necessary global styles

Eventhough the component/route-specific styles are placed within them itself, few of the styles must still be placed in the global context. For this purpose, add the %unocss-svelte-scoped.global% placeholder before %sveltekit.head% in src/app.html.

<head> %unocss-svelte-scoped.global% %sveltekit.head% </head>

Finally, the html has to be transformed in a SvelteKit hook. Therefore, place this in your src/hooks.server.ts.

import type { Handle } from '@sveltejs/kit';

export const handle: Handle = async ({ event, resolve }) => {
	const response = await resolve(event, {
		transformPageChunk: ({ html }) =>
			html.replace('%unocss-svelte-scoped.global%', 'unocss_svelte_scoped_global_styles')
	});
	return response;
};

Svelte Extractor

If you have been using SvelteKit with Tailwind CSS, you can do something like class:foo={bar}, where class foo is applied when bar evaluates to true.

By default this won’t work with what we have done. So you will have to install an extractor for svelte.

  1. Install
npm i -D @unocss/extractor-svelte
  1. Using the extractor
// uno.config.js
import { defineConfig } from 'unocss';
import extractorSvelte from '@unocss/extractor-svelte';

export default defineConfig({
	extractors: [extractorSvelte()]
});

Now you can use UnoCSS like this too! Classes from class: directive are extracted into the final stylesheet.

<div class:text-2xl={foo} />

Generated style:

.text-2xl {
	font-size: 1.5rem; /* 24px */
	line-height: 2rem; /* 32px */
}

Refer to the Config reference in the documentation for more.

Wait, here are some UnoCSS templates

Setting all this up is not a daunting task. But what if you need a starting point for your new UnoCSS website? Don’t worry we’ve got your back. Focus on your website’s purpose instead of wasting time fixing some random style issue because we have done it for you. Checkout some of these easily customizable and beautiful UnoCSS templates and SvelteKit templates.

Or are you looking for something more custom? Contact us with your requirements.

Until then, 👋!