Migrate from Emotion
Differences with Emotion and migration guide to xstyled.
Differences with Emotion
Declarative components
xstyled is similar to Emotion css
prop with some benefits. As a picture is better than 1000 words, take this example:
Using Emotion
/** @jsx jsx */ import { jsx, css } from '@emotion/react' const Button = ({ children }) => { return ( <button css={{ padding: '0.5rem 1rem', color: 'white', borderRadius: '0.375rem', fontWeight: 600, transition: 'background-color cubic-bezier(0.4, 0, 0.2, 1) 150ms', backgroundColor: '#10b981', '&:hover': { backgroundColor: '#065f46', }, '&:focus': { outline: 'none', boxShadow: '0 0 0 3px #10b98180', }, }} > {children} </button> ) }
Using xstyled
import { x } from '@xstyled/emotion' const Button = ({ children }) => ( <x.button py={2} px={4} color="white" borderRadius="md" fontWeight="semibold" transition bg={{ _: 'emerald-500', hover: 'emerald-800' }} outline={{ focus: 'none' }} ring={{ focus: 'none' }} ringColor={{ focus: 'emerald-500-a50' }} > {children} </x.button> )
As you can see xstyled is fully declarative and much more productive than using emotion.
Read declarative components guide to learn more about this approach.
Enhanced css
We know you could not be convinced by x.*
approach. That's why xstyled could help you to be more productive with enhanced css
approach too.
Most projects follow a design system, a set of space, colors, fonts.. that define the constraints and the universe of a project.
To follow a design system with emotion, the common way is to use the theme.
Using Emotion
/** @jsx jsx */ import { jsx } from '@emotion/react' const Button = ({ children }) => { return ( <button css={(theme) => ({ padding: `${theme.space[2]} ${theme.space[4]}`, color: theme.colors.white, borderRadius: theme.radii.md, fontWeight: theme.fontWeights.semibold, transition: theme.transition.default, backgroundColor: theme.colors['emerald-500'], '&:hover': { backgroundColor: theme.colors['emerald-800'], }, '&:focus': { outline: 'none', boxShadow: theme.shadows['emerald-ring'], }, })} > {children} </button> ) }
Using xstyled
/** @jsx jsx */ import { jsx } from '@xstyled/emotion' const Button = ({ children }) => { return ( <button css={{ paddingTop: 2, color: 'white', borderRadius: 'md', fontWeight: 'semibold', transition: 'default', backgroundColor: 'emerald-500', '&:hover': { backgroundColor: 'emerald-800', }, '&:focus': { outline: 'none', boxShadow: 'emerald-ring', }, }} > {children} </button> ) }
Read enhanced styled components guide to learn more about this approach.
Responsive utilities
xstyled has great responsive utilities to simplify usage of media queries.
Using Emotion
/** @jsx jsx */ import { jsx } from '@emotion/react' const Button = ({ children }) => { return ( <button css={{ width: 200, '@media (min-width: 768px)': { width: 300 } }}> {children} </button> ) }
Using xstyled
import { x } from '@xstyled/emotion' const Button = ({ children }) => { return <x.button w={{ _: 200, md: 300 }}>{children}</x.button> }
Replacing Emotion by xstyled
@xstyled/emotion
is a replacement of @emotion/react
and @emotion/styled
. You can safely replace @emotion/react
and @emotion/styled
by @xstyled/emotion
.
Once your code is using xstyled, you can start using declarative components (x.*
) and enhanced styled components (styled.*
).
JSX Pragma
JSX Pragma is exposed in @xstyled/emotion
:
/** @jsx jsx */ import { jsx } from '@xstyled/emotion' const Button = ({ children }) => { return ( <button css={{ paddingTop: 2, color: 'white', borderRadius: 'md', }} > {children} </button> ) }
Babel preset
To avoid the /** @jsx jsx */
you can use @xstyled/babel-preset-emotion-css-prop
. It has the same interface as @emotion/babel-preset-css-prop
, see Emotion documentation.
.babelrc
{ "presets": ["@xstyled/babel-preset-emotion-css-prop"] }
Babel Plugin
You may want to use Emotion Babel plugin for minification of styles, dead code elimination, components as selectors, and a nicer debugging experience.
.babelrc
{ ..., "presets": [ [ "@xstyled/babel-preset-emotion-css-prop", { // @emotion/babel-plugin options // https://emotion.sh/docs/@emotion/babel-plugin } ] ] }
Note: importMap
has some known issues coming from Emotion side
Difference in css
prop usage
css
prop with @xstyled/emotion
is slightly different from css
prop with @emotion/react
.
theme
is accessible as a destructured object{ theme }
- When using a function, you have to wrap your style in
css
With Emotion
/** @jsx jsx */ import { jsx } from '@emotion/react' const Button = ({ children }) => { return ( <button css={(theme) => ({ paddingTop: theme.space[1], })} > {children} </button> ) }
With xstyled
Edit this page on GitHub/** @jsx jsx */ import { jsx } from '@xstyled/emotion' const Button = ({ children }) => { return ( <button css={({ theme }) => css({ paddingTop: theme.space[1], }) } > {children} </button> ) }