Emotion 8

Emotion 8 expands on an already great feature set while nearly doubling performance numbers and removing the need for a babel plugin.

In this release we’ve done some great things such as rewriting the core, removing the need for babel and adding source map support. We’re going to go over the these highlights and more in this article. For all those tiny details check out the changelog.

New Core

Rewritten by Mitchell Hamilton, the core is now powered by stylis.js. This gives us the freedom to support runtime based style merging and prefixing without the need for a babel plugin. Adding stylis.js did increase the size of our bundle, but the emotion package is still only ~5kb gzipped. The increased performance and flexibility makes the size increase a no brainer.

Source Maps

We added the ability to turn on source maps! Enabling them allows developers to navigate directly to the location of their style definitions.

source map documentation

Development environment only.

The Babel Plugin Is No Longer Required

It is highly recommended, but optional.

The following features are enabled when using the babel plugin.

  • `styled.div` syntax
    styled('div') will work without the plugin
  • Minification
    Any leading/trailing space between properties in your css and styled blocks is removed. This can reduce the size of your final bundle.
  • /*#__PURE__*/ flag injection
    Uglifyjs will use these special comments to mark your css and styled as candidates for dead code elimination.
  • Static Extraction
    Static extraction can only work with the babel plugin.
  • Source Maps
    When enabled, source-maps allow you to navigate directly to the location of your styles in Javascript files.
  • css prop
    The css prop is just a shortcut for calling the css function and appending the result to the className prop. We do this all at compile time.

Babel plugin installation documentation

Emotion 8 running in CodeSandbox without the babel plugin

Performance

We’ve nearly doubled the performance of styled components compared to version 7! Benchmarks are run on every build to ensure there are no performance regressions.

We use a forked version of the benchmarks created by Nicolas Gallagher for react-native-web.

Theming

emotion-theming is available on npm as of version 8. We forked styled-component’s theming components and built theming directly into react-emotion. The major takeaway here is that wrapping styled components in withTheme is no longer required. If you are currently using the theming library it will continue to work while you migrate.

theming documentation

Composes Is No Longer Supported (Breaking Change)

The behavior is nearly the same, just remove the composes property and put a semi colon between each expression. This means you can no longer apply arbitrary class names to a styled component.

const Link = styled.a`
composes: ${css`color: blue;`} ${css`display: flex;`};
`

Would need to be updated to

const Link = styled.a`
${css`color: blue;`};
${css`display: flex;`};
`

There is a codemod that does this for you.

withComponent

This is a great feature from styled-components. In order to make the switch easier for users we added the API.

const View = styled.div`
color: darkorchid;
}
const Link = View.withComponent('a')

withComponent documentation

Configurable Imports

If you are using ES Module imports the emotion babel plugin can handle two types of import renaming.

Dynamic

import something, { css as emotion } from ‘react-emotion’;
const classes = emotion`
color: red;
`
export default something.div`
background: blue;
`

Babel Opts

The emotion babel plugin can also handle using babel options to handle
processing via the importedNames key. This is useful for targeting
a prop other than css for processing.

{
“plugins”: [
[“emotion”, { “importedNames”: { “css”: “emotion” }}]
]
}

This can be incredibly useful if you want to migrate to emotion in stages. For instance, when coming from styled-components, emotion can be used instead of styled to avoid conflicts. Similarly, emotion could be used instead of css when coming from glamor.

configurable import documentation

Component As Selector Removed (Breaking Change)

The following is no longer supported.

const Link = styled.a`
${css`color: blue;`};
${css`display: flex;`};
`
const View = styled.div`
${Link} {
color: darkorchid;
}
}

Support for this feature requires the babel plugin. It also drastically complicated the emotion codebase for minimal return. Read more here.

Import Shortcuts Removed (Breaking Change)

In order to ensure that there is only one instance of the emotion stylesheet at any given time we have removed the emotion/react , emotion/babel , and emotion/server shortcuts. You must install react-emotion , babel-plugin-emotion , and emotion-server respectively.

Note that react-emotion exports all of emotion so you can import css and friends from react-emotion.

import styled, {
css,
sheet,
injectGlobal,
keyframes,
fontFace
} from 'react-emotion'

We’ve put a ton of work into this release and it shows. Developer experience and performance really shine in Emotion 8. With it being easier than ever to try, what are you waiting for?

Useful Emotion Links