DEV Community

Cover image for The tiniest CSS-in-JS solution for your open-source React components

The tiniest CSS-in-JS solution for your open-source React components

Vlad Shilov on February 18, 2021

Hey there! My name is Vlad and I'm fascinated by the development of JavaScript micro-libraries. My primary projects at the moment are: react-col...
Collapse
 
fezvrasta profile image
Federico Zivolo • Edited

Why don't you simply render a <style/> tag? Emotion does the same and it works fine even on SSR.

Collapse
 
omgovich profile image
Vlad Shilov • Edited

Hi! What do you mean? By default Emotion adds <style data-emotion="css"> tags into the head. We do almost the same.

IMG

Collapse
 
fezvrasta profile image
Federico Zivolo • Edited

That only happens on development builds.

Collapse
 
shadowtime2000 profile image
shadowtime2000

That's a cool way to do this! As far as I can see, this would only work for client side and when SSRing the styles wouldn't be immediately shipped.

Collapse
 
omgovich profile image
Vlad Shilov

You are right. It is a drawback to this approach (and most other CSS-in-JS solutions). But in my case (a small color picker) it doesn't seem critical.

Collapse
 
vndre profile image
Andre

Honestly I feel this approach will insert many possible side effects to an app. One of the problems I have stumbled with bigger apps is css render blocking.

The team of Svelte did a similar approach: they insert all css in the head after Svelte finish loading, but sometimes it takes like a second to execute that code so all the app's layout loads naked and only then css is insert.

If a simple app (like an online color picker) visually depends on your package it would make more sense to have those styles already in the HTML file (critical css, SEO, SSR, etc). Now imagine if every package creator uses this approach, they will be a cascade of pending styles.

I feel we should let the package users decide the way they want their css to be handled. You could maybe export a function helper which loads the styles? (loadColorPickerCss())

Thread Thread
 
rschristian profile image
Ryan Christian

FWIW, react-colorful only ships 1.6kb of (minified) CSS. The amount of JS that would be needed to slow down this injection would be monumental, and even then, would only be noticed if this color picker was right at the top of the document.

I think that's searching for a solution before a problem has even appeared. The amount of JS we're talking about would already make the site really rough.

Thread Thread
 
vndre profile image
Andre

Yes, I know that for this specific library this is no issue. But a bigger app will probably use more packages, then we got the node_modules hell... Also not everyone creates packages with size and zero-deps in mind like you do.

Imagine an node app were my deps are: react-colorful (0 deps, 1kb css), react-slider (8 deps, 100kb css) and tailwindcss (64 deps, 3mb css). If those package creators all use the same method to inject css into the documents' head and react-colorful render happens deep in the tree the chain could be like: 1. tailwind injects code, browsers starts downloading 3mb of a css file... 2. react-slider does the same... 3. react-colorful does the same a little faster. In my fictional case there where only 3 main deps but you can see where a cascade of waiting requests could be created for slower connections or with more package deps...

Collapse
 
shadowtime2000 profile image
shadowtime2000

You could do it by making the CSS-in-JS-like solution optional so for people who SSR can just ship the styles separately. Though, yeah SSR may not matter as much in this case as it would in like a ui framework because a color picker a little more of a client side component instead of one that should be like fully crawlable.

Collapse
 
fkhadra profile image
Fadi Khadra • Edited

Nice one, I have the same thing with react-toastify and react-contexify. I wanted to provide a way for the users to load the style without importing the CSS.

I created a small CLI tool that generates a helper function to inject the minified css.
It's not perfect but it does the job really well, also it's not tied to react.

github.com/fkhadra/style2js

Edit: I've tried react-colorful, I'll definitely use it for the project I'm working on. Really neat 👌

Collapse
 
omgovich profile image
Vlad Shilov

Thanks for the kind words!
react-toastify is an awesome library!

The most difficult part of the migration to CSS-in-JS is a bundler configuration. I reached all of my goals by using Microbundle. Give it a try — I guess might cover your needs.