Styling Methods in React
React offers many ways to style components. Let's explore the most popular approaches.
Inline Styles
JavaScript objects for styles:
jsx
1function Button() {
2 const styles = {
3 backgroundColor: 'blue',
4 color: 'white',
5 padding: '10px 20px',
6 border: 'none',
7 borderRadius: '4px',
8 cursor: 'pointer'
9 }
10
11 return <button style={styles}>Click me</button>
12}
13
14// Dynamic styles
15function Box({ isActive }) {
16 return (
17 <div style={{
18 backgroundColor: isActive ? 'green' : 'gray',
19 opacity: isActive ? 1 : 0.5
20 }}>
21 Box
22 </div>
23 )
24}CSS Stylesheets
Traditional CSS files:
css
1/* Button.css */
2.btn {
3 padding: 10px 20px;
4 border: none;
5 border-radius: 4px;
6 cursor: pointer;
7}
8
9.btn-primary {
10 background-color: blue;
11 color: white;
12}
13
14.btn-danger {
15 background-color: red;
16 color: white;
17}jsx
1import './Button.css'
2
3function Button({ variant = 'primary', children }) {
4 return (
5 <button className={`btn btn-${variant}`}>
6 {children}
7 </button>
8 )
9}CSS Modules
Scoped CSS to prevent conflicts:
css
1/* Button.module.css */
2.button {
3 padding: 10px 20px;
4 border: none;
5 border-radius: 4px;
6}
7
8.primary {
9 background-color: blue;
10 color: white;
11}
12
13.danger {
14 background-color: red;
15 color: white;
16}jsx
1import styles from './Button.module.css'
2
3function Button({ variant = 'primary', children }) {
4 return (
5 <button className={`${styles.button} ${styles[variant]}`}>
6 {children}
7 </button>
8 )
9}
10
11// Classes become unique: Button_button__abc123Tailwind CSS
Utility-first CSS framework:
jsx
1function Card({ title, children }) {
2 return (
3 <div className="bg-white rounded-lg shadow-md p-6 hover:shadow-lg transition-shadow">
4 <h2 className="text-xl font-bold text-gray-800 mb-4">{title}</h2>
5 <div className="text-gray-600">{children}</div>
6 </div>
7 )
8}
9
10// Conditional classes
11function Button({ variant, disabled, children }) {
12 return (
13 <button
14 className={`
15 px-4 py-2 rounded-md font-medium
16 ${variant === 'primary' ? 'bg-blue-500 text-white hover:bg-blue-600' : ''}
17 ${variant === 'secondary' ? 'bg-gray-200 text-gray-800 hover:bg-gray-300' : ''}
18 ${disabled ? 'opacity-50 cursor-not-allowed' : ''}
19 `}
20 disabled={disabled}
21 >
22 {children}
23 </button>
24 )
25}clsx/classnames Library
jsx
1import clsx from 'clsx'
2
3function Button({ variant, size, disabled, children }) {
4 return (
5 <button
6 className={clsx(
7 'rounded-md font-medium',
8 {
9 'bg-blue-500 text-white': variant === 'primary',
10 'bg-gray-200 text-gray-800': variant === 'secondary',
11 'px-2 py-1 text-sm': size === 'small',
12 'px-4 py-2': size === 'medium',
13 'px-6 py-3 text-lg': size === 'large',
14 'opacity-50 cursor-not-allowed': disabled
15 }
16 )}
17 >
18 {children}
19 </button>
20 )
21}Styled Components
CSS-in-JS library:
bash
1npm install styled-componentsjsx
1import styled from 'styled-components'
2
3const Button = styled.button`
4 padding: 10px 20px;
5 border: none;
6 border-radius: 4px;
7 cursor: pointer;
8 background-color: ${props => props.primary ? 'blue' : 'gray'};
9 color: white;
10
11 &:hover {
12 opacity: 0.9;
13 }
14
15 &:disabled {
16 opacity: 0.5;
17 cursor: not-allowed;
18 }
19`
20
21const Card = styled.div`
22 background: white;
23 border-radius: 8px;
24 box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
25 padding: 20px;
26`
27
28const Title = styled.h2`
29 font-size: 1.5rem;
30 color: #333;
31 margin-bottom: 1rem;
32`
33
34// Usage
35function App() {
36 return (
37 <Card>
38 <Title>Hello World</Title>
39 <Button primary>Primary</Button>
40 <Button>Secondary</Button>
41 </Card>
42 )
43}Extending Styles
jsx
1const Button = styled.button`
2 padding: 10px 20px;
3 border-radius: 4px;
4`
5
6const PrimaryButton = styled(Button)`
7 background: blue;
8 color: white;
9`
10
11const DangerButton = styled(Button)`
12 background: red;
13 color: white;
14`Emotion
Another CSS-in-JS library:
bash
1npm install @emotion/react @emotion/styledjsx
1/** @jsxImportSource @emotion/react */
2import { css } from '@emotion/react'
3import styled from '@emotion/styled'
4
5// css prop
6function Button({ children }) {
7 return (
8 <button
9 css={css`
10 padding: 10px 20px;
11 background: blue;
12 color: white;
13 border: none;
14 border-radius: 4px;
15
16 &:hover {
17 background: darkblue;
18 }
19 `}
20 >
21 {children}
22 </button>
23 )
24}
25
26// styled API
27const Card = styled.div`
28 background: white;
29 padding: 20px;
30 border-radius: 8px;
31`CSS Variables with React
jsx
1// Define in CSS
2:root {
3 --primary-color: #3498db;
4 --secondary-color: #2ecc71;
5 --text-color: #333;
6}
7
8// Use in components
9function ThemedButton() {
10 return (
11 <button style={{ backgroundColor: 'var(--primary-color)' }}>
12 Themed Button
13 </button>
14 )
15}
16
17// Dynamic theme switching
18function ThemeProvider({ theme, children }) {
19 return (
20 <div
21 style={{
22 '--primary-color': theme.primary,
23 '--secondary-color': theme.secondary,
24 '--text-color': theme.text
25 }}
26 >
27 {children}
28 </div>
29 )
30}Comparison
| Method | Scoped | Dynamic | Bundle Size | DX |
|---|---|---|---|---|
| Inline | ✅ | ✅ | None | OK |
| CSS Files | ❌ | ❌ | Small | Good |
| CSS Modules | ✅ | ❌ | Small | Good |
| Tailwind | ✅ | ✅ | Varies | Great |
| Styled Components | ✅ | ✅ | ~12KB | Great |
| Emotion | ✅ | ✅ | ~7KB | Great |
Choose based on your team's preferences and project needs!
