Stitches homepage
Blog

Migrating from styled-components to Stitches

How to migrate from styled-components to Stitches.

Pedro Duarte

9 min read

This post is about highlighting the main differences between styled-components 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. styled-components and Stitches are two different CSS-in-JS solutions with different concerns.

Importing the styled function

In styled-components, the styled function is a default import.

In Stitches, the styled function is a named import.

// styled-components
import styled from 'styled-components';
// Stitches
import { styled } from '@stitches/react';

Object Syntax Only

In styled-components, 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).

// styled-components
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 styled-components, 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 styled-components, 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.

// styled-components
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 styled-components, you can add a theme via the <ThemeProvider/>. 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.

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

Responsive Styles

In styled-components, 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.

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

Global Styles

In styled-components, you can add global styles with the createGlobalStyle API.

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

// styled-components
import { createGlobalStyle } from 'styled-components';
const GlobalStyles = createGlobalStyle` body { margin: 0 } `;
// Stitches
import { global } from '@stitches/react';
global({
body: {
margin: '0',
},
});

Animations

In styled-components, you can import the keyframes function directly from styled-components.

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

// styled-components
import { keyframes } from 'styled-components';
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 styled-components, you create ServerStyleSheet or the StyleSheetManager depending on your needs.

In Stitches, you use the getCssString 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.

Performance

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

Both @stitches/core and @stitches/react libraries combined weigh in at ~4.7kb 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.