Skip to main content

React Styled Components

Introduction

Styled Components is a popular CSS-in-JS library that allows you to write actual CSS code to style your React components. Unlike traditional CSS or even CSS modules, Styled Components enables you to define your styles directly within your JavaScript files, creating a seamless connection between your components and their styles.

This approach offers several benefits:

  • Component-based styling: Styles are scoped to specific components
  • Dynamic styling: Styles can change based on props and state
  • No class name bugs: Automatically generates unique class names
  • Easier deletion of CSS: When you delete a component, its styles are deleted too
  • Automatic vendor prefixing: Write standard CSS and get vendor prefixes automatically

In this guide, we'll explore how to use Styled Components in your React applications, from basic usage to advanced techniques.

Getting Started with Styled Components

Installation

First, you need to install Styled Components in your React project:

bash
# Using npm
npm install styled-components

# Using yarn
yarn add styled-components

Basic Usage

Let's start with a simple example. Here's how you create a styled button component:

jsx
import styled from 'styled-components';

// Create a Button component that's a styled <button>
const Button = styled.button`
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;

&:hover {
background-color: #45a049;
}
`;

// Use it like any other React component
function App() {
return (
<div>
<h1>My First Styled Component</h1>
<Button>Click Me</Button>
</div>
);
}

In this example, we:

  1. Import the styled function from 'styled-components'
  2. Create a Button component using styled.button and write our CSS inside template literals
  3. Use the Button component just like any other React component

The resulting HTML will have a randomly generated class name that ensures your styles don't conflict with other components.

Props-Based Styling

One of the most powerful features of Styled Components is the ability to adjust styles based on props:

jsx
import styled from 'styled-components';

const Button = styled.button`
background-color: ${props => props.primary ? '#4CAF50' : 'white'};
color: ${props => props.primary ? 'white' : '#4CAF50'};
padding: 10px 15px;
border: 2px solid #4CAF50;
border-radius: 4px;
cursor: pointer;
font-size: 16px;

&:hover {
background-color: ${props => props.primary ? '#45a049' : '#e8f5e9'};
}
`;

function App() {
return (
<div>
<h1>Buttons with Props</h1>
<Button>Normal Button</Button>
<Button primary>Primary Button</Button>
</div>
);
}

The primary prop changes the styling of the button. When primary is passed, the button has a green background with white text. Without the prop, it's a white button with green text.

Extending Styles

You can extend the styles of an existing component to create a new one with additional styles:

jsx
import styled from 'styled-components';

const Button = styled.button`
background-color: #4CAF50;
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
cursor: pointer;
`;

// Extend the Button component with additional styles
const LargeButton = styled(Button)`
font-size: 20px;
padding: 15px 30px;
`;

function App() {
return (
<div>
<h1>Regular and Extended Buttons</h1>
<Button>Regular Button</Button>
<LargeButton>Large Button</LargeButton>
</div>
);
}

In this example, LargeButton inherits all the styles from Button and adds its own styles for font size and padding.

Styling Any Component

You can style any React component, not just HTML elements:

jsx
import styled from 'styled-components';
import { Link } from 'react-router-dom';

const StyledLink = styled(Link)`
color: #2196F3;
text-decoration: none;
font-weight: bold;

&:hover {
text-decoration: underline;
}
`;

function Navigation() {
return (
<nav>
<StyledLink to="/">Home</StyledLink>
<StyledLink to="/about">About</StyledLink>
<StyledLink to="/contact">Contact</StyledLink>
</nav>
);
}

The only requirement is that the component you're styling must accept a className prop, as Styled Components uses this to apply the generated class.

Global Styles

Sometimes you need to define global styles. Styled Components provides a createGlobalStyle function for this purpose:

jsx
import { createGlobalStyle } from 'styled-components';

const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
font-family: 'Arial', sans-serif;
background-color: #f9f9f9;
}

* {
box-sizing: border-box;
}
`;

function App() {
return (
<>
<GlobalStyle />
<div>Your app content here</div>
</>
);
}

The GlobalStyle component should be rendered once at the top level of your application.

Theming

Styled Components supports theming through the ThemeProvider component:

jsx
import { ThemeProvider, styled } from 'styled-components';

// Define our theme
const theme = {
colors: {
primary: '#4CAF50',
secondary: '#2196F3',
danger: '#f44336',
light: '#f9f9f9',
dark: '#333'
},
fonts: {
main: 'Arial, sans-serif'
},
breakpoints: {
mobile: '576px',
tablet: '768px'
}
};

// A styled component that uses the theme
const ThemedButton = styled.button`
background-color: ${props => props.theme.colors.primary};
color: white;
padding: 10px 15px;
border: none;
border-radius: 4px;
font-family: ${props => props.theme.fonts.main};

&:hover {
opacity: 0.9;
}
`;

function App() {
return (
<ThemeProvider theme={theme}>
<div>
<h1>Themed Components</h1>
<ThemedButton>Themed Button</ThemedButton>
</div>
</ThemeProvider>
);
}

The ThemeProvider makes the theme object available to all styled components beneath it in the component tree. This makes it easy to maintain consistent styling across your application.

CSS Helper Functions

Styled Components provides several helper functions that make certain CSS patterns easier:

The css Helper

The css helper lets you define reusable CSS fragments:

jsx
import styled, { css } from 'styled-components';

// Define a reusable style fragment
const flexCenter = css`
display: flex;
align-items: center;
justify-content: center;
`;

const Card = styled.div`
${flexCenter}
width: 300px;
height: 200px;
background-color: white;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 8px;
`;

const IconWrapper = styled.div`
${flexCenter}
width: 50px;
height: 50px;
background-color: #e3f2fd;
border-radius: 50%;
`;

Media Queries

You can use media queries directly in your styled components:

jsx
import styled from 'styled-components';

const ResponsiveContainer = styled.div`
padding: 20px;
background-color: #e3f2fd;

/* Mobile first approach */
width: 100%;

/* Tablet */
@media (min-width: 768px) {
width: 750px;
margin: 0 auto;
}

/* Desktop */
@media (min-width: 1024px) {
width: 970px;
}
`;

For more complex applications, you might want to define media query templates in your theme:

jsx
import { ThemeProvider, styled } from 'styled-components';

const theme = {
// ...other theme properties
media: {
mobile: `@media (max-width: 576px)`,
tablet: `@media (min-width: 577px) and (max-width: 768px)`,
desktop: `@media (min-width: 769px)`
}
};

const ResponsiveText = styled.p`
font-size: 16px;

${props => props.theme.media.mobile} {
font-size: 14px;
}

${props => props.theme.media.tablet} {
font-size: 15px;
}

${props => props.theme.media.desktop} {
font-size: 16px;
}
`;

Real-World Example: A Simple Card Component

Let's build a reusable card component that could be used in a real application:

jsx
import React from 'react';
import styled from 'styled-components';

const CardWrapper = styled.div`
background-color: white;
border-radius: 8px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: transform 0.3s ease, box-shadow 0.3s ease;

&:hover {
transform: translateY(-5px);
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.15);
}
`;

const CardImage = styled.img`
width: 100%;
height: 200px;
object-fit: cover;
`;

const CardContent = styled.div`
padding: 20px;
`;

const CardTitle = styled.h3`
margin-top: 0;
margin-bottom: 10px;
color: #333;
font-size: 18px;
`;

const CardDescription = styled.p`
color: #666;
margin-bottom: 15px;
line-height: 1.5;
`;

const CardFooter = styled.div`
display: flex;
justify-content: space-between;
padding: 15px 20px;
border-top: 1px solid #eee;
background-color: #f9f9f9;
`;

const CardButton = styled.button`
background-color: ${props => props.primary ? '#4CAF50' : 'transparent'};
color: ${props => props.primary ? 'white' : '#4CAF50'};
border: ${props => props.primary ? 'none' : '1px solid #4CAF50'};
padding: 8px 15px;
border-radius: 4px;
cursor: pointer;
transition: all 0.2s;

&:hover {
background-color: ${props => props.primary ? '#45a049' : '#e8f5e9'};
}
`;

// The Card Component
function Card({ title, description, imageUrl, primaryAction, secondaryAction }) {
return (
<CardWrapper>
{imageUrl && <CardImage src={imageUrl} alt={title} />}
<CardContent>
<CardTitle>{title}</CardTitle>
<CardDescription>{description}</CardDescription>
</CardContent>
<CardFooter>
<CardButton onClick={secondaryAction}>Cancel</CardButton>
<CardButton primary onClick={primaryAction}>View Details</CardButton>
</CardFooter>
</CardWrapper>
);
}

// Usage example
function ProductCatalog() {
return (
<div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(300px, 1fr))', gap: '20px', padding: '20px' }}>
<Card
title="Premium Headphones"
description="Noise-canceling wireless headphones with 30-hour battery life and premium sound quality."
imageUrl="headphones.jpg"
primaryAction={() => console.log('View headphones')}
secondaryAction={() => console.log('Cancel')}
/>
{/* More cards would be added here */}
</div>
);
}

This example demonstrates how you can compose multiple styled components to create a coherent UI element. The card component is reusable, visually appealing with hover effects, and handles both images and actions.

Animations

Styled Components works well with CSS animations. Here's an example of a pulsing button:

jsx
import styled, { keyframes } from 'styled-components';

const pulse = keyframes`
0% {
box-shadow: 0 0 0 0 rgba(76, 175, 80, 0.7);
}
70% {
box-shadow: 0 0 0 15px rgba(76, 175, 80, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(76, 175, 80, 0);
}
`;

const PulsingButton = styled.button`
background-color: #4CAF50;
color: white;
border: none;
border-radius: 50px;
padding: 12px 30px;
font-size: 16px;
cursor: pointer;
animation: ${pulse} 2s infinite;
`;

function CallToAction() {
return <PulsingButton>Subscribe Now</PulsingButton>;
}

Best Practices

When working with Styled Components, keep these best practices in mind:

  1. Component organization: Consider organizing your styled components in separate files for complex components
  2. Naming conventions: Use descriptive names for your styled components (e.g., StyledButton instead of just Button)
  3. Prop naming: Be consistent with prop names that affect styling
  4. Theme usage: Leverage themes for consistent colors, spacing, and typography
  5. Avoid too many props: Don't over-complicate components with too many style-altering props
  6. Performance: For large applications, use the Babel plugin for Styled Components to improve performance

Component Organization Example

For a complex component, you might organize your files like this:

jsx
// Card/styles.js
import styled from 'styled-components';

export const CardWrapper = styled.div`
/* styles here */
`;

export const CardImage = styled.img`
/* styles here */
`;

export const CardContent = styled.div`
/* styles here */
`;

// Card/index.js
import React from 'react';
import { CardWrapper, CardImage, CardContent } from './styles';

function Card({ title, image, children }) {
return (
<CardWrapper>
{image && <CardImage src={image} alt={title} />}
<CardContent>
{children}
</CardContent>
</CardWrapper>
);
}

export default Card;

Summary

Styled Components offers a powerful way to handle styling in React applications by bringing CSS directly into your component code. This approach:

  • Eliminates the need for separate CSS files
  • Provides component-scoped CSS that won't leak
  • Enables dynamic styling based on props and state
  • Makes components truly self-contained with their own styles
  • Improves maintainability by keeping related code together

Through this tutorial, we've explored the basic concepts of Styled Components, how to style based on props, theming, animations, and organization patterns. With these tools, you can create maintainable, dynamic, and beautiful React applications.

Additional Resources

Here are some resources to deepen your knowledge of Styled Components:

Exercises

  1. Create a toggle switch component using Styled Components that changes color when toggled.
  2. Build a responsive navigation bar that collapses into a hamburger menu on mobile screens.
  3. Implement a theme switcher that allows users to toggle between light and dark themes.
  4. Create a loading spinner animation using the keyframes helper from Styled Components.
  5. Build a form with styled input fields that change appearance based on validation state (error, success).


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)