0
# Component Styling
1
2
Core CSS-in-JS functionality for writing scoped styles directly in JSX components with full CSS support and automatic scoping.
3
4
## Capabilities
5
6
### Basic Scoped Styles
7
8
The fundamental way to add CSS to React components. Styles are automatically scoped to the component using unique class names.
9
10
```jsx { .api }
11
<style jsx>{`/* CSS rules */`}</style>
12
```
13
14
**Usage Example:**
15
16
```jsx
17
function Card({ title, children }) {
18
return (
19
<div className="card">
20
<h2>{title}</h2>
21
<div className="content">{children}</div>
22
<style jsx>{`
23
.card {
24
border: 1px solid #ddd;
25
border-radius: 8px;
26
padding: 16px;
27
margin: 8px;
28
background: white;
29
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
30
}
31
.content {
32
margin-top: 12px;
33
line-height: 1.5;
34
}
35
h2 {
36
margin: 0;
37
color: #333;
38
font-size: 1.2em;
39
}
40
`}</style>
41
</div>
42
);
43
}
44
```
45
46
### Global Styles
47
48
Apply styles globally across the entire application, bypassing component scoping.
49
50
```jsx { .api }
51
<style jsx global>{`/* Global CSS rules */`}</style>
52
```
53
54
**Usage Example:**
55
56
```jsx
57
function App() {
58
return (
59
<div>
60
<h1>My App</h1>
61
<style jsx global>{`
62
body {
63
margin: 0;
64
padding: 0;
65
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
66
background: #f5f5f5;
67
}
68
* {
69
box-sizing: border-box;
70
}
71
h1, h2, h3 {
72
color: #2c3e50;
73
}
74
`}</style>
75
</div>
76
);
77
}
78
```
79
80
### Dynamic Styles
81
82
Use JavaScript expressions within CSS for props-based styling and conditional styles.
83
84
```jsx { .api }
85
<style jsx>{`
86
.element {
87
property: ${expression};
88
}
89
`}</style>
90
```
91
92
**Usage Examples:**
93
94
```jsx
95
// Props-based styling
96
function Button({ size = 'medium', variant = 'primary', disabled, children }) {
97
const sizes = {
98
small: { padding: '8px 16px', fontSize: '14px' },
99
medium: { padding: '12px 24px', fontSize: '16px' },
100
large: { padding: '16px 32px', fontSize: '18px' }
101
};
102
103
const variants = {
104
primary: { background: '#007bff', color: 'white' },
105
secondary: { background: '#6c757d', color: 'white' },
106
outline: { background: 'transparent', color: '#007bff', border: '1px solid #007bff' }
107
};
108
109
return (
110
<button disabled={disabled}>
111
{children}
112
<style jsx>{`
113
button {
114
padding: ${sizes[size].padding};
115
font-size: ${sizes[size].fontSize};
116
background: ${disabled ? '#e9ecef' : variants[variant].background};
117
color: ${disabled ? '#6c757d' : variants[variant].color};
118
border: ${variants[variant].border || 'none'};
119
border-radius: 4px;
120
cursor: ${disabled ? 'not-allowed' : 'pointer'};
121
transition: all 0.2s ease;
122
}
123
button:hover {
124
opacity: ${disabled ? '1' : '0.9'};
125
transform: ${disabled ? 'none' : 'translateY(-1px)'};
126
}
127
`}</style>
128
</button>
129
);
130
}
131
132
// State-based styling
133
function Toggle({ isOn, onToggle }) {
134
return (
135
<div className="toggle" onClick={onToggle}>
136
<div className="slider" />
137
<style jsx>{`
138
.toggle {
139
width: 60px;
140
height: 30px;
141
background: ${isOn ? '#4CAF50' : '#ccc'};
142
border-radius: 15px;
143
position: relative;
144
cursor: pointer;
145
transition: background 0.3s;
146
}
147
.slider {
148
width: 26px;
149
height: 26px;
150
background: white;
151
border-radius: 50%;
152
position: absolute;
153
top: 2px;
154
left: ${isOn ? '32px' : '2px'};
155
transition: left 0.3s;
156
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
157
}
158
`}</style>
159
</div>
160
);
161
}
162
```
163
164
### Targeting Root Element
165
166
Target the component's root element using class names, similar to CSS-in-JS :host selector.
167
168
```jsx { .api }
169
// Root element gets jsx-* class automatically
170
<div className="root">
171
<style jsx>{`
172
.root {
173
/* styles for root element */
174
}
175
`}</style>
176
</div>
177
```
178
179
**Usage Example:**
180
181
```jsx
182
function Modal({ isOpen, onClose, children }) {
183
if (!isOpen) return null;
184
185
return (
186
<div className="modal-overlay">
187
<div className="modal">
188
<button className="close" onClick={onClose}>×</button>
189
{children}
190
<style jsx>{`
191
.modal-overlay {
192
position: fixed;
193
top: 0;
194
left: 0;
195
right: 0;
196
bottom: 0;
197
background: rgba(0, 0, 0, 0.5);
198
display: flex;
199
align-items: center;
200
justify-content: center;
201
z-index: 1000;
202
}
203
.modal {
204
background: white;
205
border-radius: 8px;
206
padding: 24px;
207
max-width: 500px;
208
max-height: 80vh;
209
overflow-y: auto;
210
position: relative;
211
}
212
.close {
213
position: absolute;
214
top: 8px;
215
right: 12px;
216
background: none;
217
border: none;
218
font-size: 24px;
219
cursor: pointer;
220
color: #999;
221
}
222
.close:hover {
223
color: #333;
224
}
225
`}</style>
226
</div>
227
</div>
228
);
229
}
230
```
231
232
### One-off Global Selectors
233
234
Use `:global()` pseudo-selector to target elements without scoping, useful for styling third-party components.
235
236
```jsx { .api }
237
<style jsx>{`
238
:global(.third-party-class) {
239
/* unscoped styles */
240
}
241
.local-class :global(.nested-global) {
242
/* mixed scoped and global */
243
}
244
`}</style>
245
```
246
247
**Usage Example:**
248
249
```jsx
250
import Select from 'react-select';
251
252
function CustomSelect({ options, value, onChange }) {
253
return (
254
<div className="select-container">
255
<Select
256
options={options}
257
value={value}
258
onChange={onChange}
259
className="react-select"
260
classNamePrefix="react-select"
261
/>
262
<style jsx>{`
263
.select-container {
264
margin: 16px 0;
265
}
266
267
/* Style react-select components globally */
268
.select-container :global(.react-select__control) {
269
border: 2px solid #e1e5e9;
270
border-radius: 8px;
271
min-height: 44px;
272
box-shadow: none;
273
}
274
275
.select-container :global(.react-select__control--is-focused) {
276
border-color: #007bff;
277
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
278
}
279
280
.select-container :global(.react-select__option--is-focused) {
281
background-color: #f8f9fa;
282
}
283
284
.select-container :global(.react-select__option--is-selected) {
285
background-color: #007bff;
286
}
287
`}</style>
288
</div>
289
);
290
}
291
```
292
293
### Constants and External Values
294
295
Use constants defined outside component scope for consistent theming and reusable values.
296
297
```jsx { .api }
298
// Constants are treated as static styles (no re-computation)
299
const theme = { primary: '#007bff', spacing: '16px' };
300
301
<style jsx>{`
302
.element {
303
color: ${theme.primary};
304
margin: ${theme.spacing};
305
}
306
`}</style>
307
```
308
309
**Usage Example:**
310
311
```jsx
312
// theme.js
313
export const theme = {
314
colors: {
315
primary: '#007bff',
316
secondary: '#6c757d',
317
success: '#28a745',
318
danger: '#dc3545',
319
warning: '#ffc107',
320
info: '#17a2b8',
321
light: '#f8f9fa',
322
dark: '#343a40'
323
},
324
spacing: {
325
xs: '4px',
326
sm: '8px',
327
md: '16px',
328
lg: '24px',
329
xl: '32px'
330
},
331
breakpoints: {
332
sm: '576px',
333
md: '768px',
334
lg: '992px',
335
xl: '1200px'
336
}
337
};
338
339
// Component using theme constants
340
import { theme } from './theme';
341
342
function Alert({ type = 'info', children }) {
343
return (
344
<div className={`alert alert-${type}`}>
345
{children}
346
<style jsx>{`
347
.alert {
348
padding: ${theme.spacing.md};
349
margin: ${theme.spacing.sm} 0;
350
border: 1px solid transparent;
351
border-radius: 4px;
352
}
353
.alert-primary {
354
background-color: ${theme.colors.primary}15;
355
border-color: ${theme.colors.primary}30;
356
color: ${theme.colors.primary};
357
}
358
.alert-success {
359
background-color: ${theme.colors.success}15;
360
border-color: ${theme.colors.success}30;
361
color: ${theme.colors.success};
362
}
363
.alert-danger {
364
background-color: ${theme.colors.danger}15;
365
border-color: ${theme.colors.danger}30;
366
color: ${theme.colors.danger};
367
}
368
@media (max-width: ${theme.breakpoints.md}) {
369
.alert {
370
padding: ${theme.spacing.sm};
371
margin: ${theme.spacing.xs} 0;
372
}
373
}
374
`}</style>
375
</div>
376
);
377
}
378
```