CSS-in-JS tutorial.

Back in 2015, a JavaScript library called JSS (which is still actively maintained) was launched that allowed developers to use JavaScript to describe styles in a declarative, conflict-free, and reusable way. JSS would automatically apply declared properties to their respective selectors once the page loaded. As frontend JavaScript (JS) libraries like React gained in popularity, they brought forth a new CSS-in-JS solution called styled-components. What styled-components and CSS-in-JS libraries like Emotion have in common is that they all allow web developers to write CSS properties for components through JavaScript. This web development tutorial will present some of the common features of CSS-in-JS, as well as discuss its strengths and weaknesses. By the end, you should also know what to look for when deciding between CSS-in-JS, CSS libraries like Less or SaSS, and good ole vanilla CSS.

How does CSS-in-JS work?

As the name suggests, CSS-in-JS allows programmers to style their components by writing CSS directly in their JavaScript or TypeScript code. Of course, you could do that yourself by defining a constant, as shown in the code example below:

const styles = {
  background: "#FE0000",
  color: "#FFFFFF"
};

Then all you need to do is pass it to the element via the style attribute, like this:

<div style={styles}>
 <!-- some content -->
</div>

While there is nothing wrong with using inline styles like this, this approach is severely limited because plain objects such as these are missing a lot of useful CSS features. For that reason, most developers choose to go to a library, of which there are many. Here is an example of a styled React button using Styled Components:

import React from "react";
import styled from "styled-components";

const StyledButton = styled.button`
  width: 90px;
  height: 40px;
  background: ${props => props.active ? "black" : "darkgrey"};
  color: blue;
`;

const Button = () => (
  <StyledButton>
    My Styled Button
  </StyledButton>
);

export default Button;

Notice that we can determine values dynamically based on conditional values like props.

SEE: Learn JavaScript from scratch for $30

Framework-Specific vs. Framework-Agnostic libraries

Now that we have established that it pays to use a CSS-in-JS library, lets explore the two prevalent types: Framework-Specific and Framework-Agnostic.

Certain libraries, like Radium and JSX, only work with a specific JavaScript framework. For example, Radium was created for React apps, while Styled JSX only supports components written in JSX (although it can also be used with React).

Unsurprisingly, framework-specific CSS-in-JS libraries use the same syntax as the framework they support. For instance, Styled JSX uses template literals within the JSX syntax to add CSS styles to components. Here is an example of Styled JSX code that creates a button with dynamic styling:

const Button = props => (
  <button>
    {props.children}
    <style jsx>{`
      button {
        padding: ${'large' in props ? '40' : '22'}px;
        background: ${props.theme.background};
        color: #555;
        display: block;
        font-size: .5em;
      }
    `}</style>
  </button>
)

Other CSS-in-JS libraries such as JSS, Emotion, and Styled Components are framework-agnostic, meaning that you can use them with any component-based framework or even plain JavaScript. Other libraries such as Aphrodite work with Web Components as well.

Here is an example of a Web Component that uses Aphrodite to set background color:

/* Registers a Web Component with blue background */
import { StyleSheet, css } from 'aphrodite';

const styles = StyleSheet.create({
    blue: {
        backgroundColor: 'blue'
    }
});

class App extends HTMLElement {
    attachedCallback() {
        this.innerHTML = `
<div class="${css(styles.red)}">
This is red.
</div>
`;
    }
}

document.registerElement('my-app', App);

SEE: BitBucket Review

Advantages of CSS-in-JS

Which ever library you choose, all include the following features:

  • Scoped CSS: All CSS-in-JS libraries generate unique CSS class names. Moreover, all styles are scoped to their respective component, providing encapsulation without affecting any styling defined outside the component. This eloquently avoids CSS class name collisions, specificity wars, and spending a lot of time to come up with unique class names across the entire application.
  • Server-Side Rendering (SSR): While Server-Side Rendering (SSR) does not provide much benefit in Single Page Apps (SPAs), it is extremely useful in websites or applications that need to be parsed and indexed by search engines as these require that both pages and styles to be generated on the server.
  • Automatic vendor prefixes: All CSS-in-JS libraries provide vendor prefixes out-of-the-box. This is a great time saver because developers do not have to figure out which features require a vendor prefix in older browsers.

Disadvantages of CSS-in-JS

CSS-in-JS is certainly not without its drawbacks. There have been several instances where project developers have abandoned it in favor of more traditional CSS approaches. Here are a couple of reasons why:

  • Runtime Overhead: As components render, the CSS-in-JS library must convert styles into plain CSS to be inserted into the document. There is some debate as to whether or not this can have a noticeable impact on application performance. That would likely depend on a number of factors from code complexity to hardware.
  • Larger Bundle Size: Every user who uses your application has to download the JavaScript for the CSS-in-JS library. Emotion is 7.9 kB minzipped and styled-components is 12.7 kB. React + react-dom is 44.5 kB for comparison, so a CSS-in-JS library probably won’t be the straw that breaks the camel’s back.

Final Thoughts on CSS-in-JS

This tutorial presented some of the common features of CSS-in-JS, as well as its strengths and weaknesses. While CSS-in-JS does offer many benefits, do not be too quick to jump on the CSS-in-JS bandwagon just because all your friends are doing it. Be sure to weigh all of its pros and cons before making a decision. Although CSS-in-JS might be just what you need, there may also be tradeoffs that you’re just not willing to accept.