Stitches homepage

Migrating from Emotion to Stitches

How to migrate from Emotion to Stitches.

Pedro Duarte

9 min read

This post is about highlighting the main differences between Emotion and Stitches. Some of these differences are related to the authoring experience. Others are about what happens behind the scenes.

Disclaimer: This post isn't about comparing which one is best. Emotion and Stitches are two different CSS-in-JS solutions with different concerns.

Importing the styled function

In Emotion, the styled function is a default import.

In Stitches, the styled function is a named import.

// Emotion
import styled from '@emotion/styled';
// Stitches
import { styled } from '@stitches/react';

Object Syntax Only

In Emotion, you can write CSS in template strings or in an object syntax.

In Stitches, you write CSS using the object style syntax. The reasons for this are: performance, bundle size and developer experience (type checks and autocomplete suggestions for both properties and values).

// Emotion (string syntax)
const Button = styled.button` color: red; font-size: 14px; :hover { color: black; font-size: 14px; } `;
// Stitches
const Button = styled('button', {
color: 'red',
fontSize: '14px';
'&:hover': {
color: 'black',
fontSize: '14px';

Chaining selectors

In Emotion, pseudo-classes and pseudo-selectors are automatically chained to the scoped selector. However, other selectors, such as class or id selectors, require the & sign, otherwise they're considered descendants.

In Stitches, all chained selectors require the & sign.

const Button = styled.button` // chained :hover { } // chained ::before { } // descendant .class { } `;
// Stitches
const Button = styled('button', {
// all chained
'&:hover': {},
'&::before': {},
'&.class': {},

Prop Interpolation vs Variants

In Emotion, you can interpolate the component's props to conditionally set styles.

In Stitches, we've introduced the concept of variants. You can conditionally apply variants at the consumption level, including at different breakpoints.

// Emotion
const Button = styled.button` ${(props) => props.color === 'violet' && ` background-color: 'blueviolet' `} ${(props) => props.color === 'gray' && ` background-color: 'gainsboro' `} `;
// Stitches
const Button = styled('button', {
variants: {
color: {
violet: { backgroundColor: 'blueviolet' },
gray: { backgroundColor: 'gainsboro' },
() => <Button color="violet">Button</Button>;

Tokens and Themes

In Emotion, you can add a theme via the <ThemeProvider/>. For this, you need to install an additional emotion-theming package. The theme gets injected to every component, and you can access it via prop interpolation.

In Stitches, you can define tokens in the config file and seamlessly consume and access directly in the Style Object.

// Emotion
import { ThemeProvider } from 'emotion-theming';
() => (
<ThemeProvider theme={{ colors: { red500: 'tomato', }, space: { 1: '5px', 2: '10px', }, }} >
<App />
const Button = styled.button`
color: ${(props) => props.theme.colors.red500};
margin: ${(props) => `${[1]} ${[2]`}; `;
// Stitches
const { styled } = createStitches({
tokens: {
colors: {
red500: 'tomato',
space: {
1: '5px',
2: '10px',
const Button = styled('button', {
color: '$red500',
margin: '$1 $2',

Responsive Styles

In Emotion, you can add at-rules directly in the CSS.

In Stitches, you can do the same. But you can also define breakpoints in the media object and access directly in the Style Object.

// Emotion
const Box = styled.div` padding: 12px; @media (min-width: 480px) { padding: 24px; } `;
// Stitches
const { styled } = createStitches({
media: {
'@bp1': '(min-width: 480px)',
const Box = styled('div', {
padding: '12px',
'@bp1': {
padding: '24px',

Global Styles

In Emotion, you can add global styles with the Global component from the @emotion-core package.

In Stitches, you can use the global API. Learn more here.

// Emotion
import { Global } from '@emotion/core';
export function EmotionApp() => (
<Global styled={{ body: { margin: '0' }, }} />
// Stitches
import { globalCss } from '@stitches/react';
const globalStyles = globalCss({
body: {
margin: '0',
export function App() => {
return <div>Your app</div>


In Emotion, you can import the keyframes function from @emotion/core.

In Stitches, you can use the keyframes function. Learn more here.

// Emotion
import { keyframes } from '@emotion/core';
import style from '@emotion/styled';
const fadeIn = keyframes` 0% { opacity: 0 } 100% { opacity: 1 } `;
const Box = styled.div` animation-name: ${fadeIn}; `;
// Stitches
import { keyframes } from '@stitches/react';
const fadeIn = keyframes({
'0%': { opacity: '0' },
'100%': { opacity: '1' },
const Box = styled('div', {
animationName: fadeIn,

Server-Side Rendering

In Emotion, there are two ways to server-side render. Each with their own pros and cons. You can read more about it here. The default approach is to rely on renderToString from react-dom/server. The advanced approach is to rely on several packages from @emotion/core, create-emotion-server and @emotion/cache.

In Stitches, you use the getCssText function. Learn more about server-side rendering. Many UI libraries document that responsive variants don't work with server-side rendering. Stitches supports cross-browser server-side rendering, even for responsive styles and variants.

Stitches is a lightweight, performant styling library with a focus on component architecture and developer experience.


Stitches avoids unnecessary prop interpolations at runtime, making it more performant than other styling libraries.

Both @stitches/core and @stitches/react libraries weigh in at ~6kb gzipped.

Developer Experience

Stitches is built on TypeScript. By default, everything you do in Stitches will be type checked. As a user, you'll be suggested autocompletion for CSS Properties, token usage in values, breakpoints and related element attributes. Variants are also typed automatically.

A video showing how to add variants to a component.

When choosing a CSS-in-JS library, keep in mind what your goals are. As demonstrated in this article, both libraries are capable of achieving many of the same goals.

If you decide to give Stitches a try, make sure to check out our GitHub, Twitter and Discord.

Share this post on Twitter.