Using the css Prop in Styled-Components for One-Off Dynamic Styles
Skip component sprawl. Learn how styled-components' css prop attaches scoped, dynamic styles directly to elements with TypeScript safety.
08 Jun 2026, 19:51 UTC

Problem
You need a button that turns red when danger is true, or a card that shifts its grid span based on a size prop. Creating a dedicated styled component for every small variation bloats your component tree and scatters one-line CSS across files. You want the variation to live next to the JSX that uses it, not in a separate export.
Thesis
The css prop in styled-components lets you write template-literal styles directly on an existing element. Styled-components compiles them into a scoped class name, injects the CSS with vendor prefixes, and passes React props straight into your interpolations. The result is a concise, type-safe way to handle dynamic styles without defining another component.
Scoped styles without a new component
Normally you define const Button = styled.button`...` and import it. With the css prop, you attach styles to a plain HTML tag or another styled component. Under the hood, styled-components generates a unique class name, injects the corresponding rule into the document head, and applies vendor prefixes automatically. You get the same isolation as a styled component—no global selector collisions—without the boilerplate.
Dynamic values from props
Because the css prop is processed by styled-components, its interpolations receive the same props object as a styled component definition. That means you can branch on state or incoming props inline:
<button
css={`
background: ${props => (props.$danger ? '#d32f2f' : '#1976d2')};
color: white;
padding: 8px 16px;
border: none;
border-radius: 4px;
`}
onClick={handleClick}
>
Delete
</button>
The transient prop convention ($danger) prevents the flag from leaking to the DOM as an invalid HTML attribute.
TypeScript checks at compile time
When your project uses TypeScript, the css prop is typed through styled-components' JSX augmentation. The interpolated function receives a typed props argument, so a typo like props.$dager fails during compilation rather than at runtime. You also get autocomplete for CSS properties inside the template literal, assuming your editor has the styled-components TypeScript plugin installed.
Worked example: a responsive card
Imagine a dashboard card whose padding and border color depend on an emphasis prop. Instead of exporting EmphasizedCard, NormalCard, and CompactCard, you can keep one element and vary its styles inline:
import { css } from 'styled-components';
type CardProps = {
$emphasis?: 'low' | 'high';
children: React.ReactNode;
};
export function DashboardCard({ $emphasis = 'low', children }: CardProps) {
return (
<div
css={[
{
borderRadius: '8px',
border: '1px solid #e0e0e0',
padding: '16px',
},
$emphasis === 'high' &&
css`
border-color: #1976d2;
padding: 24px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
`,
]}
>
{children}
</div>
);
}
Here the base styles are a plain object, and the conditional block uses the css helper to return a styled-components serialized style. The array syntax lets you compose static and dynamic rules cleanly.
Trade-offs and limitations
The css prop is not a replacement for every styled component. Three practical limits matter:
- Re-render cost in lists. Every render creates a new template literal. In a large table or virtualized list, that means styled-components re-serializes and potentially re-injects styles on each pass. Memoize the component or hoist static styles into a
styleddefinition when rows number in the hundreds. - No global CSS. Styles are component-scoped. You cannot target a global class or element selector through the
cssprop alone; usecreateGlobalStylefor resets or third-party overrides. - Readability cliff. Deeply nested interpolations and multi-branch ternaries inside JSX attributes become hard to scan. If a component needs more than a few conditional rules, extract a styled component.
How to verify it works
- Run the example in a local React sandbox and toggle the prop; the visual style should update immediately without a page reload.
- Run
npx tsc --noEmitin your project root. There should be no type errors related to thecssprop or its interpolations. - Open browser DevTools and inspect the element. You should see a generated styled-components class (e.g.,
sc-abcdef) and no unexpected global selectors injected into the stylesheet.
Closing
Use the css prop when a style variation is local, small, and driven by props. Reach for a named styled component when the same rules repeat across files or when conditional logic grows past a couple of branches. Check the compiled output with tsc and watch the DOM class names before shipping.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.