Styled Components
Styled Components is a popular CSS-in-JS library that enables you to write actual CSS code to style React components. It removes the mapping between components and styles, making component-based styling more intuitive and maintainable.
Core Concepts
CSS-in-JS Approach
- Definition: Write CSS directly within JavaScript/TypeScript files
- Benefits:
- Scoped styles with no class name conflicts
- Dynamic styling based on props
- Dead code elimination
- Better developer experience with IDE support
Installation & Setup
npm install styled-components
# For TypeScript support
npm install @types/styled-componentsBasic Usage
import styled from 'styled-components';
// Create a styled component
const Button = styled.button`
padding: 0.5rem 1rem;
background-color: ${props => props.primary ? '#007bff' : '#6c757d'};
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
&:hover {
opacity: 0.9;
}
`;
// Use the component
function App() {
return (
<div>
<Button>Normal Button</Button>
<Button primary>Primary Button</Button>
</div>
);
}Key Features
Dynamic Styling
const Box = styled.div`
width: ${props => props.width || '100px'};
height: ${props => props.height || '100px'};
background: ${props => props.bg || '#f0f0f0'};
`;
// Usage
<Box width="200px" height="150px" bg="#ff0000" />Extending Styles
const Button = styled.button`
padding: 0.5rem 1rem;
border: none;
border-radius: 4px;
`;
const PrimaryButton = styled(Button)`
background-color: #007bff;
color: white;
`;Global Styles
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
padding: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen;
}
`;
// Usage in root component
function App() {
return (
<>
<GlobalStyle />
{/* other components */}
</>
);
}Best Practices
Component Organization
- Separate Styled Components
- Keep styled components in separate files
- Group related styled components together
// Button.styles.js
import styled from 'styled-components';
export const Button = styled.button`
/* styles */
`;
export const ButtonGroup = styled.div`
/* styles */
`;- Props API Design
const Text = styled.p`
font-size: ${props => props.size || '1rem'};
color: ${props => props.color || '#000'};
${props => props.bold && 'font-weight: bold;'}
`;
// Usage
<Text size="1.2rem" color="#333" bold>
Styled Text
</Text>Theming
import { ThemeProvider } from 'styled-components';
const theme = {
colors: {
primary: '#007bff',
secondary: '#6c757d',
success: '#28a745'
},
spacing: {
small: '0.5rem',
medium: '1rem',
large: '1.5rem'
}
};
// Theme usage in components
const Button = styled.button`
background-color: ${props => props.theme.colors.primary};
padding: ${props => props.theme.spacing.medium};
`;
// Wrap your app with ThemeProvider
function App() {
return (
<ThemeProvider theme={theme}>
<Button>Themed Button</Button>
</ThemeProvider>
);
}Performance Optimization
- Use memoization for dynamic styles
- Avoid creating styled components inside render
- Leverage component composition
Common Patterns
Media Queries
const Container = styled.div`
width: 100%;
padding: 1rem;
@media (min-width: 768px) {
width: 750px;
margin: 0 auto;
}
@media (min-width: 1200px) {
width: 1170px;
}
`;Animation
import { keyframes } from 'styled-components';
const fadeIn = keyframes`
from { opacity: 0; }
to { opacity: 1; }
`;
const FadeInDiv = styled.div`
animation: ${fadeIn} 0.5s ease-in;
`;CSS Helper Functions
import { css } from 'styled-components';
const flexCenter = css`
display: flex;
align-items: center;
justify-content: center;
`;
const CenteredBox = styled.div`
${flexCenter}
width: 200px;
height: 200px;
`;