Styling

Basic styling examples with Stitches.

In order to keep the bundle size to a minimum, Stitches uses JavaScript object notation rather than string syntax. Below, are examples of all of the common use cases.

For handling things like global resets, you can write global CSS styles. The globalCss function will return another function, which you must call in your app.

const globalStyles = globalCss({
'*': { margin: 0, padding: 0 },
});
() => {
globalStyles();
return <div ... />
};
const Button = styled('button', {
backgroundColor: 'gainsboro',
borderRadius: '9999px',
fontSize: '13px',
border: '0',
});
() => <Button>Button</Button>;
const Button = styled('button', {
// base styles
'&:hover': {
backgroundColor: 'lightgray',
},
});
() => <Button>Button</Button>;

Note: you must use the & sign to chain selectors.

const Button = styled('button', {
// base styles
'&::before': {
content: `''`,
display: 'block',
backgroundImage: 'linear-gradient(to right, #1fa2ff, #12d8fa, #a6ffcb)',
position: 'absolute',
top: '-3px',
left: '-3px',
width: 'calc(100% + 6px)',
height: 'calc(100% + 6px)',
borderRadius: 'inherit',
zIndex: -1,
},
});
() => <Button>Button</Button>;

Note: you must use the & sign to chain selectors.

const Button = styled('button', {
// base styles
'&.custom-class': {
boxShadow: '0 0 0 3px blueviolet',
},
});
() => <Button className="custom-class">Button</Button>;

In addition to the class selector, you can style all other available basic selectors such as ID selectors, attribute selectors, universal selectors, and type selectors.

Note: you must use the & sign to chain selectors.

const Button = styled('button', {
// base styles
'&[data-custom-attribute]': {
boxShadow: '0 0 0 3px royalblue',
},
});
() => <Button data-custom-attribute>Button</Button>;

Note: you must use the & sign to chain selectors.

const Button = styled('button', {
// base styles
'& svg': {
display: 'inline-block',
verticalAlign: 'bottom',
height: '13px',
marginLeft: '5px',
},
});
() => (
<Button>
Button <svg>...</svg>
</Button>
);
const Button = styled('button', {
// base styles
'& + button': {
marginLeft: '10px',
},
});
() => (
<div>
<Button>Button</Button>
<Button>Button</Button>
</div>
);
const Icon = styled('svg', {
display: 'inline-block',
marginLeft: '5px',
width: '16px',
});
const Button = styled('button', {
// base styles
[`& ${Icon}`]: {
marginLeft: '5px',
},
});
() => (
<Button>
Button
<Icon>...</Icon>
</Button>
);
const RightArrow = () => (
<svg className="right-arrow" ... />
);
// add a `toString` method
RightArrow.toString = () => '.right-arrow';
const Button = styled('button', {
// base styles
[`& ${RightArrow}`]: {
display: 'inline-block',
marginLeft: '5px',
width: '16px',
},
});
() => <Button>Button <RightArrow /></Button>;

Remember to add the toString method on your component. That needs to return a string matching the desired selector. The selector can be anything you want.

const scaleUp = keyframes({
'0%': { transform: 'scale(1)' },
'100%': { transform: 'scale(1.5)' },
});
const Button = styled('button', {
// base styles
'&:hover': {
animation: `${scaleUp} 200ms`,
},
});

You can use at-rules rules in the globalCss, styled and css functions.

const Button = styled('button', {
// base styles
'@media (prefers-reduced-motion)': {
transition: 'none',
},
});

Note: The & qualifier is not required for at-rule statements.

You can use @import rules within the globalCss function.

const globalStyles = globalCss({
'@import': 'custom.css',
});

Or if you need multiple values, use an array:

const globalStyles = globalCss({
'@import': ['custom1.css', 'custom2.css'],
});

You can use @font-face rules within the globalCss function.

const globalStyles = globalCss({
'@font-face': {
fontFamily: 'CustomFont',
src: 'local("CustomFont"), url("CustomFont.woff2")',
},
});

Or if you need multiple values, use an array:

const globalStyles = globalCss({
'@font-face': [
{
fontFamily: 'CustomFont1',
src: 'local("CustomFont1"), url("CustomFont1.woff2")',
},
{
fontFamily: 'CustomFont2',
src: 'local("CustomFont2"), url("CustomFont2.woff2")',
},
],
});

You can use @supports rules in the globalCss, styled and css functions.

const globalStyles = globalCss({
'@supports (display: grid)': {
body: {
display: grid,
},
},
});
const Grid = styled('div', {
'@supports (display: grid)': {
display: grid,
},
});

Stitches is aware of your tokens by using a property-to-token mapping. To apply a token you need to prefix it with a $ sign.

For example, the backgroundColor property automatically maps to the colors tokens.

import { createStitches } from '@stitches/react';
const { styled } = createStitches({
theme: {
colors: {
blue: 'royalblue',
},
},
});
const Button = styled('button', {
backgroundColor: '$blue',
});

You can pick a token from any of your available theme scales by prefixing them with the scale name.

const Button = styled('button', {
// apply a color token to a locally scoped token
$$shadowColor: '$colors$purple500',
boxShadow: '0 0 0 15px $$shadowColor'
// use a token from the sizes scale
marginTop: '$sizes$1'
})

You can create locally scoped tokens by defining them with a $$.

const Button = styled('button', {
$$shadow: 'blueviolet',
boxShadow: '0 0 0 3px $$shadow',
'&:hover': {
$$shadow: 'royalblue',
},
});

You can add styles based on themes by retrieving the dynamically generated theme class.

import { createStitches } from '@stitches/react';
const { styled, createTheme } = createStitches({
theme: {},
});
const myTheme = createTheme({});
const Button = styled('button', {
borderRadius: '9999px',
fontSize: '13px',
border: '0',
[`.${myTheme} &`]: {
backgroundColor: '$blue',
},
});
() => (
<div className={myTheme}>
<Button>Button</Button>
</div>
);

Themes return a class name, not a selector, so make sure to prefix it with a . (dot).

Just like with React, jQuery, and other libraries, Stitches converts numeric values to px, if the CSS property doesn't accept unitless values.

{
fontSize: 13, // `font-size: 13px`
paddingTop: 10, // `padding-top: 10px`
lineHeight: 1, // `line-height: 1`
fontWeight: 500, // `font-weight: 500`
}