styled-components is a CSS-in-JS library for React. You write real CSS in your JavaScript using tagged template literals, and the library generates unique class names, injects the styles into the page, and hands the styled element back to you as an ordinary React component. The result is component-scoped styling with no class-name collisions, full access to your component's props and theme, and automatic critical-CSS handling for server rendering.
This guide is a complete, source-based reference for using styled-components
on the web and in React Native. It is written against the source at
commit 051c829 (published as package version 6.4.1).
Note
styled-components has no command-line interface and no configuration files. It is a library you import into a React application. Everything below is about the JavaScript/TypeScript API you call from your own code.
Table of Contents
- Quick Start
- Installation & Requirements
- Core Concepts
- Creating Styled Components
- Passing Props Into Styles
- Reusable Styles with
css - Animations with
keyframes - Global Styles with
createGlobalStyle - Theming
attrs— Default & Computed Props- Controlling What Reaches the DOM
- Server-Side Rendering
- React Native
- Package Entry Points
- Common Tasks (Recipes)
- TypeScript Usage
- Troubleshooting
- FAQ
- API Quick Reference
1. Quick Start
Install the package and start styling a component in under a minute.
npm
npm install styled-components
yarn
yarn add styled-components
pnpm
pnpm add styled-components
Create your first styled component:
import styled from 'styled-components';
// A <button> with styles baked in.
const Button = styled.button`
background: #0070f3;
color: white;
border: none;
padding: 0.6rem 1.2rem;
border-radius: 6px;
font-size: 1rem;
cursor: pointer;
&:hover {
background: #0059c9;
}
`;
export default function App() {
return <Button>Click me</Button>;
}
When this renders, styled-components:
- Generates a stable, unique class name for
Button(e.g.sc-bdvvtL) plus a hashed class for the compiled CSS. - Injects the CSS into a
<style data-styled="active">tag in the document<head>. - Renders a real
<button>with those classes applied.
<button class="sc-bdvvtL kFxmL0">Click me</button>
Tip
The
&in the template refers to the generated class for this component — exactly like the&in Sass/SCSS. Use it for pseudo-classes (&:hover), nested selectors (& > span), and modifier styles.
2. Installation & Requirements
Install
styled-components ships as a single package on npm. Install it as a regular dependency:
npm install styled-components
Peer dependencies
You must already have React installed. The library declares the following peers:
| Peer | Required version | When you need it |
|---|---|---|
react |
>= 19.0.0 |
Always |
react-dom |
>= 19.0.0 |
Web apps (optional peer) |
react-native |
>= 0.85.0 |
React Native apps (optional peer) |
react-native-reanimated |
>= 4.0.0 |
Only for the Reanimated native adapter (optional peer) |
The only hard runtime dependency styled-components pulls in itself is
csstype (3.2.3), used for CSS
property typings.
Important
This version of styled-components requires React 19 or newer. It uses React 19's ref-as-prop model and does not wrap components in
React.forwardRef. If you are on React 18 or earlier, use an older release of styled-components.
Node version
For building/SSR, Node >= 16 is supported by the package.
TypeScript
TypeScript types ship inside the package (dist/index.d.ts) — there is no
separate @types/styled-components to install for this version. See
TypeScript Usage.
3. Core Concepts
A few ideas underpin everything else in this guide.
Styled component
: A React component produced by styled that renders an HTML element (or wraps
another component) with a fixed set of styles attached. You use it like any
other component: <Button>, <Card as="a">, etc.
Tagged template literal
: The styled.div`...` syntax is a JavaScript tagged template. The CSS goes
between the backticks. You can interpolate values — strings, numbers,
functions of props, other styled components, keyframes, and css blocks.
Interpolation
: Anything you embed with ${...} inside the template. A function interpolation
${props => ...} runs on every render with the component's props (plus
theme), letting styles respond to props dynamically.
Transient prop
: A prop whose name starts with $ (e.g. $active). styled-components reads it
for styling but never forwards it to the underlying DOM element, so it can't
leak into your HTML. See Controlling What Reaches the DOM.
Theme
: A plain object made available to every styled component via React context
through <ThemeProvider>. Inside styles, read it with ${props => props.theme.x}.
Component selector
: Because a styled component's .toString() returns its class selector, you can
interpolate one styled component inside another's CSS to target it:
`& ${Icon} { color: red; }`.
4. Creating Styled Components
Styling an HTML element
Every standard HTML element is available as a property on styled:
const Title = styled.h1`
font-size: 2rem;
font-weight: 700;
`;
const Wrapper = styled.section`
padding: 2rem;
background: papayawhip;
`;
<Wrapper>
<Title>Hello World</Title>
</Wrapper>
Styling another component
Wrap any React component that accepts a className prop:
const StyledLink = styled(RouterLink)`
color: #0070f3;
text-decoration: none;
&:hover {
text-decoration: underline;
}
`;
Note
The wrapped component must spread
classNameonto a DOM element for the styles to apply:const Plain = ({ className, children }) => ( <div className={className}>{children}</div> ); const Fancy = styled(Plain)`color: rebeccapurple;`;
Extending an existing styled component
Call styled() on a styled component to inherit its styles and add more:
const Button = styled.button`
padding: 0.6rem 1.2rem;
border-radius: 6px;
`;
const PrimaryButton = styled(Button)`
background: #0070f3;
color: white;
`;
PrimaryButton carries both the Button class chain and its own — the base
styles come first in the cascade, so the extension wins on conflicts.
The polymorphic as prop
Change the rendered element/component at the call site without redefining styles:
const Button = styled.button`
/* button styles */
`;
// Render an anchor that looks like the button:
<Button as="a" href="/home">Home</Button>
// Render a custom component:
<Button as={RouterLink} to="/home">Home</Button>
There is also forwardedAs, which passes an as prop through to a wrapped
styled component rather than consuming it locally — useful when you wrap a
styled component that itself supports as.
Referring to other components (component selector)
Interpolate a styled component into CSS to target its rendered elements:
const Icon = styled.svg`
fill: currentColor;
transition: fill 0.2s;
`;
const Link = styled.a`
color: #333;
&:hover ${Icon} {
fill: #0070f3;
}
`;
<Link href="#"><Icon /> Settings</Link>
Warning
The component-selector trick only works with styled components. Interpolating a plain (non-styled) component into CSS throws error #13 (
... is not a styled component and cannot be referred to via component selector).
5. Passing Props Into Styles
Function interpolations receive the component's props (with theme merged in)
and run on every render.
const Box = styled.div<{ $padding?: number }>`
padding: ${props => props.$padding ?? 8}px;
`;
<Box $padding={16} />
Conditional styles
const Text = styled.p<{ $muted?: boolean }>`
color: ${props => (props.$muted ? '#888' : '#111')};
font-weight: ${props => (props.$muted ? 400 : 600)};
`;
Whole CSS blocks based on a prop
Combine props with the css helper so the
interpolated styles are processed correctly (and any nested interpolations keep
working):
import styled, { css } from 'styled-components';
const Panel = styled.div<{ $variant: 'info' | 'danger' }>`
border: 1px solid;
padding: 1rem;
${props =>
props.$variant === 'danger'
? css`
border-color: #e00;
background: #fff5f5;
`
: css`
border-color: #0070f3;
background: #f0f7ff;
`}
`;
Tip
Use transient props (
$-prefixed) for any prop that exists only to drive styling. They will not be forwarded to the DOM, so you avoid React's "unknown prop" warnings. See section 11.
6. Reusable Styles with css
The css helper tags a block of CSS so it can be stored in a variable and
reused across components. It also enables interpolation type-checking and is the
correct way to interpolate dynamic CSS that itself contains interpolations.
import { css } from 'styled-components';
const truncate = css`
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
`;
const Title = styled.h2`
${truncate}
font-size: 1.25rem;
`;
css accepts a tagged template, a style object, or a function, and it
supports the same prop/theme interpolations as styled:
const focusRing = css<{ $color?: string }>`
&:focus-visible {
outline: 2px solid ${p => p.$color ?? '#0070f3'};
outline-offset: 2px;
}
`;
Important
When you interpolate a function that returns CSS containing further interpolations (e.g.
${rotate}keyframes inside a${props => ...}), wrap the returned CSS incss\...``. Returning a bare template string instead can trigger error #12 for keyframes.
7. Animations with keyframes
keyframes defines a CSS @keyframes animation with an automatically scoped,
collision-free name. Interpolate the returned value into an animation
declaration.
import styled, { keyframes } from 'styled-components';
const rotate = keyframes`
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
`;
const Spinner = styled.div`
width: 24px;
height: 24px;
border: 3px solid #ccc;
border-top-color: #0070f3;
border-radius: 50%;
animation: ${rotate} 1s linear infinite;
`;
The same keyframes value can be reused in multiple components; styled-components
injects the @keyframes rule once and dedups it.
Caution
Always interpolate keyframes inside a tagged template (
styledorcss), never into a plain string. Interpolating a keyframes object into an untagged string throws error #12.
8. Global Styles with createGlobalStyle
createGlobalStyle produces a component that injects global, document-level CSS
while it is mounted (and removes it on unmount). It does not render any DOM of
its own.
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
* { box-sizing: border-box; }
body {
margin: 0;
font-family: system-ui, sans-serif;
background: ${props => props.theme.bg ?? '#fff'};
}
`;
function App() {
return (
<>
<GlobalStyle />
{/* rest of app */}
</>
);
}
Global styles support props and theming exactly like other styled components.
Warning
Do not pass children to a global style component — it renders nothing and will warn (
createGlobalStyle does not render children).
Warning
Avoid
@importinsidecreateGlobalStyle. The CSSOM APIs used in production do not handle@importreliably; the library warns about this. Inject font<link>tags in your HTML<head>or via a head-management library instead.
9. Theming
ThemeProvider
Wrap part of your tree in <ThemeProvider theme={...}> to make a theme object
available to every styled component below it.
import styled, { ThemeProvider } from 'styled-components';
const theme = {
colors: { primary: '#0070f3', text: '#111' },
space: [0, 4, 8, 16, 32],
};
const Title = styled.h1`
color: ${props => props.theme.colors.primary};
`;
function App() {
return (
<ThemeProvider theme={theme}>
<Title>Themed</Title>
</ThemeProvider>
);
}
Nested <ThemeProvider>s merge with the outer theme:
- On web, the merge is a shallow spread of the inner theme over the outer.
- On React Native, themes are deep-merged so nested leaves inherit.
You can also pass a function as theme; it receives the outer theme and
returns the merged theme:
<ThemeProvider theme={outer => ({ ...outer, mode: 'dark' })}>
{children}
</ThemeProvider>
Note
If the
themefunction does not return an object, you get error #7. A missing or non-objectthemeprop throws error #8 or #14.
Reading the theme: useTheme
import { useTheme } from 'styled-components';
function Sized({ children }) {
const theme = useTheme();
return <div style={{ maxWidth: theme.space[4] }}>{children}</div>;
}
Caution
useThemethrows error #18 if there is no<ThemeProvider>ancestor. If you need a tolerant read, useReact.useContext(ThemeContext)directly — it returnsundefinedinstead of throwing.
Reading the theme: withTheme (HOC)
For class components or HOC-style code, withTheme injects a theme prop:
import { withTheme } from 'styled-components';
class Chart extends React.Component {
render() {
return <svg fill={this.props.theme.colors.primary} />;
}
}
export default withTheme(Chart);
ThemeConsumer (render prop)
import { ThemeConsumer } from 'styled-components';
<ThemeConsumer>
{theme => <div style={{ color: theme.colors.text }} />}
</ThemeConsumer>
CSS-variable theming: createTheme
createTheme builds a theme backed by CSS custom properties. It returns an
object shaped like your theme, but every leaf value is a
var(--prefix-path, fallback) string you can interpolate directly into styles —
and it works in React Server Components, where context is unavailable.
import { createTheme, ThemeProvider } from 'styled-components';
const theme = createTheme({
colors: { primary: '#0070f3', text: '#111' },
});
// In any component (including RSC):
const Card = styled.div`
color: ${theme.colors.primary}; // → "var(--sc-colors-primary, #0070f3)"
`;
// At your app root, mount the emitted variable declarations:
function Root({ children }) {
return (
<ThemeProvider theme={darkValues}>
<theme.GlobalStyle />
{children}
</ThemeProvider>
);
}
The object returned by createTheme carries these extras:
| Property | What it is |
|---|---|
<your shape> |
Same shape as input, leaves are var(--…, fallback) refs |
.GlobalStyle |
A component that emits the --var: value; declarations from the active theme |
.raw |
The original theme object you passed in |
.vars |
Same shape, leaves are the bare variable names (e.g. --sc-colors-primary) |
.resolve(el?) |
Client-only: reads the computed variable values off an element (defaults to <html>) |
Options:
| Option | Default | Purpose |
|---|---|---|
prefix |
"sc" |
Prefix for variable names (--sc-...). Set for isolation across design systems/microfrontends. |
selector |
":root" |
Selector the declarations are emitted under. Use ":host" for Shadow DOM/web components. |
const theme = createTheme(tokens, { prefix: 'ds', selector: ':host' });
// → :host { --ds-colors-primary: ...; }
Tip
createThemeis the recommended approach when you use React Server Components, because thevar(...)strings are plain text and don't depend on React context at render time.
10. attrs — Default & Computed Props
.attrs() attaches default or computed props/attributes to a styled component.
It is more expressive than defaultProps and can also widen a wrapped
component's prop interface.
Static attrs
const Input = styled.input.attrs({
type: 'text',
spellCheck: false,
})`
border: 1px solid #ccc;
padding: 0.4rem;
`;
<Input placeholder="Name" /> // renders <input type="text" spellcheck="false" ...>
Computed attrs (function form)
The function receives the resolved props (including theme) and returns
attributes to merge in:
const Slider = styled.input.attrs<{ $size?: number }>(props => ({
type: 'range',
min: 0,
max: 100,
style: { width: (props.$size ?? 100) + 'px' },
}))`
accent-color: ${p => p.theme.colors.primary};
`;
Note
Attrs are applied in order and chain when you extend components. An explicit
undefinedprop passed at the call site wins over an attrs-provided value, letting you opt out of an attrs default.
Post-compile attrs with pop / peek
The function form can take a second argument — an accessor over the
component's compiled style. This is mainly used to bridge CSS declarations into
props for third-party components (e.g. mapping a CSS color onto a native SVG's
fill). pop(name) reads and removes a declaration; peek(name) reads without
removing. Both also accept a dotted theme path (e.g. 'color.red.500') to
read a theme token with full type inference.
const Icon = styled(SvgIcon).attrs((props, ast) => ({
// move the CSS `color` declaration onto the SVG's `fill` prop
fill: ast.pop('color', 'black'),
}))`
color: ${p => p.theme.colors.primary};
`;
11. Controlling What Reaches the DOM
By default, styled-components forwards props to the underlying element. For
HTML tags, it filters to valid HTML/SVG attributes (and on* event
handlers); for wrapped components, it forwards everything (the component
decides). There are three ways to control this.
1. Transient props ($ prefix) — recommended
Any prop whose name starts with $ is used for styling but never forwarded
to the DOM:
const Box = styled.div<{ $active: boolean }>`
opacity: ${p => (p.$active ? 1 : 0.5)};
`;
<Box $active /> // renders <div class="..."> — no `$active` attribute on the DOM
2. Per-component shouldForwardProp via withConfig
const Comp = styled('div').withConfig({
shouldForwardProp: (prop) => !['hidden', 'size'].includes(prop),
})<{ size: number; hidden: boolean }>`
width: ${p => p.size}px;
`;
3. App-wide shouldForwardProp via StyleSheetManager
import { StyleSheetManager } from 'styled-components';
import isPropValid from '@emotion/is-prop-valid';
<StyleSheetManager shouldForwardProp={(prop, target) =>
typeof target === 'string' ? isPropValid(prop) : true
}>
<App />
</StyleSheetManager>
Tip
In development, forwarding an unknown prop to a DOM tag logs a one-time warning telling you to use a transient prop or a
shouldForwardPropfilter. Component-levelwithConfig({ shouldForwardProp })takes precedence over theStyleSheetManagerfilter.
StyleSheetManager also configures other injection concerns — see its full prop
list in the API Quick Reference and the Admin Guide.
12. Server-Side Rendering
For traditional (non-streaming) SSR, wrap your render in a ServerStyleSheet to
collect the critical CSS, then emit it into the HTML you send to the client.
import { renderToString } from 'react-dom/server';
import { ServerStyleSheet } from 'styled-components';
const sheet = new ServerStyleSheet();
try {
const html = renderToString(sheet.collectStyles(<App />));
const styleTags = sheet.getStyleTags(); // string of <style> tags
// Inject `html` and `styleTags` into your page template.
} catch (error) {
throw error;
} finally {
sheet.seal();
}
ServerStyleSheet methods:
| Method | Returns | Use |
|---|---|---|
collectStyles(children) |
Wrapped element | Wrap your app so styles are captured |
getStyleTags() |
string |
Full <style …>…</style> markup |
getStyleElement() |
React element array | Style as React element(s) for frameworks |
interleaveWithNodeStream(stream) |
Node stream | Streaming SSR (Node only) |
seal() |
void |
Finalize the sheet (one render cycle per instance) |
Caution
A
ServerStyleSheetis single-use per render cycle. Reusing it, or callingcollectStyles/getStyleTagsafter consuming styles, throws error #2.interleaveWithNodeStreamis Node-only and throws error #3 in the browser.
React Server Components
This version has built-in RSC support: styled components rendered on the server
emit their CSS as inline <style> tags automatically, so basic usage works in
RSC without ServerStyleSheet. For theming in RSC, prefer
createTheme (CSS variables) since React context is not available
during server component rendering. The first-party rscPlugin (from
styled-components/plugins) supports advanced RSC scenarios — see the Admin Guide.
Note
A known issue (#5760) is that
styled.<tag>(fn)parameters can widen toanywith@types/react ≤ 18.2.0; use React 19 types. See Troubleshooting.
13. React Native
Import from styled-components/native. The API mirrors the web, with React
Native component aliases instead of HTML tags.
import styled from 'styled-components/native';
const Card = styled.View`
padding: 16px;
background-color: white;
border-radius: 8px;
`;
const Label = styled.Text`
font-size: 14px;
color: ${p => p.theme.text};
`;
Available component aliases include: View, Text, TextInput, ScrollView,
Image, ImageBackground, Pressable, TouchableOpacity,
TouchableHighlight, TouchableNativeFeedback, TouchableWithoutFeedback,
FlatList, SectionList, VirtualizedList, Modal, Switch,
ActivityIndicator, Button, SafeAreaView, StatusBar,
KeyboardAvoidingView, RefreshControl, InputAccessoryView. You can also wrap
any component: styled(MyComp)`...`.
Note
styled.ScrollViewis pinned toflex-shrink: 0(React Native shipsflex-shrink: 1for ScrollView) so explicitwidth/heightdeclarations aren't silently overridden inside flex parents.
Native supports modern CSS features
The native engine understands @media, @container (container queries),
@supports, pseudo-states (&:hover, &:focus, &:active, &:disabled),
attribute selectors (&[aria-pressed='true']), structural selectors
(&:nth-child(...), &:has(...)), combinators (>, +, ~), CSS custom
properties / var(), and @starting-style transitions.
Native helpers
import {
css, createTheme, ThemeProvider, useTheme, withTheme, isStyledComponent,
toStyleSheet,
useMediaQuery, useBreakpoint, useContainer, useContainerQuery,
useMediaEnv, matchMedia,
} from 'styled-components/native';
toStyleSheet(css\...`)converts acss` block to a plain React Native style
object:
const styles = toStyleSheet(css`background-color: red; padding: 10px;`);
// → { backgroundColor: 'red', paddingTop: 10, ... }
Animations on native
Native animations use React Native's Animated by default. To use
Reanimated 4, add a single side-effect import once at your app entry:
import 'styled-components/native/reanimated';
Important
The Reanimated adapter requires
react-native-reanimated@^4(a peer you must install) and the New Architecture (Fabric). If the package can't be resolved, the import throws a clear error at load time.
React Native Web bridge (experimental)
styled-components/native/web-bridge routes styled-components/native consumers
running under react-native-web through the web CSS pipeline (hashed class
names, CSSOM insertion) instead of building RN style objects that get
re-tokenized. It is experimental — see the Admin Guide.
14. Package Entry Points
styled-components publishes several entry points from the one package:
| Import path | Provides |
|---|---|
styled-components |
Web API: styled, css, keyframes, createGlobalStyle, createTheme, ThemeProvider, useTheme, withTheme, StyleSheetManager, ServerStyleSheet, isStyledComponent, version, types |
styled-components/native |
React Native API (see section 13) |
styled-components/native/reanimated |
Side-effect import enabling the Reanimated 4 animation adapter |
styled-components/native/web-bridge |
Experimental react-native-web bridge |
styled-components/plugins |
rtlPlugin, rscPlugin for use with StyleSheetManager |
styled-components/test-utils |
find, findAll, enzymeFind test helpers |
The default styled import also exposes the secondary helpers as properties, so
import styled from 'styled-components' lets you use styled.css,
styled.keyframes, etc., without separate named imports.
15. Common Tasks (Recipes)
Toggle a style with a boolean prop
const Tab = styled.button<{ $selected?: boolean }>`
border-bottom: 2px solid ${p => (p.$selected ? '#0070f3' : 'transparent')};
font-weight: ${p => (p.$selected ? 700 : 400)};
`;
Build a button variant system
import styled, { css } from 'styled-components';
const variants = {
primary: css`background: #0070f3; color: #fff;`,
ghost: css`background: transparent; color: #0070f3;`,
};
const Button = styled.button<{ $variant?: keyof typeof variants }>`
padding: 0.6rem 1.2rem;
border-radius: 6px;
${p => variants[p.$variant ?? 'primary']}
`;
Media queries
const Grid = styled.div`
display: grid;
grid-template-columns: 1fr;
@media (min-width: 768px) {
grid-template-columns: repeat(3, 1fr);
}
`;
Reuse a theme-aware mixin
const card = css`
border-radius: 8px;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
background: ${p => p.theme.surface};
`;
const Panel = styled.section`${card} padding: 1rem;`;
const Modal = styled.div`${card} padding: 2rem;`;
Find a styled component's DOM nodes in tests
import { find, findAll } from 'styled-components/test-utils';
const root = container; // an HTMLElement from your test render
const el = find(root, Button); // first match
const all = findAll(root, Button); // NodeList of matches
Set a CSP nonce on injected styles
<StyleSheetManager nonce="r4nd0m">
<App />
</StyleSheetManager>
A nonce is also auto-detected from <meta name="sc-nonce">,
<meta property="csp-nonce">, or the bundler's __webpack_nonce__.
Scope/namespace generated rules
<StyleSheetManager namespace="#my-app">
<App />
</StyleSheetManager>
Inject styles into an iframe or alternate root
<StyleSheetManager target={iframeDocument.head}>
<App />
</StyleSheetManager>
16. TypeScript Usage
Types are bundled — no extra @types package for this version.
Typing component props
const Box = styled.div<{ $w: number; $muted?: boolean }>`
width: ${p => p.$w}px;
color: ${p => (p.$muted ? '#888' : '#111')};
`;
Typing your theme
Augment the library's DefaultTheme interface so props.theme is fully typed
everywhere:
// styled-components.d.ts in your project source
import 'styled-components';
declare module 'styled-components' {
export interface DefaultTheme {
colors: { primary: string; text: string };
space: number[];
}
}
If it isn't picked up, check compilerOptions.types/include in tsconfig.json.
Enabling the css prop in TypeScript
The css prop is not declared globally by default (it would otherwise appear on
everything). Opt in:
// styled-components.d.ts
import type { CSSProp } from 'styled-components';
declare module 'react' {
interface Attributes {
css?: CSSProp;
}
}
Note
Some large component libraries (e.g. antd Button, Mantine) have triggered TypeScript complexity/regression issues in past versions (#5725, #5756, #4350). This version reworked several prop-mapping types to reduce that. If you hit "type instantiation is excessively deep" or OOM during type-checking, ensure you're on React 19 types and the latest release.
17. Troubleshooting
styled-components throws numbered errors. In production the message is a short
pointer to the docs; in development you get the full text below. Format:
### Error: ... → Cause → Solution → Prevention.
Error: Cannot create styled-component for component: %s (#1)
- Cause: You called
styled(x)with a falsy/invalid target (e.g.undefinedfrom a bad import). - Solution: Verify the component or tag you pass to
styled()is defined and imported correctly. - Prevention: Check default-vs-named imports of the component you're wrapping.
Error: Can't collect styles once you've consumed a ServerStyleSheet's styles! (#2)
- Cause: You reused a
ServerStyleSheet, or calledcollectStyles/getStyleTagsafter the sheet was already consumed/sealed. - Solution: Create a new
ServerStyleSheetfor every render cycle and callseal()in afinally. - Prevention: Never share a sheet instance across requests/renders.
Error: Streaming SSR is only supported in a Node.js environment (#3)
- Cause:
interleaveWithNodeStreamwas called in the browser. - Solution: Only call it on the server.
Error: The StyleSheetManager expects a valid target or sheet prop! (#4)
- Cause: A falsy
target(client) orsheet(server) was passed toStyleSheetManager. - Solution: Ensure the DOM node / sheet you pass actually exists when the component mounts.
Error: ThemeProvider: Please return an object from your "theme" prop function (#7)
- Cause: A function
themeprop returned a non-object (null/array/primitive). - Solution: Return a plain object:
theme={outer => ({ ...outer })}.
Error: ThemeProvider: Please make your "theme" prop an object (#8)
- Cause:
themewas an array or non-object value. - Solution: Pass a plain object (or a function returning one).
Error: ThemeProvider: "theme" prop is required (#14)
- Cause:
<ThemeProvider>was rendered without atheme. - Solution: Always provide
theme.
Error: It seems you are interpolating a keyframe declaration into an untagged string (#12)
- Cause: A
keyframesvalue was interpolated into a plain string instead of acss/styledtemplate. - Solution: Wrap the CSS in the
css\...`` helper.
Error: %s is not a styled component and cannot be referred to via component selector (#13)
- Cause: You interpolated a non-styled component into CSS as a selector.
- Solution: Only use styled components in component-selector interpolations.
Error: A plugin has been supplied that is not named (#15)
- Cause: A plugin passed to
<StyleSheetManager plugins={[...]}>has noname. - Solution: Give each plugin a unique
name(e.g.Object.defineProperty(plugin, 'name', { value: 'my-plugin' })).
Error: Reached the limit of how many styled components may be created (#16)
- Cause: You created more than 1,073,741,824 components — almost always from creating styled components inside render in a loop.
- Solution: Define styled components at module scope, not inside render.
Error: Accessing useTheme hook outside of a <ThemeProvider> element (#18)
- Cause:
useTheme()was called with no<ThemeProvider>ancestor. - Solution: Wrap the tree in
<ThemeProvider>, or useReact.useContext(ThemeContext)for a tolerant read.
Warning: several instances of styled-components are initialized
- Cause: More than one copy of styled-components is loaded (duplicate versions in the bundle). Causes broken dynamic styles, theme loss, and rehydration errors.
- Solution: Deduplicate the dependency (single version) in your lockfile / bundler; ensure libraries share one styled-components instance.
Warning: unknown prop "x" is being sent to the DOM
- Cause: A non-standard prop is being forwarded to an HTML element.
- Solution: Rename it to a transient prop (
$x) or add ashouldForwardPropfilter.
SSR hydration mismatch / class names differ between server and client
- Cause: Multiple instances of the library, or a build that externalizes styled-components inconsistently (#5737), can cause class-name divergence.
- Solution: Ensure exactly one styled-components instance is used for both
server and client; check
nodeExternals/SSR bundling config.
styled(SomeLibButton) rejects all props / parameter becomes any
- Cause: Old
@types/react(#5756, #5760). - Solution: Upgrade to React 19 types.
18. FAQ
Q: Do I need a Babel or build plugin?
No. styled-components works at runtime with no build step. A build plugin
(babel-plugin-styled-components) exists to add stable component IDs and nicer
display names, but it is optional and not required for the library to function.
Q: What's the difference between transient props and shouldForwardProp?
Transient props ($-prefixed) are the simplest opt-out: they're never forwarded.
shouldForwardProp is a programmatic filter for cases where you can't rename the
prop (e.g. bridging a third-party prop validator).
Q: How do I share styles between components?
Put them in a css\...`` block and interpolate that block into each component.
Q: Can I use object styles instead of strings?
Yes — css({...}) and the styled.div({...})-style object syntax are supported;
they go through the same pipeline as template literals.
Q: How do I do dark mode?
Either swap the theme object passed to <ThemeProvider> (and read
props.theme), or use createTheme with CSS variables and toggle the values at
the :root selector.
Q: Does it work with React Server Components?
Yes. Basic styled components emit inline <style> tags on the server
automatically. For theming in RSC, use createTheme (CSS variables), since React
context isn't available in server components.
Q: Where did the documentation site go? The full narrative docs live at https://styled-components.com/docs. The in-repository docs only point there; this guide is generated directly from the source code.
Q: How do I name/scope the injected style attribute?
The DOM attribute defaults to data-styled. You can override it via the
SC_ATTR (or REACT_APP_SC_ATTR) environment variable at build time — see the
Admin Guide.
Q: Is styled.xxx available for every HTML element?
Yes — every standard HTML element is a property on styled, and every SVG/HTML
attribute is recognized for prop forwarding.
Q: How do I change the rendered tag at the usage site?
Use the as prop: <Button as="a" href="...">. Use forwardedAs to pass as
through to a wrapped styled component.
Q: Can I detect whether something is a styled component?
Yes: isStyledComponent(MaybeStyled) returns a boolean.
19. API Quick Reference
Web exports (styled-components)
| Export | Kind | Purpose |
|---|---|---|
styled (default + named) |
factory | Create styled components: styled.tag\`, styled(Comp)``` |
styled.tag.attrs(...) |
method | Default/computed props (object or function) |
styled(...).withConfig(...) |
method | Set displayName, componentId, shouldForwardProp, etc. |
css |
helper | Reusable CSS blocks / dynamic CSS / object styles |
keyframes |
helper | Scoped @keyframes animations |
createGlobalStyle |
factory | Global CSS component |
createTheme |
factory | CSS-variable-backed theme (.GlobalStyle, .raw, .vars, .resolve) |
ThemeProvider |
component | Provide a theme via context |
ThemeConsumer |
component | Render-prop theme access |
ThemeContext |
context | Raw theme context (tolerant access) |
useTheme |
hook | Read theme (throws if no provider) |
withTheme |
HOC | Inject theme prop |
StyleSheetManager |
component | Configure injection (see props below) |
ServerStyleSheet |
class | Collect critical CSS for SSR |
isStyledComponent |
function | Test if a value is a styled component |
extractCSS |
function | Extract CSS (advanced/utility) |
version |
string | The library version (SC_VERSION) |
StyleSheetManager props
| Prop | Type | Purpose |
|---|---|---|
namespace |
string |
Prepend a selector to all generated rules |
sheet |
StyleSheet |
Provide a custom sheet (advanced SSR) |
shouldForwardProp |
(prop, target) => boolean |
App-wide prop forwarding filter |
plugins |
SCPlugin[] |
CSS-emission plugins (e.g. rtlPlugin, rscPlugin) |
nonce |
string |
CSP nonce for injected <style> tags |
target |
HTMLElement | ShadowRoot |
Alternate node to host styles (e.g. iframe) |
Native exports (styled-components/native)
styled (with RN component aliases), css, createTheme, ThemeProvider,
ThemeConsumer, ThemeContext, useTheme, withTheme, isStyledComponent,
toStyleSheet, matchMedia, useMediaQuery, useBreakpoint, useContainer,
useContainerQuery, useMediaEnv, setAnimationDebug, plus
NativeStyleContext/ParentContext and related hooks.
Other entry points
styled-components/plugins → rtlPlugin, rscPlugin.
styled-components/native/reanimated → side-effect import (Reanimated 4 adapter).
styled-components/native/web-bridge → experimental rn-web bridge.
styled-components/test-utils → find, findAll, enzymeFind.