5 CSS-in-JS Frameworks to use in 2021
As web development continues massive evolving, new ways of doing things emerge, and communities get built around them. Handling frontend development with JS frameworks, styling components have been all about having separately dedicated stylesheets for each component which are now applied to the DOM.
Introduction
CSS can be really exhausting for developers, maintaining styles across components and context switching can become a chore, you can also relate to this if you have spent some time trying to center a div or a button before. Developers who primarily work with JavaScript started to innovate around styling and asking what if it can also be done in JS.
CSS-in-JS is a new approach to styling using JavaScript to style components in-line, on compile, the JS is parsed and CSS rules are generated and pushed to the DOM. This means you do not really have to carry the burden of the CSS learning curve, neither do you need to fully understand it as it is now totally abstracted for you. This approach promises to be more maintainable, easier to use (as you stick to the JS you already know) and some even have special features built to enhance CSS.
In today’s post, we will be looking at a few of these CSS-in-JS frameworks you can try out in your workflow right away.
Styled Components
This is the most popular CSS-in-JS library that currently exists and the term CSS-in-JS was also made very popular by Styled Components. With widespread usage, over 35,000 stars on GitHub with over 10m projects using it per month Styled Components lets you define CSS styles inline using ES6 template literals. Popular in the React community for styling React components easily. This is how easy a button is styled:
import styled from 'styled-components'
const Button = styled.button``
The style definition would look like this:
const Button = styled.button`
background: transparent;
border-radius: 3px;
border: 2px solid palevioletred;
color: palevioletred;
margin: 0 1em;
padding: 0.25em 1em;
`
Styled Components comes with a lot of advantages asides we general ones we already mentioned above, you can do selector nesting, just like with SASS. You also never need to worry about class name bugs as it generates unique class names automatically and manages them as they go in and out of the DOM.
Emotion
The first special thing about Emotion as a CSS-in-JS library is that is framework agnostic so you can use it in Vue and Angular projects as well as React too. With over 13,000 stars on GitHub Emotion is a very flexible library that is built on other CSS-in-JS libraries and another great thing about it is how it is predictable so even with little knowledge of CSS, you can start using it without any issues. It has a really cool documentation, the vue-style that you are probably already familiar with and is very performant.
A hover button in Emotion looks like this:
import { css, cx } from '@emotion/css'
const color = 'white'
render(
<div
className={css`
padding: 32px;
background-color: hotpink;
font-size: 24px;
border-radius: 4px;
&:hover {
color: ${color};
}
`}
>
Hover to change color.
</div>
)
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.
Start enjoying your debugging experience - start using OpenReplay for free.
Stitches
This is a very interesting one, with almost 4,000 stars on GitHub Stitches is a CSS-in-JS library that runs in near-zero runtime. It supports server-side rendering and has variants support. Basically, CSS was re-imagined as a JS library with stitches. It is also framework agnostic so you can use it with any frontend development library. It ships with smart tokens and even custom CSS properties.
With Stitches, you do not have to download an entire library because it does style injection. With a fully-typed API, token-aware properties, and custom utils, Stitches offers a fun and intuitive experience all-round.
A simple button is created like this:
import { styled } from '@stitches/react';
const Button = styled('button', {
backgroundColor: 'gainsboro',
borderRadius: '9999px',
fontSize: '13px',
padding: '10px 15px',
'&:hover': {
backgroundColor: 'lightgray',
},
});
Radium
Radium took a kind of radical approach, eliminating CSS totally for inline styles and making all of those styles global. This basically provides us with scoped styling without using selectors, eliminating dead code or chances of repeattition and being totally expressive. You might say inline styles are limited by default, that is correct but Radium offers a standard interface that deals with issues like media queries and browser or mouse states like click or hover.
A button in Radium looks like this:
import Radium from 'radium';
import React from 'react';
import color from 'color';
class Button extends React.Component {
static propTypes = {
kind: PropTypes.oneOf(['primary', 'warning']).isRequired
};
render() {
// Radium extends the style attribute to accept an array. It will merge
// the styles in order. We use this feature here to apply the primary
// or warning styles depending on the value of the `kind` prop. Since its
// all just JavaScript, you can use whatever logic you want to decide which
// styles are applied (props, state, context, etc).
return (
<button style={[styles.base, styles[this.props.kind]]}>
{this.props.children}
</button>
);
}
}
Button = Radium(Button);
// You can create your style objects dynamically or share them for
// every instance of the component.
var styles = {
base: {
color: '#fff',
// Adding interactive state couldn't be easier! Add a special key to your
// style object (:hover, :focus, :active, or [@media](http://twitter.com/media)) with the additional rules.
':hover': {
background: color('#0074d9')
.lighten(0.2)
.hexString()
}
},
primary: {
background: '#0074D9'
},
warning: {
background: '#FF4136'
}
};
It was built for React applications, most of the CSS-in-JS libraries have dedicated React libraries too.
JSS
JSS is a CSS abstraction in JavaScript, it dynamically outputs rules based on component state. It is super lightweight and one great thing about it is integrations, it has a React integration, a Styled Component integration and a lot of plugins too. Remember how some CSS-in-JS generates styles and injects them inline in the DOM, JSS does it the old fashioned way output a master stylesheet before injecting it. There are a lot of useful plugins you can use to achieve the functionality available in other CSS-in-JS libraries like nesting, global selectors, plugin isolation etc.
A button looks like this:
import React from 'react'
import {render} from 'react-dom'
import {createUseStyles} from 'react-jss'
// Create your Styles. Remember, since React-JSS uses the default preset,
// most plugins are available without further configuration needed.
const useStyles = createUseStyles({
myButton: {
color: 'green',
margin: {
// jss-expand gives more readable syntax
top: 5, // jss-default-unit makes this 5px
right: 0,
bottom: 0,
left: '1rem'
},
'& span': {
// jss-nested applies this to a child span
fontWeight: 'bold' // jss-camel-case turns this into 'font-weight'
}
},
myLabel: {
fontStyle: 'italic'
}
})
const Button = ({children}) => {
const classes = useStyles()
return (
<button className={classes.myButton}>
<span className={classes.myLabel}>{children}</span>
</button>
)
}
const App = () => <Button>Submit</Button>
render(<App />, document.getElementById('root'))
Conclusion
We have gotten acquainted with the concept of CSS-in-JS and how it can be useful to us in our workflow. We also took a look at a few CSS-in-JS libraries we can start using today. You can follow the State of CSS survey here where thousands of developers share their feeedback every year. Which is your favourite and why?