An intro to CSS-in-JS libraries
Tags: javascript, react, beginners
Published: 2019-09-08 02:03:04

As so many inspired by [Christopher Chedeau's talk on Facebook's use of CSS in JS](https://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html), many libraries have emerged as a way of implementing the methodology. In fact, when selecting a library, you may yourself slightly overwhelmed with the number of options available.

At the core of each of the libraries is the ability to use them with modern component-based applications. The aim of this article to provide an outline and comparison of four of the libraries that I've used most often:

* Styled-Components
* Emotion
* Glamor
* Aphrodite

## Summary

Library | Template Literal | Object Literal | Automatic Vendor Prefixing | Server-Side Rendering | ClassName Required 
----------------- | ----- | ----- | ----- | ----- | ----- |
styled-components |![tick][tick] | ![tick][tick] | ![tick][tick] | ![tick][tick]| ![cross][cross] |
Emotion           |![tick][tick] | ![tick][tick] | ![tick][tick]| ![tick][tick]| ![cross][cross] |
Glamor            | ![cross][cross] | ![tick][tick]| ![tick][tick]| ![tick][tick]| ![tick][tick]|
Aphrodite         | ![cross][cross] | ![tick][tick]| ![tick][tick]| ![tick][tick]| ![tick][tick]|

[tick]: https://img.icons8.com/color/48/000000/checked-2.png
[cross]: https://img.icons8.com/color/48/000000/delete-sign.png

From the table above, it is clear that many of the key features are shared by all the libraries. In fact, I often find myself choosing a particular CSS-in-JSS library based on syntactic reasons. At the time of writing, that means using **styled-components** for converting preexisting projects to React (for the ability to use template literals) and **Aphrodite** for new projects (for, in my opinion, it's clearer separation of CSS and JS logic).

### Template Literal vs Object Literal

At the time of writing, only **styled-components** and **Emotion** allow you to write styles as template literals. This is a significant advantage for when you are converting an existing codebase to React, as it forces you to do very little modification of the CSS. 

#### Template Literal

```javascript
// Using template literal string in Emotion
const base = css`
  color: hotpink;
`

render(
  <div
    css={css`
      ${base};
      background-color: #eee;
    `}
  >
    This is hotpink.
  </div>
)
```

#### Object Literal

```javascript
// using Object Literal styles in Emotion

const Button = styled.button(
  {
    color: 'darkorchid'
  },
  props => ({
    fontSize: props.fontSize
  })
)

render(
  <Button fontSize={16}>
    This is a darkorchid button.
  </Button>
)
```

### Syntactic Differences

In comparing the syntactic differences between the libraries, it is best to replicate the same element. For these purposes, I will be creating two buttons of different colors.

#### Styled-Components

```javascript
import React from 'react';
import styled, { css } from 'styled-components';
 
const Button = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid #007bff;
  color: #007bff;
  margin: 0.5em 1em;
  padding: 0.25em 1em;
 
  ${props => props.primary && css`
    background: #007bff;
    color: white;
  `}
`;
 
const StyledComponentsLib = () => {
  return (
    <div>
      <Button>Normal Button</Button>
      <Button primary>Primary Button</Button>
    </div>
  );
};
 
export default StyledComponentsLib;
```

#### Emotion

```javascript
import React from 'react';
import styled from '@emotion/styled';
import { css } from '@emotion/core';
 
const Button = styled.button`
  background: transparent;
  border-radius: 3px;
  border: 2px solid #007bff;
  color: #007bff;
  margin: 0.5em 1em;
  padding: 0.25em 1em;
 
  ${props => props.primary && css`
    background: #007bff;
    color: white;
  `}
`;
 
const EmotionLib = () => {
  return (
    <div>
      <Button>Normal Button</Button>
      <Button primary>Primary Button</Button>
    </div>
  );
};
 
export default EmotionLib;
```

#### Glamor

```javascript
import React from 'react';
import { css } from 'glamor';
 
const Button = (props) => {
  const myButton = css({
    background: 'transparent',
    color: '#007bff',
    borderRadius: '3px',
    border: '2px solid #007bff',
    margin: '0.5em 1em',
    padding: '0.25em 1em'
  });
 
  return (
    <button className={css(myButton, props.css)}>{ props.children }</button>
  );
};
 
const GlamorLib = () => {
  const primaryButton = css({
    background: '#007bff',
    color: 'white'
  });
 
  return (
    <div>
      <Button>Normal Button</Button>
      <Button css={primaryButton}>
        Primary Button
     </Button>
    </div>
  );
};
 
export default GlamorLib;
```

#### Aphrodite

```javascript
import React from 'react';
import { StyleSheet, css } from 'aphrodite';

const styles = StyleSheet.create({
  myButton: {
    background: 'transparent',
    color: '#007bff',
    borderRadius: '3px',
    border: '2px solid #007bff',
    margin: '0.5em 1em',
    padding: '0.25em 1em'
  },
  primary: {
    background: '#007bff',
    color: 'white'
  }
});

const Button = (props) => {
  const primaryButton = props.primary && styles.primary;

  return (
    <button className={css(styles.myButton, primaryButton)}>
      { props.children }
    </button>
  );
};

const AphroditeLib = () => {
  return (
    <div>
      <Button>Normal Button</Button>
      <Button primary>Primary Button</Button>
    </div>
  );
};

export default AphroditeLib;
```