Stitches
"Stitches: near-zero runtime CSS-in-JS, variants API, theme tokens, responsive styles, SSR support, polymorphic components"
You are an expert in styling applications with Stitches, the near-zero runtime CSS-in-JS library. ## Key Points - Define all design tokens (colors, spacing, font sizes) in the Stitches config rather than using raw values in styled components, ensuring consistency and easy theme switching. - Use the variants API instead of conditional style props — it produces type-safe, statically extractable styles and avoids runtime style recalculation. - Leverage compound variants for style combinations that cannot be expressed as independent variant axes, keeping component APIs clean. - Using the `css` prop excessively for one-off overrides defeats the purpose of atomic CSS generation and can lead to style bloat. Prefer defining variants for recurring patterns. - Forgetting to call `getCssText()` in SSR setups causes a flash of unstyled content on first page load, because styles are only injected client-side by default. ## Quick Example ```bash npm install @stitches/react # or for core (framework-agnostic) npm install @stitches/core ```
skilldb get css-styling-services-skills/StitchesFull skill: 329 linesStitches — CSS & Styling
You are an expert in styling applications with Stitches, the near-zero runtime CSS-in-JS library.
Core Philosophy
Overview
Stitches is a CSS-in-JS library with near-zero runtime, SSR support, and a best-in-class developer experience. It features a first-class variants API for building type-safe, composable component styles. Styles are generated at build time where possible, and it uses atomic CSS output to minimize bundle size. Stitches provides a robust theming system with design tokens and supports responsive variant application. Note: Stitches is currently in maintenance mode but remains widely used in production codebases.
Setup & Configuration
Installation
npm install @stitches/react
# or for core (framework-agnostic)
npm install @stitches/core
Create Stitches Configuration
// stitches.config.ts
import { createStitches } from '@stitches/react'
export const {
styled,
css,
globalCss,
keyframes,
getCssText,
theme,
createTheme,
config,
} = createStitches({
theme: {
colors: {
gray100: '#f7fafc',
gray900: '#1a202c',
blue500: '#3b82f6',
blue600: '#2563eb',
white: '#ffffff',
text: '$gray900',
background: '$white',
primary: '$blue500',
primaryDark: '$blue600',
},
space: {
1: '4px',
2: '8px',
3: '12px',
4: '16px',
5: '20px',
6: '24px',
8: '32px',
},
fontSizes: {
sm: '0.875rem',
base: '1rem',
lg: '1.125rem',
xl: '1.25rem',
'2xl': '1.5rem',
},
radii: {
sm: '4px',
md: '8px',
lg: '12px',
full: '9999px',
},
shadows: {
sm: '0 1px 2px rgba(0, 0, 0, 0.05)',
md: '0 4px 6px rgba(0, 0, 0, 0.1)',
lg: '0 10px 15px rgba(0, 0, 0, 0.1)',
},
},
media: {
sm: '(min-width: 640px)',
md: '(min-width: 768px)',
lg: '(min-width: 1024px)',
xl: '(min-width: 1280px)',
dark: '(prefers-color-scheme: dark)',
},
utils: {
// Margin shorthand
mx: (value: string) => ({ marginLeft: value, marginRight: value }),
my: (value: string) => ({ marginTop: value, marginBottom: value }),
// Padding shorthand
px: (value: string) => ({ paddingLeft: value, paddingRight: value }),
py: (value: string) => ({ paddingTop: value, paddingBottom: value }),
// Size shorthand
size: (value: string) => ({ width: value, height: value }),
// Linear gradient
linearGradient: (value: string) => ({
backgroundImage: `linear-gradient(${value})`,
}),
},
})
Global Styles
// globalStyles.ts
import { globalCss } from './stitches.config'
export const globalStyles = globalCss({
'*': { margin: 0, padding: 0, boxSizing: 'border-box' },
body: {
fontFamily: 'system-ui, -apple-system, sans-serif',
color: '$text',
backgroundColor: '$background',
},
a: { color: 'inherit', textDecoration: 'none' },
})
// Call in App root:
// globalStyles()
SSR Setup (Next.js)
// pages/_document.tsx
import { getCssText } from '../stitches.config'
import { Html, Head, Main, NextScript } from 'next/document'
export default function Document() {
return (
<Html>
<Head>
<style id="stitches" dangerouslySetInnerHTML={{ __html: getCssText() }} />
</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
Core Patterns
Styled Components with Variants
import { styled } from '../stitches.config'
const Button = styled('button', {
// Base styles
fontFamily: 'inherit',
border: 'none',
cursor: 'pointer',
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
fontWeight: 600,
transition: 'all 150ms ease',
// Variants
variants: {
size: {
sm: { fontSize: '$sm', px: '$3', py: '$1', borderRadius: '$sm' },
md: { fontSize: '$base', px: '$4', py: '$2', borderRadius: '$md' },
lg: { fontSize: '$lg', px: '$6', py: '$3', borderRadius: '$md' },
},
color: {
primary: {
backgroundColor: '$primary',
color: '$white',
'&:hover': { backgroundColor: '$primaryDark' },
},
outline: {
backgroundColor: 'transparent',
border: '2px solid $primary',
color: '$primary',
'&:hover': { backgroundColor: '$primary', color: '$white' },
},
ghost: {
backgroundColor: 'transparent',
color: '$primary',
'&:hover': { backgroundColor: '$gray100' },
},
},
fullWidth: {
true: { width: '100%' },
},
},
// Compound variants
compoundVariants: [
{
color: 'outline',
size: 'lg',
css: { borderWidth: '3px' },
},
],
// Default variants
defaultVariants: {
size: 'md',
color: 'primary',
},
})
// Usage — fully type-safe
<Button size="lg" color="outline">Click Me</Button>
<Button fullWidth>Submit</Button>
Theming
import { createTheme } from '../stitches.config'
const darkTheme = createTheme({
colors: {
text: '#f7fafc',
background: '#1a202c',
gray100: '#2d3748',
primary: '#63b3ed',
primaryDark: '#4299e1',
},
})
// Apply theme class to a container or <body>
<div className={darkTheme}>
<App />
</div>
Responsive Variants
const Grid = styled('div', {
display: 'grid',
gap: '$4',
variants: {
columns: {
1: { gridTemplateColumns: '1fr' },
2: { gridTemplateColumns: 'repeat(2, 1fr)' },
3: { gridTemplateColumns: 'repeat(3, 1fr)' },
},
},
defaultVariants: {
columns: 1,
},
})
// Apply different variants at different breakpoints
<Grid columns={{ '@initial': 1, '@sm': 2, '@lg': 3 }}>
<Card />
<Card />
<Card />
</Grid>
Polymorphic Components
const Text = styled('span', {
variants: {
size: {
body: { fontSize: '$base', lineHeight: 1.6 },
heading: { fontSize: '$2xl', fontWeight: 700, lineHeight: 1.2 },
caption: { fontSize: '$sm', color: '$gray900' },
},
},
})
// Render as different HTML elements
<Text as="h1" size="heading">Page Title</Text>
<Text as="p" size="body">Paragraph content</Text>
<Text as="label" size="caption">Field label</Text>
Composing and Overriding Styles
const BaseCard = styled('div', {
padding: '$4',
borderRadius: '$lg',
boxShadow: '$md',
backgroundColor: '$white',
})
const InteractiveCard = styled(BaseCard, {
cursor: 'pointer',
transition: 'transform 200ms ease, box-shadow 200ms ease',
'&:hover': {
transform: 'translateY(-2px)',
boxShadow: '$lg',
},
})
// One-off overrides with css prop
<BaseCard css={{ border: '1px solid $gray100', maxWidth: '400px' }}>
Content
</BaseCard>
Best Practices
- Define all design tokens (colors, spacing, font sizes) in the Stitches config rather than using raw values in styled components, ensuring consistency and easy theme switching.
- Use the variants API instead of conditional style props — it produces type-safe, statically extractable styles and avoids runtime style recalculation.
- Leverage compound variants for style combinations that cannot be expressed as independent variant axes, keeping component APIs clean.
Common Pitfalls
- Using the
cssprop excessively for one-off overrides defeats the purpose of atomic CSS generation and can lead to style bloat. Prefer defining variants for recurring patterns. - Forgetting to call
getCssText()in SSR setups causes a flash of unstyled content on first page load, because styles are only injected client-side by default.
Anti-Patterns
Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.
Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.
Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.
Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.
Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.
Install this skill directly: skilldb add css-styling-services-skills
Related Skills
CSS Modules
"CSS Modules: scoped CSS, composition, global styles, Next.js integration, TypeScript declarations, naming conventions"
Lightning CSS
"Lightning CSS: ultra-fast CSS transformer, bundler, and minifier written in Rust, with modern syntax lowering, vendor prefixing, and CSS modules"
Panda CSS
"Panda CSS: build-time CSS-in-JS, atomic CSS, recipes, patterns, tokens, conditions, RSC compatible, type-safe styles"
Styled Components
"styled-components: CSS-in-JS, tagged template literals, theming, dynamic styles, SSR, global styles, extending"
Tailwind CSS
"Tailwind CSS: utility-first CSS, responsive design, dark mode, custom theme, plugins, @apply, JIT, content configuration, arbitrary values"
UnoCSS
"UnoCSS: instant on-demand atomic CSS engine, presets, shortcuts, rules, variants, attributify mode, icon support, inspector"