File: README.md
Emotion 11 has been released ๐ See the blog post
Emotion is a performant and flexible CSS-in-JS library. Building on many other CSS-in-JS libraries, it allows you to style apps quickly with string or object styles. It has predictable composition to avoid specificity issues with CSS. With source maps and labels, Emotion has a great developer experience and great performance with heavy caching in production.
[๐ Demo Sandbox](https://codesandbox.io/s/pk1qjqpw67)
[๐ Docs](https://emotion.sh/docs/introduction)
Frequently viewed docs:
Quick Start
Get up and running with a single import.
npm install --save @emotion/react/** @jsx jsx */
import { jsx } from '@emotion/react'
let SomeComponent = props => {
return (
)
}Do I Need To Use the Babel Plugin?
The babel plugin is not required, but enables some optimizations and customizations that could be beneficial for your project.
Look here ๐ emotion babel plugin feature table and documentation
Demo Sandbox
Examples
- emotion website [Demo Here]
- next-hnpwa-guide-kit [Demo Here]
- reactivesearch, a react UI library for Elasticsearch [Website]
- circuit-ui, a react component library built at SumUp [Storybook]
- open a PR and add yours!
Ecosystem
- stylelint - A mighty, modern linter that helps you avoid errors and enforce conventions in your styles.
- facepaint
- emotion-vue
- nuxt-community/emotion-module - Emotion module for Nuxt.js
- ember-emotion
- CSS to emotion transform
- ShevyJS
- design-system-utils - Utilities to give better access to your design system.
- polished - Lightweight set of Sass/Compass-style mixins/helpers for writing styles in JavaScript.
- monad-ui - Utility First CSS-In-JS
- css-in-js-media - you can deal with responsive design using css-in-js easily with this
css-in-js-mediawhich is similar with include-media - emotion-native-extended - Better styling support for Emotion Native with React Native Extended Stylesheet
In the Wild
- feathery.io
- frontity.org
- abacusfi.com
- healthline.com
- nytimes.com
- vault.crucible.gg
- render.com
- gatsbythemes.com
- blazity.com
- postmates.com
- thedisconnect.co
- zefenify.com
- sentry.io
- comparett.com
- Domain.com.au
- cyberhaven.com
- CommercialRealEstate.com.au
- codecademy.com
- Apache Superset
Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor]
Backers
Thank you to all our backers! ๐ [Become a backer]
Contributors
This project exists thanks to all the people who contribute. [Contribute].
File: docs/babel.mdx
title: 'Babel Plugin'
@emotion/babel-plugin is highly recommended. All of the options that can be provided to @emotion/babel-plugin are documented in @emotion/babel-plugin's README.
Install
In emotion version 8 and above, installation is optional. In older versions, installation is required. See the installation instructions.
Features which are enabled with the babel 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.
Dead Code Elimination
Uglifyjs will use the injected /*#__PURE__*/ flag comments to mark your css and styled blocks as candidates for dead code elimination.
Source Maps
When enabled, navigate directly to the style declaration in your javascript file.
Components as selectors
The ability to refer to another component to apply override styles depending on nesting context. Learn more in the styled docs.
File: docs/babel-macros.mdx
title: 'Babel Macros'
Create React App recently added support for Babel Macros which makes it possible to run Babel transforms without changing a Babel config.
All of Emotion's Babel Macros are available by adding /macro to the end of the import you'd normally use. (assuming you're using Create React App v2 or you've added babel-plugin-macros to your .babelrc) For example, to use the macro for styled, use @emotion/styled/macro.
import styled from '@emotion/styled/macro'
import { jsx, css, Global, keyframes } from '@emotion/react/macro'
import { css, keyframes, injectGlobal } from '@emotion/css/macro'Note
There are some optimisations which aren't possible with Babel Macros, so if it's possible, we still recommend using @emotion/babel-plugin
File: docs/best-practices.mdx
title: 'Best Practices'
Emotion is an extremely flexible library, but this can make it intimidating, especially for new users. This guide contains several recommendations for how to use Emotion in your application. Keep in mind, these are only recommendations, not requirements!
Recommendations
Use TypeScript and object styles
You don't get Intellisense or type checking when using CSS strings, e.g. css`color: blue`. You can improve the developer experience and prevent style bugs by using TypeScript and object styles, which enable Intellisense and some static type checking:
const myCss = css({
color: 'blue',
grid: 1 // Error: Type 'number' is not assignable to type 'Grid | Grid[] | undefined'
})Colocate styles with components
With normal CSS, the styles for a component are defined in a separate file. This makes maintenance more difficult because it's harder to tell which components use a given piece of CSS, and you can easily forget to update the relevant CSS after modifying a component. One of the main benefits of Emotion is that you can colocate your styles with your components. All this means is that the CSS for a component should be in the same file as the component itself.
Consider how you will share styles
There are two main approaches for sharing styles across an Emotion application.
To illustrate the two methods, let's imagine we're developing an application that needs to display error messages in many different components. All of the error messages should be red and bold. Some error messages should also use a large font.
Method 1: Export CSS objects
The simplest way to share styles is to export CSS from a shared file and then import that CSS in many places:
export const errorCss = css({
color: 'red',
fontWeight: 'bold'
})
// Use arrays to compose styles
export const largeErrorCss = css([errorCss, { fontSize: '1.5rem' }])Then, in one of your components:
import { errorCss } from '...'
return Failed to fizzle the frozzle.This method is great when you only want to share CSS between components. A potential drawback of this method is that shared styles are not colocated with the components that use them.
Method 2: Share styles via component reuse
This method is slightly more complex but arguably more powerful than the previous method.
export function ErrorMessage({ className, children }) {
return (
{children}
)
}
// `fontSize: '1.5rem'` is passed down to the ErrorMessage component via the
// className prop, so ErrorMessage must accept a className prop for this to
// work!
export function LargeErrorMessage({ className, children }) {
return (
<ErrorMessage css={{ fontSize: '1.5rem' }} className={className}>
{children}
</ErrorMessage>
)
}Then, in one of your components:
import { ErrorMessage } from '...'
return <ErrorMessage>Failed to fizzle the frozzle.</ErrorMessage>Advantages of sharing styles via component reuse include:
- Component reuse allows you to share both logic and styles. You can easily add additional props and functionality to the
ErrorMessagecomponent with limited refactoring. - Styles are always colocated with their components.
Use the `style` prop for dynamic styles
The css prop or styled should be used for static styles, while the style prop (inline styles) should be used for truly dynamic styles. By dynamic styles, we mean styles that change frequently or are unique to a single element.
Imagine you are displaying a list of user avatars in a forum application. Every avatar shares certain static CSS, like width: 40px and border-radius: 50%, but the avatar image is set via a background-image rule whose value is different for each avatar. If you pass all of this CSS through the CSS prop, you'll end up with a lot of nearly-duplicate CSS in the document. With 3 avatars, Emotion will create something like:
<style>
.css-1udhswa {
border-radius: 50%;
width: 40px;
height: 40px;
background-image: url(https://i.pravatar.cc/150?u=0);
}
.css-1cpwmbr {
border-radius: 50%;
width: 40px;
height: 40px;
background-image: url(https://i.pravatar.cc/150?u=1);
}
.css-am987o {
border-radius: 50%;
width: 40px;
height: 40px;
background-image: url(https://i.pravatar.cc/150?u=2);
}
</style>Now imagine how much CSS there would be if there were 100 avatars on the page!
You should also use the style prop if the styles will be updated frequently. If your application lets a user drag and drop an element, you likely have a transform property like
{
transform: `translate(${x}px, ${y}px)`
}This property should go through the style prop since x and y will change rapidly as the element is dragged.
Advanced: CSS variables with `style`
CSS variables can be used with the style prop to keep the CSS in a single place while "deferring" the actual value of a property. Going back to the avatar example above, you could define the following static CSS using the css prop:
.avatar {
border-radius: 50%;
width: 40px;
height: 40px;
background-image: var(--background-image);
}Then, for each avatar, you render an element which sets the value of the --background-image CSS variable:
function Avatar({ imageUrl }) {
return
}If you're using TypeScript, you'll have to use a type assertion like style={{ ['--background-image' as any]: imageUrl }} as explained here.
If using React, prefer `@emotion/react` or `@emotion/styled` over `@emotion/css`
@emotion/react and @emotion/styled generally offer a better developer experience over class names (@emotion/css) when using React.
Use the css prop or `@emotion/styled`, but not both
While the css prop and styled can peacefully coexist, it's better to pick one approach and use it consistently across your codebase. Whether you choose the css prop or styled is a matter of personal preference. (If you're curious, the css prop is more popular among the maintainers of Emotion.)
Consider defining styles outside your components
For example:
import { css } from '@emotion/react'
const cardCss = {
self: css({
backgroundColor: 'white',
border: '1px solid #eee',
borderRadius: '0.5rem',
padding: '1rem'
}),
title: css({
fontSize: '1.25rem'
})
}
export function Card({ title, children }) {
return (
<h5 css={cardCss.title}>{title}</h5>
{children}
)
}Benefits of this approach:
- Styles are only serialized once, instead of on every render.
- It's no longer possible to accidentally pass dynamic styles through the css prop.
- The JSX is arguably more readable with the CSS separated out into a different part of the file.
Define colors and other style constants as JavaScript variables
Don't repeat yourself! If you are using a color, padding, border radius, .etc throughout your application, add it to your theme or define it as a JavaScript constant, like
export const colors = {
primary: '#0d6efd',
success: '#198754',
danger: '#dc3545'
}Don't use a theme unless your app supports multiple themes (or will eventually support multiple themes)
Emotion allows you to define a theme which you can use in style rules across your application. This feature is awesome if your app has multiple themes, like light mode and dark mode.
On the other hand, if your app will only ever have a single theme, it's simpler to define colors and other style variables as JavaScript constants.
Additional Reading
- Colocation by Kent C. Dodds
- Change how you write your CSS-in-JS for better performance by Michael Dougall
File: docs/cache-provider.mdx
title: 'CacheProvider'
It can be useful to customize emotion's options - i.e. to add custom Stylis plugins, customize prefix of inserted class names, render style tags into specific element and more. You can look up full list of options here.
// @live
import { CacheProvider, css } from '@emotion/react'
import createCache from '@emotion/cache'
import { prefixer } from 'stylis'
const customPlugin = () => {}
const myCache = createCache({
key: 'my-prefix-key',
stylisPlugins: [
customPlugin,
// has to be included manually when customizing `stylisPlugins` if you want
// to have vendor prefixes added automatically
prefixer
]
})
render(
<CacheProvider value={myCache}>
Some text
</CacheProvider>
)File: docs/class-names.mdx
title: 'Class Names'
It can be useful to create a className that is not passed to a component, for example if a component accepts a wrapperClassName prop or similar. To do this, Emotion exposes a render prop component which you can pass a function which accepts css and cx. If you have used versions of Emotion prior to Emotion 10 or used vanilla Emotion, the css and cx functions work exactly like they do in those versions.
// @live
import { ClassNames } from '@emotion/react'
// this might be a component from npm that accepts a wrapperClassName prop
let SomeComponent = props => (
in the wrapper!
{props.children}
)
render(
<ClassNames>
{({ css, cx }) => (
<SomeComponent
wrapperClassName={css({ color: 'green' })}
className={css`
color: hotpink;
`}
>
from children!!
</SomeComponent>
)}
</ClassNames>
)File: docs/community.mdx
title: 'Community'
A curated list of awesome stuff related to Emotion.
Contents
Libraries
- facepaint - Responsive style values for css-in-js
- ember-emotion - Use emotion in Ember.js
- vue-emotion - Use emotion in Vue.js
- CSS to emotion transform
- ShevyJS - Configurable Vertical Rhythm & Typography in CSS-in-JS
- design-system-utils - Utilities to give better access to your design system.
- styled-map - Super simple lib to map props to styles
- polished - Lightweight set of Sass/Compass-style mixins/helpers for writing styles in JavaScript
- styled-conditions - Ultra-lightweight flag utility to conditionally apply css depending on React props
- manipulative - React devtool to style emotion components from the browser
- emotion-tailwind-preflight - Merge the shiny TailwindCSS base styles into your CSS-in-JS project
Component Libraries
- react-select (Website)
- reactivesearch (Website)
- circuit-ui (Storybook)
- govuk-react (Storybook)
- smooth-ui (Website)
- material-ui (Website)
- mineral-ui (Website)
- sancho-ui (Website)
Examples In the Wild
- healthline.com
- nytimes.com
- vault.crucible.gg
- saldotuc.com
- gatsbythemes.com
- blazity.com
- postmates.com
- thedisconnect.co
- zefenify.com
- strelkamag.com
- rookout.com
- figma.com
- designsystems.com
File: docs/composition.mdx
title: 'Composition'
Composition is one of the most powerful and useful patterns in Emotion. You can compose styles together by interpolating value returned from css in another style block.
// @live
import { css } from '@emotion/react'
const base = css`
color: hotpink;
`
render(
This is hotpink.
)With regular css, you can compose styles together using multiple class names, but this is very limited because the order that they're defined is the order they'll be applied. This can lead to hacks with !important and such to apply the correct styles.
For example, we have some base styles and a danger style, we want the danger styles to have precedence over the base styles but because base is in the stylesheet after danger its styles will override the styles defined in danger, as per the cascade rules. In regular CSS, you might do something to make danger take precedence over base like moving the danger class so it's defined later than base, or use !important, or abandon composition and rewrite the styles each time you need them.
// @live
render(
<style>
{`
.danger {
color: red;
}
.base {
background-color: lightgray;
color: turquoise;
}
`}
>
</style>
What color will this be?
)With Emotion though, you can create styles and combine them.
// @live
import { css } from '@emotion/react'
const danger = css`
color: red;
`
const base = css`
background-color: darkgreen;
color: turquoise;
`
render(
This will be turquoise
This will be also be turquoise since the base styles overwrite the danger
styles.
This will be red
)Using Emotion's composition, you don't have to think about the order that styles were created because the styles are merged in the order that you use them.
File: docs/css-prop.mdx
title: 'The css Prop'
The primary way to style elements with emotion is the css prop. It provides a concise and flexible API to style your components.
Get Started
There are 2 ways to get started with the css prop.
Both methods result in the same compiled code.
After adding the preset or setting the pragma as a comment, compiled jsx code will use emotion's jsx function instead of React.createElement.
| Input | Output | |
|---|---|---|
| Before | `` | React.createElement('img', { src: 'avatar.png' }) |
| After | `` | jsx('img', { src: 'avatar.png' }) |
Babel Preset
This method will not work with Create React App or other projects that do not allow custom Babel configurations.
Use the JSX Pragma method instead.
.babelrc
{
"presets": ["@emotion/babel-preset-css-prop"]
}If you are using the compatible React version (>=16.14.0) then you can opt into using the new JSX runtimes by using such configuration:
.babelrc
{
"presets": [
[
"@babel/preset-react",
{ "runtime": "automatic", "importSource": "@emotion/react" }
]
],
"plugins": ["@emotion/babel-plugin"]
}In case you want to use the new JSX runtimes with Next.js and you are using their next/babel preset then the configuration should look like this:
.babelrc
{
"presets": [
[
"next/babel",
{
"preset-react": {
"runtime": "automatic",
"importSource": "@emotion/react"
}
}
]
],
"plugins": ["@emotion/babel-plugin"]
}JSX Pragma
Set the jsx pragma at the top of your source file that uses the css prop.
This option works best for testing out the css prop feature or in projects where the babel configuration is not configurable (create-react-app, codesandbox, etc.).
/** @jsx jsx */Similar to a comment containing linter configuration, this configures the jsx babel plugin to use the jsx function instead of React.createElement.
If you are using a zero-config tool with automatic detection of which runtime (classic vs. automatic) should be used and you are already using a React version that has the new JSX runtimes (hence runtime: 'automatic' being configured automatically for you) such as Create React App 4 then /** @jsx jsx */ pragma might not work and you should use /** @jsxImportSource @emotion/react */ instead.
Import the `jsx` function from `@emotion/react`
/** @jsx jsx */
import { jsx } from '@emotion/react'Note that excluding this will cause your css to render as [Object Object].
Use the `css` prop
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 className prop.
Object Styles
The css prop accepts object styles directly and does not require an additional import.
// @live
render(
This has a hotpink background.
)String Styles
To pass string styles, you must use css which is exported by @emotion/react, it can be used as a tagged template literal like below.
// @live
import { css } from '@emotion/react'
const color = 'darkgreen'
render(
This has a hotpink background.
)Note:
cssfrom@emotion/reactdoes not return the computed class name string. The function returns an object containing the computed name and flattened styles. The returned object is understood by emotion at a low level and can be composed with other emotion based styles inside of thecssprop, othercsscalls, or thestyledAPI.
You can also pass in your css as variables, which allows for composition (read more about this here).
Style Precedence
- Class names containing emotion styles from the
classNameprop overridecssprop 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 ArticleText component.
const P = props => (
)
const ArticleText = props => (
)The ArticleText component can be customized and the styles composed with its default styles. The result is passed P and the process repeats.
const P = props => (
)
const ArticleText = props => (
)
const SmallArticleText = props => (
<ArticleText
css={{
fontSize: 10
}}
{...props} // <- props contains the `className` prop
/>
)The styles are concatenated together and inserted via insertRule.
Pcomponent
.css-1 {
margin: 0;
font-size: 12px;
line-height: 1.5;
font-family: sans-serif;
color: black;
}ArticleTextcomponent
.css-2 {
font-size: 14px;
font-family: Georgia, serif;
color: darkgray;
}SmallArticleTextcomponent
.css-3 {
font-size: 10px;
}- Result
.css-result {
+ margin: 0;
- font-size: 12px;
+ line-height: 1.5;
- font-family: 'sans-serif';
- color: black;
- font-size: 14px;
+ font-family: Georgia, serif;
+ color: darkgray;
+ font-size: 10px;
}Relying on the css spec's "Order of Appearance" rule, property values defined later (green) override those before it (red).
Gotchas
- If you include the plugin
@babel/plugin-transform-react-inline-elementsin your.babelrcyour styles will not be applied. The plugin is not compatible with thecssprop. - When using
React.cloneElementyou can't easily add a css prop if the cloned element doesn't already have it. OtherwiseReact.cloneElementworks withjsx-created elements.
File: docs/emotion-11.mdx
title: 'Emotion 11'
Emotion 11 is a slight evolution over the Emotion 10. It focuses mainly on the developer experience, TS types improvements, switches internals to hooks and to the new version of the parser that we use: Stylis.
Package renaming
One of the most significant changes is that most of the user-facing packages have been renamed.
Most of this renaming can be done automatically via a codemod, following these steps:
- Install
@emotion/eslint-plugin - Add it as a plugin to
.eslintrc - Add Emotion 11 codemod rule
- Run
eslintwith the--fixflag. For example:yarn eslint --config .eslintrc --ext .js,.jsx "." --fix
The full list of renamed packages:
@emotion/coreโ@emotion/reactemotionโ@emotion/cssemotion-themingโ moved into@emotion/reactemotion-serverโ@emotion/servercreate-emotionโ@emotion/css/create-instancecreate-emotion-serverโ@emotion/server/create-instancebabel-plugin-emotionโ@emotion/babel-plugineslint-plugin-emotionโ@emotion/eslint-pluginjest-emotionโ@emotion/jest
Hooks
Use hooks internally for improved bundle size and a better tree in React DevTools ๐.
TypeScript
Types overhaul
TypeScript types have been significantly restructured.
- reduce build times when using Emotion, especially in larger projects
- it's no longer necessary to manually specify generic parameters for your Emotion components in many cases
- union types as props are better supported and should be inferred properly
- the
cssfunction has been restricted to prevent passing invalid types styled's generic parameter has been changed, if you were specifying theComponentTypeyou will need to remove that generic parameterstyledno longer takes a secondExtraPropsparameter - instead of that move it to after thestyledcall. So instead of writingstyled<typeof MyComponent, ExtraProps>(MyComponent)({})you should now be writingstyled(MyComponent)<ExtraProps>({})
If you encounter build issues after upgrade, try removing any manually specified generic types and let them be inferred.
Theme type
It's now easier to provide a type for Theme. Instead of creating custom instances (like before) you can augment the builtin Theme interface like this:
import '@emotion/react'
declare module '@emotion/react' {
export interface Theme {
primaryColor: string
secondaryColor: string
}
}css prop types
The way in which we provide TypeScript support for the css prop has changed. Based on the usage of our JSX factories, we can add support for css prop only for components that support className prop (as our JSX factory functions take the provided css prop, resolve it and pass the generated className to the rendered component).
For the classic runtime this has been implemented using technique described here. What is important - we no longer extend any global interfaces, so people shouldn't bump anymore into type conflicts for the css prop when using different libraries with css prop support, such as styled-components.
For the automatic runtime this has been implemented by exporting JSX namespace from the appropriate entries but this is only supported in TypeScript 4.1 or higher.
However, if you are stuck with older version of TypeScript or using the classic runtime implicitly by using our @emotion/babel-preset-css-prop then it's not possible to leverage css prop support being added conditionally based on a type of rendered component. For those cases we have added a special file that can be imported once to add support for the css prop globally, for all components. Use it like this:
/// <reference types="@emotion/react/types/css-prop" />In this particular case we are forced to extend the existing React.Attributes interface. Previously we've been extending both React.DOMAttributes and JSX.IntrinsicAttributes. This change is really minor and shouldn't affect any consuming code.
Stylis v4
The parser we use (Stylis) got upgraded. It fixes some long-standing parsing edge cases while being smaller and faster ๐
It has been completely rewritten and comes with some breaking changes. The most notable ones that might affect Emotion users are:
- plugins written for the former Stylis v3 are not compatible with the new version. To learn more on how to write a plugin for Stylis v4 you can check out its README and the source code of core plugins.
- vendor-prefixing was previously customizable using
prefixoption. This was always limited to turning off all of some of the prefixes as all available prefixes were on by default. Theprefixoption is gone and to customize which prefixes are applied you need to fork (copy-paste) the prefixer plugin and adjust it to your needs. While this being somewhat more problematic to setup at first we believe that the vast majority of users were not customizing this anyway. By not including the possibility to customize this through an extra option the final solution is more performant because there is no extra overhead of checking if a particular property should be prefixed or not. - the prefixer is now just a plugin which happens to be included in the default
stylisPlugins. If you plan to use customstylisPluginsand you want to have your styles prefixed automatically you must include prefixer in your customstylisPlugins. You can importprefixerfrom thestylismodule to do that. @importrules are no longer special-cased. The responsibility to put them first has been moved to the author of the styles. They also can't be nested within other rules now. It's only possible to write them at the top level of global styles.
Emotion's caches
The key option is now required when creating a custom instance of a cache. Please make sure it's unique (and not equal to 'css') as it's used for linking styles to your cache. If multiple caches share the same key they might "fight" for each other's style elements.
The new prepend option can make Emotion add style tags at the beginning of the specified DOM container instead of the end.
Other
There are a lot of less substantial changes than what has been described here, some of them might even be breaking changes but are not relevant to the majority of users. Therefore to learn more about all of the changes please read through the full list of changes contained in the respective changelogs:
@emotion/babel-plugin@emotion/babel-preset-css-prop@emotion/cache@emotion/css@emotion/eslint-plugin@emotion/is-prop-valid@emotion/jest@emotion/native@emotion/primitives-core@emotion/primitives@emotion/react@emotion/serialize@emotion/server@emotion/sheet@emotion/styled@emotion/utils