Getting Emotional with React

2 Sep 2019
4 min read

SO WHAT IS IT ? πŸ™„ πŸ™„ πŸ™„

Emotion is a library made for writing CSS styles with JavaScript. It allows you to style apps quickly with string or object styles. The most amazing thing about this library – other than it’s size and performance – is the flexibility of use. It supports strings, objects and functions and makes all the composable goodness possible.

The way this library intertwines itself with your React components is really amazing and it’s a joy to work with.


Add css prop magic to your styles

Emotion gives us CSS prop support. The CSS prop is similar to the style prop available in other libraries but also adds support for nested selectors, media queries, and auto-prefixing.

This provides a concise and flexible API to style my React components. The CSS prop also accepts a function that is called with your theme as an argument allowing developers easy access to common and customizable values.

How do I get started? πŸ€” πŸ€” πŸ€”

First step is to add it via npm or yarn:

yarn add @emotion/core

Now you can just import it like so:

import { css } from '@emotion/core';

or install the @emotion/styled package and import the styled prop like so:

import styled from '@emotion/styled'

Using it with React components

Any component or element that accepts a className prop can also use the css prop. The styles supplied to the css prop are evaluated and the computed class name is applied to the prop.

1.Object Styles

The css prop accepts object styles directly and does not require an additional import. It needs camelCase instead of kebab-case, for example background-color would be backgroundColor

With the css prop
import { css } from '@emotion/core';
render(
  <div
    css={{
      color: 'red',
      backgroundColor: 'gray',
    }}
  >
    This is red.
  </div>,
);
With styled
import styled from '@emotion/styled';
const Button = styled.button(
  {
    color: 'red',
  },
  props => ({
    fontSize: props.fontSize,
  }),
);
render(<Button fontSize={16}>This is a red button.</Button>);
Child Selectors
/* @jsx jsx */
import { css } from '@emotion/core';
render(
  <div
    css={{
      color: 'blue',
      '& .name': {
        color: 'orange',
      },
    }}
  >
    This is blue.
    <div className="name">This is orange</div>
  </div>,
);
import { css } from '@emotion/core';
render(
  <div
    css={{
      color: 'green',
      '@media(min-width: 420px)': {
        color: 'orange',
      },
    }}
  >
    This is orange on a big screen and green on a small screen.
  </div>,
);

For Numbers, Arrays, Fallbacks, Composition refer https://emotion.sh/docs/object-styles. πŸ˜‡ πŸ˜‡ πŸ˜‡

  1. String Styles

To pass string styles, you must use css which is exported by @emotion/core

/** @jsx jsx */
import { css, jsx } from '@emotion/core';
const color = 'green';
render(
  <div
    css={css`
      background-color: pink;
      &:hover {
        color: ${color};
      }
    `}
  >
    This has a pink background.
  </div>,
);
  1. Style Precedence

Two things to keep in mind:

  • Class names containing emotion styles from the className prop override css prop styles.
  • Class names from sources other than emotion are ignored and appended to the computed emotion class name.

The precedence order may seem counter-intuitive, but it allows components with styles defined on the css prop to be customized via the className prop passed from the parent.

The P component in this example has its default styles overridden in the headerComponent.

/** @jsx jsx */
import { jsx } from '@emotion/core';
const P = props => (
  <p
    css={{
      fontSize: 12,
      fontFamily: 'Sans-Serif',
      color: 'black',
      margin: 0,
    }}
    {...props}
  />
);
const headerComponent = props => (
  <P
    css={{
      fontSize: 14,
      color: 'red',
    }}
    {...props} // <- props contains the `className` prop
  />
);
Here is what happens to the originalΒ PΒ component:
.css-1 {
  font-size: 12px;
  font-family: sans-serif;
  color: black;
  margin: 0;
}
and these are the styles applied when the headerComponent component is rendered:
.css-2 {
  font-size: 14px,
  color: red;
}
Result
.css-result {
- font-size: 12px;
+ font-family: 'sans-serif';
- color: black;
+ font-size: 14px,
+ color: red;
+ margin: 0;
}

But how different is this from styled-components? 😈 😈 😈

Emotion does basically have all the features of styled-components but

The Difference is

Size difference via bundlephobia 😒

Now isn’t that amazing! 😎