0
# External CSS
1
2
CSS utilities for creating styles outside of JSX components, including scoped class generation and global style definition.
3
4
## Capabilities
5
6
### css Function (Default Export)
7
8
Creates scoped CSS styles outside of JSX components. Requires Babel transformation to function properly.
9
10
```typescript { .api }
11
/**
12
* Creates scoped CSS styles (compile-time only)
13
* @param chunks - Template literal string chunks
14
* @param args - Template literal interpolated values
15
* @returns JSX style element (after Babel transformation)
16
* @throws Error if not processed by styled-jsx Babel plugin
17
*/
18
function css(chunks: TemplateStringsArray, ...args: any[]): JSX.Element;
19
```
20
21
**Usage Examples:**
22
23
```jsx
24
import css from 'styled-jsx/css';
25
26
// Basic scoped CSS
27
const buttonStyles = css`
28
.button {
29
padding: 12px 24px;
30
border: none;
31
border-radius: 4px;
32
cursor: pointer;
33
font-size: 16px;
34
}
35
.button:hover {
36
opacity: 0.9;
37
}
38
`;
39
40
function Button({ children }) {
41
return (
42
<div>
43
<button className="button">{children}</button>
44
{buttonStyles}
45
</div>
46
);
47
}
48
49
// With dynamic values
50
function createThemeStyles(theme) {
51
return css`
52
.container {
53
background: ${theme.background};
54
color: ${theme.text};
55
padding: ${theme.spacing.medium};
56
}
57
.header {
58
border-bottom: 1px solid ${theme.border};
59
margin-bottom: ${theme.spacing.large};
60
}
61
`;
62
}
63
64
function ThemedComponent({ theme, children }) {
65
const styles = createThemeStyles(theme);
66
67
return (
68
<div className="container">
69
<div className="header">Header</div>
70
{children}
71
{styles}
72
</div>
73
);
74
}
75
```
76
77
### css.global Function
78
79
Creates global CSS styles that are not scoped to components.
80
81
```typescript { .api }
82
/**
83
* Creates global CSS styles (compile-time only)
84
* @param chunks - Template literal string chunks
85
* @param args - Template literal interpolated values
86
* @returns JSX style element with global styles (after Babel transformation)
87
* @throws Error if not processed by styled-jsx Babel plugin
88
*/
89
function css.global(
90
chunks: TemplateStringsArray,
91
...args: any[]
92
): JSX.Element;
93
```
94
95
**Usage Examples:**
96
97
```jsx
98
import css from 'styled-jsx/css';
99
100
// Global reset styles
101
const globalReset = css.global`
102
* {
103
margin: 0;
104
padding: 0;
105
box-sizing: border-box;
106
}
107
108
html, body {
109
height: 100%;
110
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
111
}
112
113
button {
114
font-family: inherit;
115
}
116
`;
117
118
function App() {
119
return (
120
<div>
121
<h1>My Application</h1>
122
{globalReset}
123
</div>
124
);
125
}
126
127
// Dynamic global styles
128
function createGlobalTheme(theme) {
129
return css.global`
130
:root {
131
--primary-color: ${theme.primary};
132
--secondary-color: ${theme.secondary};
133
--background-color: ${theme.background};
134
--text-color: ${theme.text};
135
}
136
137
body {
138
background-color: var(--background-color);
139
color: var(--text-color);
140
}
141
142
.btn-primary {
143
background-color: var(--primary-color);
144
color: white;
145
}
146
`;
147
}
148
149
function ThemeProvider({ theme, children }) {
150
const globalTheme = createGlobalTheme(theme);
151
152
return (
153
<div>
154
{globalTheme}
155
{children}
156
</div>
157
);
158
}
159
```
160
161
### css.resolve Function
162
163
Creates scoped CSS that returns both the generated className and the style element, useful for styling external components.
164
165
```typescript { .api }
166
/**
167
* Creates scoped CSS that returns className and styles (compile-time only)
168
* @param chunks - Template literal string chunks
169
* @param args - Template literal interpolated values
170
* @returns Object with className and styles (after Babel transformation)
171
* @throws Error if not processed by styled-jsx Babel plugin
172
*/
173
function css.resolve(
174
chunks: TemplateStringsArray,
175
...args: any[]
176
): { className: string; styles: JSX.Element };
177
```
178
179
**Usage Examples:**
180
181
```jsx
182
import css from 'styled-jsx/css';
183
import ExternalComponent from 'some-library';
184
185
// Basic resolve usage
186
function StyledExternalComponent() {
187
const { className, styles } = css.resolve`
188
a {
189
color: #007bff;
190
text-decoration: none;
191
font-weight: 500;
192
}
193
a:hover {
194
text-decoration: underline;
195
}
196
`;
197
198
return (
199
<div>
200
<ExternalComponent className={className} />
201
{styles}
202
</div>
203
);
204
}
205
206
// Dynamic resolve styles
207
function createLinkStyles(color, size) {
208
return css.resolve`
209
a {
210
color: ${color};
211
font-size: ${size};
212
text-decoration: none;
213
border-bottom: 1px solid transparent;
214
transition: border-color 0.2s;
215
}
216
a:hover {
217
border-bottom-color: ${color};
218
}
219
`;
220
}
221
222
function CustomLink({ href, color = '#007bff', size = '16px', children }) {
223
const { className, styles } = createLinkStyles(color, size);
224
225
return (
226
<div>
227
<a href={href} className={className}>
228
{children}
229
</a>
230
{styles}
231
</div>
232
);
233
}
234
235
// Multiple resolved styles
236
function MultiStyleComponent() {
237
const buttonStyle = css.resolve`
238
button {
239
padding: 8px 16px;
240
border: none;
241
border-radius: 4px;
242
background: #007bff;
243
color: white;
244
cursor: pointer;
245
}
246
`;
247
248
const inputStyle = css.resolve`
249
input {
250
padding: 8px 12px;
251
border: 1px solid #ccc;
252
border-radius: 4px;
253
font-size: 14px;
254
}
255
input:focus {
256
outline: none;
257
border-color: #007bff;
258
box-shadow: 0 0 0 2px rgba(0, 123, 255, 0.25);
259
}
260
`;
261
262
return (
263
<form>
264
<input className={inputStyle.className} placeholder="Enter text" />
265
<button className={buttonStyle.className} type="submit">
266
Submit
267
</button>
268
{inputStyle.styles}
269
{buttonStyle.styles}
270
</form>
271
);
272
}
273
```
274
275
### Styling Third-Party Components
276
277
Common patterns for styling external libraries and components using css.resolve.
278
279
```jsx { .api }
280
// Pattern for styling third-party components
281
const { className, styles } = css.resolve`/* styles */`;
282
<ExternalComponent className={className} />
283
{styles}
284
```
285
286
**Usage Examples:**
287
288
```jsx
289
import css from 'styled-jsx/css';
290
import Select from 'react-select';
291
import DatePicker from 'react-datepicker';
292
import 'react-datepicker/dist/react-datepicker.css';
293
294
// Styling react-select
295
function CustomSelect({ options, value, onChange }) {
296
const { className, styles } = css.resolve`
297
.react-select__control {
298
border: 2px solid #e1e5e9 !important;
299
border-radius: 8px !important;
300
min-height: 44px !important;
301
box-shadow: none !important;
302
}
303
304
.react-select__control--is-focused {
305
border-color: #007bff !important;
306
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1) !important;
307
}
308
309
.react-select__value-container {
310
padding: 8px 12px !important;
311
}
312
313
.react-select__option--is-focused {
314
background-color: #f8f9fa !important;
315
}
316
317
.react-select__option--is-selected {
318
background-color: #007bff !important;
319
}
320
`;
321
322
return (
323
<div>
324
<Select
325
className={className}
326
classNamePrefix="react-select"
327
options={options}
328
value={value}
329
onChange={onChange}
330
/>
331
{styles}
332
</div>
333
);
334
}
335
336
// Styling react-datepicker
337
function CustomDatePicker({ selected, onChange }) {
338
const { className, styles } = css.resolve`
339
.react-datepicker-wrapper {
340
width: 100%;
341
}
342
343
.react-datepicker__input-container input {
344
width: 100%;
345
padding: 12px 16px;
346
border: 2px solid #e1e5e9;
347
border-radius: 8px;
348
font-size: 16px;
349
background: white;
350
}
351
352
.react-datepicker__input-container input:focus {
353
outline: none;
354
border-color: #007bff;
355
box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1);
356
}
357
358
.react-datepicker {
359
border: 1px solid #e1e5e9;
360
border-radius: 8px;
361
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
362
}
363
364
.react-datepicker__header {
365
background-color: #007bff;
366
border-bottom: none;
367
border-radius: 8px 8px 0 0;
368
}
369
370
.react-datepicker__current-month {
371
color: white;
372
}
373
374
.react-datepicker__day--selected {
375
background-color: #007bff;
376
border-radius: 4px;
377
}
378
`;
379
380
return (
381
<div className={className}>
382
<DatePicker
383
selected={selected}
384
onChange={onChange}
385
dateFormat="MM/dd/yyyy"
386
placeholderText="Select a date"
387
/>
388
{styles}
389
</div>
390
);
391
}
392
393
// Modal/Dialog styling
394
import Modal from 'react-modal';
395
396
function StyledModal({ isOpen, onRequestClose, children }) {
397
const { className, styles } = css.resolve`
398
.modal-overlay {
399
background-color: rgba(0, 0, 0, 0.6) !important;
400
display: flex !important;
401
align-items: center !important;
402
justify-content: center !important;
403
}
404
405
.modal-content {
406
background: white !important;
407
border-radius: 12px !important;
408
padding: 24px !important;
409
max-width: 500px !important;
410
max-height: 80vh !important;
411
overflow-y: auto !important;
412
border: none !important;
413
outline: none !important;
414
position: relative !important;
415
}
416
`;
417
418
return (
419
<div>
420
<Modal
421
isOpen={isOpen}
422
onRequestClose={onRequestClose}
423
className={{
424
base: `modal-content ${className}`,
425
afterOpen: 'modal-content--after-open',
426
beforeClose: 'modal-content--before-close'
427
}}
428
overlayClassName={{
429
base: `modal-overlay ${className}`,
430
afterOpen: 'modal-overlay--after-open',
431
beforeClose: 'modal-overlay--before-close'
432
}}
433
>
434
{children}
435
</Modal>
436
{styles}
437
</div>
438
);
439
}
440
```
441
442
### Error Handling
443
444
Common error scenarios and solutions when using styled-jsx/css functions.
445
446
#### Transpilation Errors
447
448
All css functions must be processed by the styled-jsx Babel plugin. Without proper transpilation, runtime errors will occur.
449
450
```typescript { .api }
451
/**
452
* Runtime error thrown when css functions are not transpiled
453
* Occurs when Babel plugin is not configured or working properly
454
*/
455
class TranspilationError extends Error {
456
message: "styled-jsx/css: if you are getting this error it means that your `css` tagged template literals were not transpiled.";
457
}
458
```
459
460
**Common Error Scenarios:**
461
462
```jsx
463
import css from 'styled-jsx/css';
464
465
// ❌ This will throw an error if Babel plugin is not configured
466
const styles = css`
467
.button { color: red; }
468
`;
469
// Error: styled-jsx/css: if you are getting this error it means that your `css` tagged template literals were not transpiled.
470
471
// ❌ Same error for css.global
472
const globalStyles = css.global`
473
body { margin: 0; }
474
`;
475
// Error: styled-jsx/css: if you are getting this error it means that your `global` tagged template literals were not transpiled.
476
477
// ❌ Same error for css.resolve
478
const { className, styles } = css.resolve`
479
.link { color: blue; }
480
`;
481
// Error: styled-jsx/css: if you are getting this error it means that your `resolve` tagged template literals were not transpiled.
482
```
483
484
**Solutions:**
485
486
1. **Configure Babel Plugin:**
487
488
```json
489
// .babelrc or babel.config.js
490
{
491
"plugins": ["styled-jsx/babel"]
492
}
493
```
494
495
2. **Next.js (built-in support):**
496
497
```jsx
498
// No configuration needed - styled-jsx is built into Next.js
499
export default function Page() {
500
return (
501
<div>
502
<style jsx>{`
503
.container { padding: 20px; }
504
`}</style>
505
</div>
506
);
507
}
508
```
509
510
3. **Webpack Configuration:**
511
512
```javascript
513
// webpack.config.js
514
module.exports = {
515
module: {
516
rules: [
517
{
518
test: /\.(js|jsx)$/,
519
use: {
520
loader: 'babel-loader',
521
options: {
522
plugins: ['styled-jsx/babel']
523
}
524
}
525
}
526
]
527
}
528
};
529
```
530
531
4. **Development vs Production:**
532
533
```javascript
534
// babel.config.js
535
module.exports = {
536
plugins: [
537
[
538
'styled-jsx/babel',
539
{
540
optimizeForSpeed: process.env.NODE_ENV === 'production',
541
sourceMaps: process.env.NODE_ENV === 'development'
542
}
543
]
544
]
545
};
546
```
547
548
#### Build Environment Issues
549
550
**Problem:** CSS functions work in development but fail in production builds.
551
552
**Solution:** Ensure Babel plugin is included in production configuration:
553
554
```javascript
555
// babel.config.js
556
module.exports = {
557
presets: ['@babel/preset-env', '@babel/preset-react'],
558
plugins: ['styled-jsx/babel'],
559
env: {
560
production: {
561
plugins: [
562
['styled-jsx/babel', { optimizeForSpeed: true }]
563
]
564
}
565
}
566
};
567
```
568
569
#### TypeScript Integration
570
571
**Problem:** TypeScript compilation errors with css template literals.
572
573
**Solution:** Install types and configure properly:
574
575
```bash
576
npm install --save-dev @types/styled-jsx
577
```
578
579
```json
580
// tsconfig.json
581
{
582
"compilerOptions": {
583
"jsx": "preserve",
584
"types": ["styled-jsx"]
585
}
586
}
587
```
588
589
#### Server-Side Rendering Issues
590
591
**Problem:** Styles not being extracted during SSR.
592
593
**Solution:** Use StyleRegistry for proper SSR handling:
594
595
```jsx
596
import { StyleRegistry, createStyleRegistry } from 'styled-jsx';
597
import css from 'styled-jsx/css';
598
599
// ✅ Correct SSR setup
600
function renderPage() {
601
const registry = createStyleRegistry();
602
603
const appHtml = ReactDOM.renderToString(
604
<StyleRegistry registry={registry}>
605
<App />
606
</StyleRegistry>
607
);
608
609
const styles = registry.styles();
610
611
return { appHtml, styles };
612
}
613
```