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.
styled
functionIn 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';
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',
},
});
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': {},
});
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>;
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 } = createStitches({
theme: {
colors: {
red500: 'tomato',
},
space: {
1: '5px',
2: '10px',
},
},
});
const Button = styled('button', {
color: '$red500',
margin: '$1 $2',
});
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 } = createStitches({
media: {
'@bp1': '(min-width: 480px)',
},
});
const Box = styled('div', {
padding: '12px',
'@bp1': {
padding: '24px',
},
});
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
}
`;
export function SCApp() => (
<>
<GlobalStyles />
<div>Your app</div>
</>
);
// Stitches
import { globalCss } from '@stitches/react';
const globalStyles = globalCss({
body: {
margin: '0',
},
});
export function App() => {
globalStyles();
return <div>Your app</div>
}
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,
});
In styled-components, you create ServerStyleSheet
or the StyleSheetManager
depending on your needs.
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.
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.
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.