CSS-in-JS has transformed how we style React applications. Let's explore the two most popular solutions.
What is CSS-in-JS?
CSS-in-JS uses JavaScript to style components, offering:
- Scoped styles by default
- Dynamic styling with props
- Theme support
- Critical CSS extraction
- No class name conflicts
Styled Components
Installation
bash
npm install styled-componentsBasic Usage
javascript
import styled from 'styled-components';
const Button = styled.button`
background: ${props => props.primary ? '#0066cc' : '#ffffff'};
color: ${props => props.primary ? '#ffffff' : '#0066cc'};
padding: 12px 24px;
border-radius: 4px;
border: 2px solid #0066cc;
cursor: pointer;
`;
// Usage
<Button primary>Click me</Button>Advanced Features
Theming
javascript
import { ThemeProvider } from 'styled-components';
const theme = {
colors: {
primary: '#0066cc',
secondary: '#6c757d'
}
};
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>Adapting based on props
javascript
const Button = styled.button`
font-size: ${props => `
${props.small ? '12px' : props.large ? '18px' : '14px'}
`};
`;Global Styles
javascript
import { createGlobalStyle } from 'styled-components';
const GlobalStyle = createGlobalStyle`
body {
margin: 0;
font-family: -apple-system, sans-serif;
}
`;Emotion
Installation
bash
npm install @emotion/react @emotion/styledBasic Usage
javascript
import styled from '@emotion/styled';
const Button = styled.button`
background: ${props => props.primary ? '#0066cc' : '#ffffff'};
color: ${props => props.primary ? '#ffffff' : '#0066cc'};
padding: 12px 24px;
border-radius: 4px;
border: 2px solid #0066cc;
cursor: pointer;
`;CSS Prop
Emotion's unique feature:
jsx
/** @jsxImportSource @emotion/react */
<div css={`
background: #0066cc;
color: white;
padding: 12px;
`}>
Styled div
</div>Performance Comparison
Bundle Size
- Styled Components: ~13KB gzipped
- Emotion: ~3KB gzipped
Winner: Emotion 🏆
Runtime Performance
Both libraries generate unique class names, but:
- Styled Components: Uses components, slightly slower
- Emotion: Uses babel plugin, faster at runtime
Winner: Emotion 🏆
Developer Experience
- Styled Components: More intuitive API, better documentation
- Emotion: More flexible, CSS prop is powerful
Tie 🤝
When to Use Each
Choose Styled Components when:
- Building a design system
- Want excellent documentation
- Prefer component-based API
- Need consistent theming
Choose Emotion when:
- Bundle size is critical
- Need maximum flexibility
- Want the CSS prop
- Building performance-critical apps
Best Practices
1. Use Theme Prop
javascript
const Button = styled.button`
background: ${props => props.theme.colors.primary};
`;2. Avoid Inline Styles in Components
javascript
// Bad
const Badge = styled.span`
top: ${props => props.position.top}px;
left: ${props => props.position.left}px;
`;
// Good
const Badge = styled.span`
position: absolute;
top: ${props => props.top}px;
left: ${props => props.left}px;
`;3. Extract Reusable Styles
javascript
import { css } from 'styled-components';
const flexCenter = css`
display: flex;
justify-content: center;
align-items: center;
`;
const Container = styled.div`
${flexCenter}
height: 100vh;
`;4. Use TypeScript
typescript
import styled from 'styled-components';
interface ButtonProps {
primary?: boolean;
size?: 'small' | 'medium' | 'large';
}
const Button = styled.button<ButtonProps>`
// Types are now available
`;SSR Setup
Styled Components
javascript
import { ServerStyleSheet } from 'styled-components';
app.get('*', (req, res) => {
const sheet = new ServerStyleSheet();
const html = ReactDOMServer.renderToString(
sheet.collectStyles(<App />)
);
const styles = sheet.getStyleTags();
res.send(`
<!DOCTYPE html>
<html>
<head>${styles}</head>
<body>${html}</body>
</html>
`);
});Emotion
javascript
import { renderStylesToString } from '@emotion/server';
const html = ReactDOMServer.renderToString(<App />);
const styles = renderStylesToString(html);
res.send(`
<!DOCTYPE html>
<html>
<head>${styles}</head>
<body>${html}</body>
</html>
`);Migration Tips
From CSS Modules
- 1Start with new components
- 2Migrate one component at a time
- 3Use styled-components/macros for performance
- 4Set up theme provider early
From Plain CSS
- 1Create styled component for each element
- 2Copy CSS rules into template literal
- 3Convert dynamic values to props
- 4Extract theme values
Conclusion
Both Styled Components and Emotion are excellent choices. Pick based on your priorities: use Styled Components for DX and ecosystem, or Emotion for performance and flexibility. Either way, CSS-in-JS will improve your styling workflow.