The css Prop

Edit this page

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

Set the jsx pragma at the top of your source file.

/** @jsx jsx */

Similar to a comment containing linter configuration, this configures the jsx babel plugin to use the jsx function instead of React.createElement.

JSX Pragma Babel Documentation

Import the jsx function from @emotion/core

/** @jsx jsx */
import { jsx } from '@emotion/core'

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>
)
This has a hotpink background.

Object Style Documentation.

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>
)
This has a hotpink background.

Note:

css from @emotion/core does 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 the css prop, other css calls, or the styled API.

Style Precedence

  • 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 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.

  1. P component
.css-1 {
  margin: 0;
  font-size: 12px;
  line-height: 1.5;
  font-family: sans-serif;
  color: black;
}
  1. ArticleText component
.css-2 {
  font-size: 14px,
  font-family: Georgia, serif,
  color: darkgray;
}
  1. SmallArticleText component
.css-3 {
  font-size: 10px;
}
  1. 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-elements in your .babelrc your styles will not be applied. The plugin is not compatible with the css prop.