UnoCSS with Laravel

I’m an avowed fan of Laravel and it’s one of my go to frameworks for php development. However these days its default frontend stack - TailwindCSS, Inertia or Livewire, AlpineJS - seems somewhat esoteric and contrarian to me, apart from Tailwind.

Whether that’s a fair assessment or not, it has definitely diverged from my own preferences. My usual frontend stack is UnoCSS for utitilies, SASS for custom CSS, StimulusJS for simpler interactions/sprinkles, and VueJS for reactive components and SPAs. This post is specifically going to talk about how I set up UnoCSS with Laravel.

Firstly just to be clear I’m not a huge fan of so-called “utility first” approaches - they look an awful lot like inline styles to me, and tend towards becoming a total mess when over-used. Yes I know about @apply, but that looks like re-inventing the wheel to me - I can already do that in, erm, CSS.

However I do generally need a utility layer - check out Andy Bell’s excellent CubeCSS and Every Layout for where my head is currently at. Although fairly trivial to do so it doesn’t really make sense to write this layer yourself unless you really want to - TaiwindCSS clearly fulfills this use case, but I’ve gotten very used to consuming it via Antfu’s excellent UnoCSS which I’ve been using in Nuxt/Vue projects. I recently wanted to bring it into a greenfield Laravel project - below I’ll detail the steps that worked for me.

In this project there are no reactive js components (e.g. Vue/React) at least not yet - for now I’m just using plain old blade views, with some StimulusJS directives for interactivity. This means the unocss vite plugin is of no use to me here - enter the unocss cli. The unocss cli watches ad hoc directories for css classes and generates a css file accordingly. After that Vite takes care of the final bundle as normal.

The first step was to install UnoCSS and its CLI. I needed to install both, or nothing works - this isn’t really clear in the unocss docs. I’m using pnpm, but bun, yarn or good old npm also work.

pnpm -D install unocss @unocss/cli

I then set up the unocss config so that the cli will watch the views directory and outputs to a (gitignored) uno.css file

// unocss.config.ts
import { defineConfig } from 'unocss'

export default defineConfig({
    cli: {
        entry: {
            patterns: [
                'resources/views/**/*.blade.php',
            ],
            outFile: 'resources/css/uno.css'
        },
    },
})
# resources/css/.gitignore
uno.css

I then added the unocss command to package.json - note that this runs in parallel with vite for dev via &, and sequentially for build using &&

// package.json
"scripts": {
        "dev": "unocss --watch & vite",
        "build": "unocss && vite build"
    },

Finally I imported uno.css into my main app.scss

// resources/scss/app.scss
@import '../css/uno.css';

I can now pnpm run dev or pnpm run build and everything works as expected.