We're going to learn about CSS-in-JS, the powers of this technique and how we can create better applications by writing our CSS code with JavaScript.
In this article, we’re going to learn more about CSS-in-JS, a different way to style our elements in applications. This technique has been used for a while now in the community, and a lot of developers are finding they have a better style of composition in their applications and are making their CSS elements and code cleaner, more beautiful, and easier to deal with.
In this article, most of the examples will be related to React applications, but CSS-in-JS is not a thing specific for React — it’s a technique to style applications and can be applied in any other framework or library. To understand CSS-in-JS, first we’re going to learn a little bit about CSS in general in React and how we were styling our apps before the rise of CSS-in-JS. Then we’re going to learn about CSS Modules, another technique to style React applications that were hugely used for some time by many developers. After that we’re going to cover CSS-in-JS, why it has been used so much lately by developers, its benefits, etc.
CSS, in general, was always a popular and important topic on the web, and the way we style our applications was always a topic of discussion and study for a lot of developers, requiring some study to understand what would be the right choice for a specific situation or application. In the beginning, we had a simple and easy way of styling our applications, a way well known by almost every developer: create a simple .css file and, inside that file, you’re able to organize, change, and style any element of your application you want. But once you have a .css file and starting to style your elements, your application and mainly your CSS code is going to increase in size, so you’ll need to start to think of other ways to organize your CSS code and make your application simpler, easier to maintain, contain cleaner code, etc.
.css
The technique of CSS-in-JS basically came to solve this particular problem so that you won’t have a ton of .css files, and you won’t have to deal with your CSS code like we used to, in some situations having to apply techniques such as BEM, OOCSS, etc. to get better code and improve your application.
BEM
OOCSS
Let’s learn some ways to style our React applications — some methods we were using before the rise of CSS-in-JS, and then we’ll go through an introduction to CSS-in-JS. Finally, we’ll learn a little bit about some libraries that we can start to use today to have a better style of composition in our applications.
In React, before the rise of CSS-in-JS, the most widely used way to work with CSS was by using CSS Modules. But what exactly are CSS Modules?
A CSS Module is basically a .css file where you'll put all your CSS code, such as class names, ids, animations, etc. and, every time it's imported, the names and animations inside that specific CSS Module is scoped locally to the component by default. The main idea of CSS Modules is that each component has its own .css file, and is a process that happens at build time that will change the class names and selectors that you have to be scoped.
Let's imagine that we have a simple .css file called menu.css., Inside this file, we have some CSS code, like this:
menu.css
width: 200px;
height: 600px;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.item {
font-size: 16px;
font-weight: 600;
}
Then, to use it we'll import this module to our component, like this:
import styles from "./menu.css"
For example, let's imagine that we have a simple ul element with three li elements inside, like this:
ul
li
<ul className="menu">
<li className="item">CSS</li>
<li className="item">CSS-in-JS</li>
<li className="item">CSS Modules</li>
</ul>
To use the classes that we defined in our module, all we need to do is to pass the className of each element inside an object, like this:
<ul className={styles.menu}>
<li className={styles.menu}>CSS</li>
<li className={styles.menu}>CSS-in-JS</li>
<li className={styles.menu}>CSS Modules</li>
</ul>
Now, when the application starts, the class names will be transformed into new class names, to avoid global conflicts between styles. We covered a little bit about CSS Modules, just to understand how it works. Now we can dive deep and learn more about CSS-in-JS and its benefits.
You may already know this, but there's a slight difference between CSS-in-JS and inline styles. With inline styles, you write your code in a JavaScript object, then attach it to the style attribute. By using inline styles you have some limitations — you can't use pseudo-selectors, media queries, keyframes, etc.
style
CSS-in-JS is different from inline styles. We still write all our CSS in JavaScript, but instead of passing it to the style attribute, we take those styles and inject an actual string of CSS in a <style> tag into the DOM. By having all your CSS in JavaScript and using CSS in-JS, you can have separate folders to organize your styles in a better way and have files to different React components, eliminating that whole mess that you have in one single .css file.
<style>
For example, to start to work with inline styles, all you need to do is create a JavaScript object and pass options for styling your element, like this:
const styles = {
background: "#FE0000",
color: "#FFFFFF"
};
Then, in your element, you pass it in the style attribute, like this:
<div style={styles}>
<h1>CSS-in-JS</h1>
</div>
But using inline styles has its limitations because we don't have all features of CSS in plain objects like this. So to have better styling in our application, we need to go to a library; in this case, I'm going to use Styled Components.
All you have to do is install Styled Components:
yarn add styled-components
Then, import it in your React component:
import styled from "styled-components";
To start to use Styled Components, all you need to do it create an object using template literals, like this:
const StyledButton = styled.button`
width: 120px;
height: 42px;
background: #FE0000;
color: #FFFFFF;
`;
Then, to use this "component" that we created, all we need to do is pass it. Instead of a native button element, we pass the Button that we created, like this:
import React from "react";
import styled from "styled-components";
const StyledButton = styled.button`
width: 120px;
height: 42px;
background: #FE0000;
color: #FFFFFF;
`;
const Button = () => (
<StyledButton>
My Styled Button
</StyledButton>
);
export default Button;
We can also render based on conditional values like props, for example. Let's imagine that our button receives a prop called active, and we want to change the color of the button based on props. This is how we would do that:
const StyledButton = styled.button`
width: 120px;
height: 42px;
background: ${props => props.active ? "#FE0000" : "#FE2012};
color: #FFFFFF;
`;
By using CSS-in-JS in your applications, you're at a great advantage. You won't have to deal with painful maintenance in your app, it's easier to organize your code since you can organize all your styles by components or containers, and you can use conditional rendering very easily (if you're using some library like Styled Components, it's way easier) and render what you need based on props.
CSS-in-JS in React applications especially is the most-used way to style your apps, and, of course, it has a lot of libraries to do this job. Here comes a list of the top three CSS-in-JS libraries and their features.
The most famous and used CSS-in-JS library is Styled Components. We covered a little bit of it in this article, but it's worth mentioning again to say that it has some nice features. When we mention CSS-in-JS, the first thing that comes to mind for many developers is Styled Components. That’s because almost every developer who has been working with React lately has worked with Styled Components at some point. It's a powerful way to define styles by using the ES6 feature called template literals, and the idea to use components as a low-level styling helps a lot when we're styling our apps.
template literals
A simple button using Styled Component would look like this:
import React from "react";
import styled from "styled-components";
const ButtonStyled = styled.button`
width: 120px;
height: 40px;
background: #FE0000;
color: #FFFFFF;
`;
const Button = (props) => (
<ButtonStyled {...props}>My Styled Component Button</ButtonStyled>
);
export default Button;
Very simple and powerful! Styled components have a lot of other features, such as server-side rendering, theming, refs, style objects, and test utilities. If you're going to create a complex application that will require a lot of CSS, I'd really recommend you to go with Styled Components.
If you're coming from a CSS Modules application and never worked with CSS-in-JS in React applications, the library that can be easier and more powerful for you to start is Emotion. The whole idea of Emotion is to have the syntax as close to CSS possible. This way, beginners won't struggle with it, and it makes the adoption a lot easier. This library has a lot of advanced features, such as source maps, cache provider, testing utilities like snapshot tests, and labels, and another nice point to mention here is that Emotion is framework-agnostic.
If you're planning to use Emotion with React, you'll need to have the @emotion/core package installed.
yarn add @emotion/core
A simple button component, styled with Emotion, would look like this:
import { css, jsx } from '@emotion/core'
const color = 'white'
render(
<button
css={css`
background-color: #FE0000;
font-size: 24px;
border-radius: 6px;
color: #FFFFFF;
`}
>
My Emotion Button
</button>
)
A little bit different from the first two libraries above, Radium takes a different approach to deal with CSS. Instead of generating a unique class name for each component, it adds inline styles right to the HTML, so each element of your application that's been using Radium will be directly styled with the style global attribute. A point here that we should mention is: Radium can be only used in React applications, it's not framework-agnostic.
A simple button element using Radium would look like this:
button
import React from "react";
import Radium from "radium";
const styles = {
base: {
width: 120px,
height: 40px
},
warning: {
background: "#FFB200"
},
success: {
background: "#169EFF"
}
};
const Button = ({ kind }) => (
<button style={[styles.base, styles[this.props.kind]]}>My Radium Button</button>
);
// You need to wrap your component with Radium.
export default Radium(Button);
This is one of the three most-used libraries in React applications, but, of course, we have a lot of other libraries, such as Aphrodite, JSS, and Styletron. The whole point here is to show you how CSS-in-JS can benefit your development and improve your application, by having more concise, better written, reusable CSS code throughout your application. By using CSS-in-JS, you won’t have a lot of the problems that we used to have with CSS Modules, like dead code, global conflicts between classes, minification, etc.
In this article, we covered a lot of topics, beginning with CSS in general. We learned about how we were dealing with styles in our applications before the rise of CSS-in-JS, we learned a little bit about how we can use CSS Modules to style our elements, and then we learned about CSS-in-JS. CSS-in-JS, as we covered in this article, is the most-used and the simplest and most concise way to deal with CSS in React applications, allowing you to create reusable components and have better code composition throughout your application. We also learned about three main CSS-in-JS libraries that are widely used nowadays and their benefits.
Leonardo is a Full Stack Developer, working with everything React-related, and loves to write about React and GraphQL to help developers. He also created the 33 JavaScript Concepts.