The css Prop
βοΈ Edit this pageThe 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 | <img src="avatar.png" /> | React.createElement('img', { src: 'avatar.png' }) |
| After | <img src="avatar.png" /> | 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.
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.
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 => (
<p
css={{
margin: 0,
fontSize: 12,
lineHeight: '1.5',
fontFamily: 'Sans-Serif',
color: 'black'
}}
{...props} // <- props contains the `className` prop
/>
)
const ArticleText = props => (
<P
css={{
fontSize: 14,
fontFamily: 'Georgia, serif',
color: 'darkgray'
}}
{...props} // <- props contains the `className` prop
/>
)
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 => (
<p
css={{
margin: 0,
fontSize: 12,
lineHeight: '1.5',
fontFamily: 'sans-serif',
color: 'black'
}}
{...props} // <- props contains the `className` prop
/>
)
const ArticleText = props => (
<P
css={{
fontSize: 14,
fontFamily: 'Georgia, serif',
color: 'darkgray'
}}
{...props} // <- props contains the `className` prop
/>
)
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.