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"]
}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.
Import the jsx function from @emotion/core
/** @jsx jsx */
import { jsx } from '@emotion/core'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.
/** @jsx jsx */ import { jsx } from '@emotion/core' render( <div css={{ backgroundColor: 'hotpink', '&:hover': { color: 'lightgreen' } }} > This has a hotpink background. </div> )
String Styles
To pass string styles, you must use css which is exported by @emotion/core, it can be used as a tagged template literal like below.
// this comment tells babel to convert jsx to calls to a function called jsx instead of React.createElement /** @jsx jsx */ import { css, jsx } from '@emotion/core' const color = 'darkgreen' render( <div css={css` background-color: hotpink; &:hover { color: ${color}; } `} > This has a hotpink background. </div> )
Note:
cssfrom@emotion/coredoes 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.
/** @jsx jsx */
import { jsx } from '@emotion/core'
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.
/** @jsx jsx */
import { jsx } from '@emotion/core'
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.