DEV Community

Blusk
Blusk

Posted on

Zero-Runtime Scoped Component Styling Made Easy!

Background

I have traditionally been a Vue user, though recently I have decided to write an app in Solid. Unfortunately, turns out Solid doesn't have anything like <style scoped> in Vue. I saw some recommendations for CSS-in-JS solutions, but I didn't really like adding additional runtime just for styling, and integrations with tooling were painful a lot of the time. I needed something with better compatibility and less runtime preferably.

CSS Modules are (almost) perfect

As in, they seem to address the problem I have almost perfectly. One small issue though: making a CSS module for every new component gets tedious! Imagine having a new CSS file for every component sitting in the same folder!

Introducing: vite-plugin-inline-css-modules

So, I wrote a simple Vite plugin that lets you write CSS modules inside of your components. It's blazingly fast due to its simplicity, and features no additional runtime since it transpiles directly to a CSS module.

Let's see it in action:

import { css } from 'vite-plugin-inline-css-modules'

const classes = css`
  .root {
    background-color: #1f1;
    @apply rounded-md;
  }
`

export const Root = () => <div class={classes.root}>Hello world</div>
Enter fullscreen mode Exit fullscreen mode

Transforms to:

import classes from 'virtual:inline-css-modules/App-0.module.css'

export const Root = () => <div class={classes.root}>Hello world</div>
Enter fullscreen mode Exit fullscreen mode

No runtime!

Also, side note: this also can help with messy tooling such as integrating Tailwind/UnoCSS, since I've experienced problems in the past with CSS-in-JS solutions and using @apply. The rule is simple: any valid CSS module syntax is going to also be valid inside of a inline CSS module. Because that's what it transpiles to.

Also, this'll work with any framework without any sort of special integration because CSS modules are standard across all frameworks. Just declare a template string with styles and it should just work. :)

Check out the plugin here

Discussion (0)