1. Introduction to Styled Components
Styled Components is a popular CSS-in-JS library for React that enables you to write actual CSS inside your JavaScript. It leverages tagged template literals (a feature from ES6) to define scoped, reusable styles directly within your components.
This approach brings a number of modern benefits:
- Scoped styles by default (no class name collisions)
- Theming support via context
- Dynamic styling using props
- Eliminates global CSS problems
- Cleaner code separation in React projects
Here’s a basic example:
import { styled } from 'styled-components';
const H1 = styled.h1`
font-size: 30px;
font-weight: 600;
background-color: yellow;
`;
const Button = styled.button`
font-size: 1.4rem;
padding: 1.2rem 1.6rem;
font-weight: 500;
border: none;
border-radius: 7px;
background-color: purple;
color: white;
cursor: pointer;
margin: 20px;
`;
function App() {
return (
<div>
<H1>Hotel California</H1>
<Button onClick={() => alert('Check in')}>Check in</Button>
<Button onClick={() => alert('Check out')}>Check out</Button>
</div>
);
}
export default App;
2. Installation (2025)
The latest version of Styled Components is fully compatible with React 18+ and modern bundlers like Vite, Webpack, and Next.js.
Install using npm or yarn:
npm install styled-components
For TypeScript users, install the types:
npm install -D @types/styled-components
Note: From v6 onward,
styled-components
provides both ESM and CJS builds. If you're using Vite or other ESM-first tools, it works natively.
3. Basic Usage and Syntax
3.1 Creating Styled Elements
You use styled.[element]
followed by a template literal containing your CSS:
const Container = styled.div`
padding: 20px;
background-color: #f7f7f7;
`;
const Heading = styled.h1`
font-size: 2rem;
color: darkblue;
`;
3.2 Using Styled Components in JSX
Use them just like normal React components:
<Container>
<Heading>Styled Components are awesome</Heading>
</Container>
The styles are automatically scoped and do not bleed into other components.
4. How Styled Components Work Behind the Scenes
Styled Components dynamically generates unique class names for each styled definition. These classes are injected into the DOM at runtime.
Example:
const H1 = styled.h1`
font-weight: bold;
`;
Generates:
<h1 class="sc-gTRQi iXbVjY">Styled Heading</h1>
<style>
.sc-gTRQi.iXbVjY {
font-weight: bold;
}
</style>
This guarantees:
- No class name collisions
- True component-level scoping
- Automatic deduplication of styles
5. Developer Tooling and Extensions
5.1 VS Code Syntax Highlighting
To enable full syntax highlighting and formatting, install this VS Code extension:
-
Name:
vscode-styled-components
- Publisher: Julien Poissonnier
- Benefit: Adds syntax highlighting inside template literals, linting, and IntelliSense
5.2 Prettier Support
If you use Prettier, it automatically formats styled components. Just make sure prettier-plugin-styled-components
is not installed anymore — it's deprecated and no longer required.
6. Styling Existing Components
You can use styled()
to style not only HTML elements, but also custom React components:
const BaseButton = ({ children, ...props }) => (
<button {...props}>{children}</button>
);
const StyledButton = styled(BaseButton)`
padding: 10px 16px;
border-radius: 5px;
background-color: teal;
color: white;
`;
You can also extend existing styled components:
const PrimaryButton = styled(Button)`
background-color: green;
`;
const DangerButton = styled(Button)`
background-color: crimson;
`;
7. Recap: Core Concepts and Setup
- What Styled Components are and how they work
- Installation and compatibility (React 18+, Vite, Webpack)
- Creating styled elements with tagged template literals
- How styles are scoped and rendered
- Styling React components and extending styles
- Editor support and formatting
8. Dynamic Styling with Props
One of the most powerful features of Styled Components is that it supports JavaScript logic inside CSS, especially when driven by component props
.
Example: Dynamic Color
const Button = styled.button`
background-color: ${(props) => (props.primary ? 'blue' : 'gray')};
color: white;
padding: 1rem 1.4rem;
border: none;
border-radius: 5px;
font-size: 1rem;
cursor: pointer;
`;
Usage:
<Button primary>Primary</Button>
<Button>Default</Button>
The
primary
prop controls which style is applied. This is incredibly helpful when building a design system with reusable buttons, cards, badges, etc.
9. Theming with ThemeProvider
Styled Components offers built-in support for global themes using React Context under the hood.
Step 1: Define a Theme Object
// theme.js
export const theme = {
colors: {
primary: '#0070f3',
secondary: '#facc15',
text: '#333333',
background: '#f7f7f7',
},
fonts: {
heading: '"Poppins", sans-serif',
body: '"Open Sans", sans-serif',
},
};
Step 2: Wrap Your App with ThemeProvider
// App.jsx
import { ThemeProvider } from 'styled-components';
import { theme } from './theme';
import Home from './Home';
function App() {
return (
<ThemeProvider theme={theme}>
<Home />
</ThemeProvider>
);
}
export default App;
Step 3: Access Theme in Components
const Container = styled.div`
background-color: ${(props) => props.theme.colors.background};
color: ${(props) => props.theme.colors.text};
font-family: ${(props) => props.theme.fonts.body};
`;
This way, all components have theme access via props, and your design system becomes centralized and maintainable.
10. Global Styles
Styled Components allows you to write global CSS (e.g., resets, base styles) using the createGlobalStyle
helper.
Step 1: Import the helper
import { createGlobalStyle } from 'styled-components';
Step 2: Define Global Styles
const GlobalStyle = createGlobalStyle`
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: ${(props) => props.theme.fonts.body};
background-color: ${(props) => props.theme.colors.background};
color: ${(props) => props.theme.colors.text};
line-height: 1.6;
}
button {
font-family: inherit;
}
`;
Step 3: Use in App
<ThemeProvider theme={theme}>
<GlobalStyle />
<App />
</ThemeProvider>
You can also use multiple
createGlobalStyle
declarations for modularity (e.g., reset + base + typography).
11. CSS Helpers: css
and keyframes
Styled Components offers powerful helpers for advanced styling use cases.
11.1 Reusable Styles with css
Use the css
helper to define and reuse chunks of CSS:
import { css } from 'styled-components';
const buttonBase = css`
padding: 0.8rem 1.2rem;
font-size: 1rem;
border-radius: 6px;
border: none;
cursor: pointer;
`;
const Button = styled.button`
${buttonBase}
background-color: navy;
color: white;
`;
You can also conditionally inject different blocks:
const variant = css`
background-color: green;
color: white;
`;
const Button = styled.button`
${buttonBase}
${(props) => props.success && variant}
`;
11.2 Animations with keyframes
import { keyframes } from 'styled-components';
const fadeIn = keyframes`
from {
opacity: 0;
transform: translateY(5px);
}
to {
opacity: 1;
transform: translateY(0);
}
`;
const Notification = styled.div`
animation: ${fadeIn} 0.5s ease-out;
`;
Use this for tooltips, modals, transitions, or any animation state.
12. Media Queries and Responsive Design
Styled Components supports regular CSS media queries inside template literals.
const Card = styled.div`
padding: 2rem;
@media (max-width: 768px) {
padding: 1rem;
}
`;
To centralize breakpoints, you can define them in your theme:
// theme.js
export const theme = {
breakpoints: {
sm: '480px',
md: '768px',
lg: '1024px',
},
};
And use:
const Wrapper = styled.div`
padding: 2rem;
@media (max-width: ${(props) => props.theme.breakpoints.md}) {
padding: 1rem;
}
`;
13. Recap: Dynamic Styling, Theming, and Helpers
- Dynamically styling components using props
- Building a global theme system using
ThemeProvider
- Applying global styles with
createGlobalStyle
- Writing reusable CSS blocks using
css
- Adding animations with
keyframes
- Responsive styles via media queries
14. Nesting and Selector Support
Styled Components allows you to write nested CSS just like in SCSS. You can nest child elements, pseudo-selectors, or class-based styles.
Example: Nested Elements and States
const Card = styled.div`
padding: 2rem;
background-color: white;
border-radius: 10px;
h2 {
font-size: 1.5rem;
margin-bottom: 1rem;
}
p {
font-size: 1rem;
color: #555;
}
&:hover {
background-color: #f9f9f9;
}
`;
Styling Child Components via Class or Props
You can use attribute selectors if necessary:
const ListItem = styled.li`
&[data-active='true'] {
font-weight: bold;
color: blue;
}
`;
15. Polymorphic Components with as
Prop
Styled Components support the as
prop, which allows a component to render a different HTML tag without changing its style.
const Text = styled.p`
font-size: 1rem;
color: #444;
`;
<Text>This is a paragraph</Text>
<Text as="span">This is a span</Text>
<Text as="h2">This is a heading</Text>
This is helpful when reusing the same styles across different HTML elements (e.g., links vs buttons vs spans).
16. Composition Patterns
There are two ways to reuse and extend styled components.
16.1 Extend a Styled Component
const BaseButton = styled.button`
padding: 1rem 1.5rem;
font-size: 1rem;
`;
const PrimaryButton = styled(BaseButton)`
background-color: royalblue;
color: white;
`;
16.2 Share CSS Blocks with css
import { css } from 'styled-components';
const cardBase = css`
border-radius: 10px;
padding: 2rem;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.1);
`;
const Card = styled.div`
${cardBase}
background-color: white;
`;
const Modal = styled.div`
${cardBase}
background-color: #fffdf5;
`;
17. Testing Styled Components
You can test styled components using tools like Jest and React Testing Library.
17.1 Unit Testing Components
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from 'styled-components';
import { theme } from '../theme';
import Button from './Button';
test('renders styled button with correct text', () => {
render(
<ThemeProvider theme={theme}>
<Button>Submit</Button>
</ThemeProvider>
);
expect(screen.getByText('Submit')).toBeInTheDocument();
});
You don’t need to test styles directly — just focus on behavior and output. You can use snapshot testing if needed.
18. Best Practices
Here are key strategies for writing clean, scalable styled components:
18.1 Structure Components Clearly
- Name styled versions with a prefix like
Styled
, e.g.StyledContainer
- Keep styled components near the component that uses them
- Group common styles in a
styles.js
file per component when needed
18.2 Keep CSS Logic Minimal
Avoid overcomplicating styles with too much logic:
// OK
color: ${(props) => (props.active ? 'blue' : 'gray')};
// Avoid this
color: ${(props) =>
props.active ? (props.theme.dark ? '#fff' : '#000') : props.disabled ? 'gray' : 'red'};
Instead, compute values earlier or use utility functions.
18.3 Prefer css
for Shared Styles
// Avoid duplication
const buttonStyles = css`
padding: 1rem;
border-radius: 5px;
`;
const Button = styled.button`
${buttonStyles}
background-color: blue;
`;
const LinkButton = styled.a`
${buttonStyles}
background-color: transparent;
`;
18.4 Theming and Responsiveness
- Always extract theme values instead of hardcoding colors or fonts
- Use
props.theme.breakpoints
for responsive styles - Keep theme definitions in a centralized file
18.5 Keep createGlobalStyle
Minimal
Only include base resets and typography in global styles. Avoid injecting component-specific styles globally.
19. Styled Components Reference Table
Feature | Description |
---|---|
styled.[tag] |
Create styled HTML elements (div, h1, button, etc.) |
styled(Component) |
Style existing React components |
ThemeProvider |
Provide theme context globally |
props |
Dynamically change styles with JS logic |
createGlobalStyle |
Inject global CSS rules |
css |
Reuse or compose chunks of CSS |
keyframes |
Define animations |
as prop |
Polymorphic rendering (e.g., button rendered as link) |
@media queries |
Responsive styling |
.extend , class nesting |
Extend and nest styles like SCSS |
20. Final Thoughts
Styled Components brings the full power of CSS into your React component system — while solving key pain points like style leakage, naming conflicts, and theming.
Whether you're building small reusable UI kits or large-scale design systems, Styled Components enables:
- Co-located styles and logic
- Dynamic styling via props
- Full JavaScript power in your CSS
- Encapsulation and reusability by default
Adopting it takes a small learning curve, but once you embrace its model, you’ll likely never return to traditional CSS or even CSS Modules.
21. Frequently Asked Questions (FAQs)
Q: Is Styled Components still relevant in 2025?
A: Yes. Styled Components is actively maintained, compatible with React 18+, and widely used in both open-source and enterprise projects.
Q: What are alternatives to Styled Components?
A: Emotion, Linaria, Stitches, and even Tailwind (utility-first CSS) are viable alternatives. Choose based on your project needs.
Q: Will Styled Components slow down my app?
A: In most cases, no. Runtime injection is lightweight. However, if you're rendering large component trees or complex animations, consider static extraction via Babel plugin.
Q: Can I use Styled Components with Next.js?
A: Yes. Next.js supports Styled Components out of the box, but you’ll need to set up a custom _document.js
with SSR support using ServerStyleSheet
.
Q: Should I use Styled Components or Tailwind?
A: Both solve different problems. Tailwind emphasizes low-level utility composition, while Styled Components emphasizes encapsulated, component-scoped CSS. You can even use both together in hybrid setups.
📬 Let’s Connect
🌐 Portfolio: paulanik.com
💼 LinkedIn: Anik Paul
🐙 GitHub: anikpaul99
📩 Email: hello@paulanik.com
Top comments (0)