1 | # styled-jsx
|
2 |
|
3 | [![Build Status](https://travis-ci.org/zeit/styled-jsx.svg?branch=master)](https://travis-ci.org/zeit/styled-jsx)
|
4 | [![XO code style](https://img.shields.io/badge/code_style-XO-5ed9c7.svg)](https://github.com/sindresorhus/xo)
|
5 | [![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
|
6 | [![Slack Channel](http://zeit-slackin.now.sh/badge.svg)](https://zeit.chat)
|
7 |
|
8 | Full, scoped and component-friendly CSS support for JSX (rendered on the server or the client).
|
9 |
|
10 |
|
11 | Code and docs are for v2 which we highly recommend you to try. Looking for styled-jsx v1? Switch to the [v1 branch](https://github.com/zeit/styled-jsx/tree/v1).
|
12 |
|
13 | For an overview about the **features** and **tradeoffs** of styled-jsx you may want to take a look at [this presentation](https://speakerdeck.com/giuseppe/styled-jsx).
|
14 |
|
15 | - [Getting started](#getting-started)
|
16 | - [Configuration options](#configuration-options)
|
17 | * [`optimizeForSpeed`](#optimizeforspeed)
|
18 | * [`sourceMaps`](#sourcemaps)
|
19 | * [`vendorPrefixes`](#vendorprefixes)
|
20 | - [Features](#features)
|
21 | - [How It Works](#how-it-works)
|
22 | * [Why It Works Like This](#why-it-works-like-this)
|
23 | - [Targeting The Root](#targeting-the-root)
|
24 | - [Keeping CSS in separate files](#keeping-css-in-separate-files)
|
25 | - [Styles outside of components](#styles-outside-of-components)
|
26 | - [Global styles](#global-styles)
|
27 | * [One-off global selectors](#one-off-global-selectors)
|
28 | - [Dynamic styles](#dynamic-styles)
|
29 | * [Via interpolated dynamic props](#via-interpolated-dynamic-props)
|
30 | * [Via `className` toggling](#via-classname-toggling)
|
31 | * [Via inline `style`](#via-inline-style)
|
32 | - [Constants](#constants)
|
33 | - [Server-Side Rendering](#server-side-rendering)
|
34 | * [`styled-jsx/server`](#-styled-jsx-server)
|
35 | - [CSS Preprocessing via Plugins](#css-preprocessing-via-plugins)
|
36 | * [Plugin options](#plugin-options)
|
37 | * [Example plugins](#example-plugins)
|
38 | - [FAQ](#faq)
|
39 | * [Warning: unknown `jsx` prop on <style> tag](#warning-unknown-jsx-prop-on-style-tag)
|
40 | * [Can I return an array of components when using React 16?](#can-i-return-an-array-of-components-when-using-react-16)
|
41 | * [Styling third parties / child components from the parent](#styling-third-parties--child-components-from-the-parent)
|
42 | * [Some styles are missing in production](https://github.com/zeit/styled-jsx/issues/319#issuecomment-349239326)
|
43 | - [Syntax Highlighting](#syntax-highlighting)
|
44 |
|
45 | ## Getting started
|
46 |
|
47 | Firstly, install the package:
|
48 |
|
49 | ```bash
|
50 | npm install --save styled-jsx
|
51 | ```
|
52 |
|
53 | Next, add `styled-jsx/babel` to `plugins` in your babel configuration:
|
54 |
|
55 | ```json
|
56 | {
|
57 | "plugins": [
|
58 | "styled-jsx/babel"
|
59 | ]
|
60 | }
|
61 | ```
|
62 |
|
63 | Now add `<style jsx>` to your code and fill it with CSS:
|
64 |
|
65 | ```jsx
|
66 | export default () => (
|
67 | <div>
|
68 | <p>only this paragraph will get the style :)</p>
|
69 |
|
70 | { /* you can include <Component />s here that include
|
71 | other <p>s that don't get unexpected styles! */ }
|
72 |
|
73 | <style jsx>{`
|
74 | p {
|
75 | color: red;
|
76 | }
|
77 | `}</style>
|
78 | </div>
|
79 | )
|
80 | ```
|
81 |
|
82 | ## Configuration options
|
83 |
|
84 | The following are optional settings for the babel plugin.
|
85 |
|
86 | #### `optimizeForSpeed`
|
87 |
|
88 | Blazing fast and optimized CSS rules injection system based on the CSSOM APIs.
|
89 |
|
90 | ```
|
91 | {
|
92 | "plugins": [
|
93 | ["styled-jsx/babel", { "optimizeForSpeed": true }]
|
94 | ]
|
95 | }
|
96 | ```
|
97 | When in production\* this mode is automatically enabled.<br>
|
98 | Beware that when using this option source maps cannot be generated and styles cannot be edited via the devtools.
|
99 |
|
100 | \* `process.env.NODE_ENV === 'production'`
|
101 |
|
102 |
|
103 | #### `sourceMaps`
|
104 |
|
105 | Generates source maps (default: `false`)
|
106 |
|
107 | #### `vendorPrefixes`
|
108 |
|
109 | Turn on/off automatic vendor prefixing (default: `true`)
|
110 |
|
111 | ## Features
|
112 |
|
113 | - Full CSS support, no tradeoffs in power
|
114 | - Runtime size of just **3kb** (gzipped, from 12kb)
|
115 | - Complete isolation: Selectors, animations, keyframes
|
116 | - Built-in CSS vendor prefixing
|
117 | - Very fast, minimal and efficient transpilation (see below)
|
118 | - High-performance runtime-CSS-injection when not server-rendering
|
119 | - Future-proof: Equivalent to server-renderable "Shadow CSS"
|
120 | - Source maps support
|
121 | - Dynamic styles and themes support \***new**
|
122 | - CSS Preprocessing via Plugins \***new**
|
123 |
|
124 | ## How It Works
|
125 |
|
126 | The example above transpiles to the following:
|
127 |
|
128 | ```jsx
|
129 | import _JSXStyle from 'styled-jsx/style'
|
130 |
|
131 | export default () => (
|
132 | <div className='jsx-123'>
|
133 | <p className='jsx-123'>only this paragraph will get the style :)</p>
|
134 | <_JSXStyle styleId='123' css={`p.jsx-123 {color: red;}`} />
|
135 | </div>
|
136 | )
|
137 | ```
|
138 |
|
139 | ### Why It Works Like This
|
140 |
|
141 | Unique classnames give us style encapsulation and `_JSXStyle` is heavily optimized for:
|
142 |
|
143 | - Injecting styles upon render
|
144 | - Only injecting a certain component's style once (even if the component is included multiple times)
|
145 | - Removing unused styles
|
146 | - Keeping track of styles for server-side rendering
|
147 |
|
148 | ### Targeting The Root
|
149 |
|
150 | Notice that the outer `<div>` from the example above also gets a `jsx-123` classname. We do this so that
|
151 | you can target the "root" element, in the same manner that
|
152 | [`:host`](https://www.html5rocks.com/en/tutorials/webcomponents/shadowdom-201/#toc-style-host) works with Shadow DOM.
|
153 |
|
154 | If you want to target _only_ the host, we suggest you use a class:
|
155 |
|
156 | ```jsx
|
157 | export default () => (
|
158 | <div className="root">
|
159 | <style jsx>{`
|
160 | .root {
|
161 | color: green;
|
162 | }
|
163 | `}</style>
|
164 | </div>
|
165 | )
|
166 | ```
|
167 |
|
168 | ### Keeping CSS in separate files
|
169 |
|
170 | Styles can be defined in separate JavaScript modules by tagging with `css` any template literal that contain CSS.
|
171 |
|
172 | `css` must be imported from `styled-jsx/css`:
|
173 |
|
174 | ```js
|
175 | /* styles.js */
|
176 | import css from 'styled-jsx/css'
|
177 |
|
178 | export const button = css`button { color: hotpink; }`
|
179 | export default css`div { color: green; }`
|
180 | ```
|
181 |
|
182 | imported as regular strings:
|
183 |
|
184 | ```jsx
|
185 | import styles, { button } from './styles'
|
186 |
|
187 | export default () => (
|
188 | <div>
|
189 | <button>styled-jsx</button>
|
190 | <style jsx>{styles}</style>
|
191 | <style jsx>{button}</style>
|
192 | </div>
|
193 | )
|
194 | ```
|
195 |
|
196 | Styles are automatically scoped but you can also be consumed as [globals](#global-styles).
|
197 |
|
198 | N.B. Dynamic styles cannot be used in external styles.
|
199 |
|
200 | We also support CommonJS exports but you can only export one string per module:
|
201 |
|
202 | ```js
|
203 | module.exports = css`div { color: green; }`
|
204 |
|
205 | // the following won't work
|
206 | // module.exports = { styles: css`div { color: green; }` }
|
207 | ```
|
208 |
|
209 | ### Styles outside of components
|
210 |
|
211 | The `css` tag from `styled-jsx/css` can be also used to define styles in your components files but outside of the component itself. This might help with keeping `render` methods smaller.
|
212 |
|
213 | ```jsx
|
214 | import css from 'styled-jsx/css'
|
215 |
|
216 | export default () => (
|
217 | <div>
|
218 | <button>styled-jsx</button>
|
219 | <style jsx>{button}</style>
|
220 | </div>
|
221 | )
|
222 |
|
223 | const button = css`button { color: hotpink; }`
|
224 | ```
|
225 |
|
226 | Like in externals styles `css` doesn't work with dynamic styles. If you have dynamic parts you might want to place them inline inside of your component using a regular `<style jsx>` element.
|
227 |
|
228 | ### Global styles
|
229 |
|
230 | To skip scoping entirely, you can make the global-ness of your styles
|
231 | explicit by adding _global_.
|
232 |
|
233 | ```jsx
|
234 | export default () => (
|
235 | <div>
|
236 | <style jsx global>{`
|
237 | body {
|
238 | background: red
|
239 | }
|
240 | `}</style>
|
241 | </div>
|
242 | )
|
243 | ```
|
244 |
|
245 | The advantage of using this over `<style>` is twofold: no need
|
246 | to use `dangerouslySetInnerHTML` to avoid escaping issues with CSS
|
247 | and take advantage of `styled-jsx`'s de-duping system to avoid
|
248 | the global styles being inserted multiple times.
|
249 |
|
250 | ### One-off global selectors
|
251 |
|
252 | Sometimes it's useful to skip selectors scoping. In order to get a one-off global selector we support `:global()`, inspired by [css-modules](https://github.com/css-modules/css-modules).
|
253 |
|
254 | This is very useful in order to, for example, generate a *global class* that
|
255 | you can pass to 3rd-party components. For example, to style
|
256 | `react-select` which supports passing a custom class via `optionClassName`:
|
257 |
|
258 | ```jsx
|
259 | import Select from 'react-select'
|
260 | export default () => (
|
261 | <div>
|
262 | <Select optionClassName="react-select" />
|
263 |
|
264 | <style jsx>{`
|
265 | /* "div" will be prefixed, but ".react-select" won't */
|
266 |
|
267 | div :global(.react-select) {
|
268 | color: red
|
269 | }
|
270 | `}</style>
|
271 | </div>
|
272 | )
|
273 | ```
|
274 |
|
275 | ### Dynamic styles
|
276 |
|
277 | To make a component's visual representation customizable from the outside world there are three options.
|
278 |
|
279 | #### Via interpolated dynamic props
|
280 |
|
281 | Any value that comes from the component's `render` method scope is treated as dynamic. This makes it possible to use `props` and `state` for example.
|
282 |
|
283 | ```jsx
|
284 | const Button = (props) => (
|
285 | <button>
|
286 | { props.children }
|
287 | <style jsx>{`
|
288 | button {
|
289 | padding: ${ 'large' in props ? '50' : '20' }px;
|
290 | background: ${props.theme.background};
|
291 | color: #999;
|
292 | display: inline-block;
|
293 | font-size: 1em;
|
294 | }
|
295 | `}</style>
|
296 | </button>
|
297 | )
|
298 | ```
|
299 |
|
300 | New styles' injection is optimized to perform well at runtime.
|
301 |
|
302 | That said when your CSS is mostly static we recommend to split it up in static and dynamic styles and use two separate `style` tags so that, when changing, only the dynamic parts are recomputed/rendered.
|
303 |
|
304 | ```jsx
|
305 | const Button = (props) => (
|
306 | <button>
|
307 | { props.children }
|
308 | <style jsx>{`
|
309 | button {
|
310 | color: #999;
|
311 | display: inline-block;
|
312 | font-size: 2em;
|
313 | }
|
314 | `}</style>
|
315 | <style jsx>{`
|
316 | button {
|
317 | padding: ${ 'large' in props ? '50' : '20' }px;
|
318 | background: ${props.theme.background};
|
319 | }
|
320 | `}</style>
|
321 | </button>
|
322 | )
|
323 | ```
|
324 |
|
325 | #### Via `className` toggling
|
326 |
|
327 | The second option is to pass properties that toggle class names.
|
328 |
|
329 | ```jsx
|
330 | const Button = (props) => (
|
331 | <button className={ 'large' in props && 'large' }>
|
332 | { props.children }
|
333 | <style jsx>{`
|
334 | button {
|
335 | padding: 20px;
|
336 | background: #eee;
|
337 | color: #999
|
338 | }
|
339 | .large {
|
340 | padding: 50px
|
341 | }
|
342 | `}</style>
|
343 | </button>
|
344 | )
|
345 | ```
|
346 |
|
347 | Then you would use this component as either `<Button>Hi</Button>` or `<Button large>Big</Button>`.
|
348 |
|
349 | #### Via inline `style`
|
350 |
|
351 | \***best for animations**
|
352 |
|
353 | Imagine that you wanted to make the padding in the button above completely customizable. You can override the CSS you configure via inline-styles:
|
354 |
|
355 | ```jsx
|
356 | const Button = ({ padding, children }) => (
|
357 | <button style={{ padding }}>
|
358 | { children }
|
359 | <style jsx>{`
|
360 | button {
|
361 | padding: 20px;
|
362 | background: #eee;
|
363 | color: #999
|
364 | }
|
365 | `}</style>
|
366 | </button>
|
367 | )
|
368 | ```
|
369 |
|
370 | In this example, the padding defaults to the one set in `<style>` (`20`), but the user can pass a custom one via `<Button padding={30}>`.
|
371 |
|
372 | ### Constants
|
373 |
|
374 | It is possible to use constants like so:
|
375 |
|
376 | ```jsx
|
377 | import { colors, spacing } from '../theme'
|
378 | import { invertColor } from '../theme/utils'
|
379 |
|
380 | const Button = ({ children }) => (
|
381 | <button>
|
382 | { children }
|
383 | <style jsx>{`
|
384 | button {
|
385 | padding: ${ spacing.medium };
|
386 | background: ${ colors.primary };
|
387 | color: ${ invertColor(colors.primary) };
|
388 | }
|
389 | `}</style>
|
390 | </button>
|
391 | )
|
392 | ```
|
393 |
|
394 | Please keep in mind that constants defined outside of the component scope are treated as static styles.
|
395 |
|
396 | ## Server-Side Rendering
|
397 |
|
398 | ### `styled-jsx/server`
|
399 |
|
400 | The main export flushes your styles to an array of `React.Element`:
|
401 |
|
402 | ```jsx
|
403 | import React from 'react'
|
404 | import ReactDOM from 'react-dom/server'
|
405 | import flush from 'styled-jsx/server'
|
406 | import App from './app'
|
407 |
|
408 | export default (req, res) => {
|
409 | const app = ReactDOM.renderToString(<App />)
|
410 | const styles = flush()
|
411 | const html = ReactDOM.renderToStaticMarkup(<html>
|
412 | <head>{ styles }</head>
|
413 | <body>
|
414 | <div id="root" dangerouslySetInnerHTML={{__html: app}} />
|
415 | </body>
|
416 | </html>)
|
417 | res.end('<!doctype html>' + html)
|
418 | }
|
419 | ```
|
420 |
|
421 | We also expose `flushToHTML` to return generated HTML:
|
422 |
|
423 | ```jsx
|
424 | import React from 'react'
|
425 | import ReactDOM from 'react-dom/server'
|
426 | import { flushToHTML } from 'styled-jsx/server'
|
427 | import App from './app'
|
428 |
|
429 | export default (req, res) => {
|
430 | const app = ReactDOM.renderToString(<App />)
|
431 | const styles = flushToHTML()
|
432 | const html = `<!doctype html>
|
433 | <html>
|
434 | <head>${styles}</head>
|
435 | <body>
|
436 | <div id="root">${app}</div>
|
437 | </body>
|
438 | </html>`
|
439 | res.end(html)
|
440 | }
|
441 | ```
|
442 |
|
443 | It's **paramount** that you use one of these two functions so that
|
444 | the generated styles can be diffed when the client loads and
|
445 | duplicate styles are avoided.
|
446 |
|
447 | ## CSS Preprocessing via Plugins
|
448 |
|
449 | Styles can be preprocessed via plugins.
|
450 |
|
451 | Plugins are regular JavaScript modules that export a simple function with the following signature:
|
452 |
|
453 | ```js
|
454 | (css: string, options: Object) => string
|
455 | ```
|
456 |
|
457 | Basically they accept a CSS string in input, optionally modify it and finally return it.
|
458 |
|
459 | Plugins make it possible to use popular preprocessors like SASS, Less, Stylus, PostCSS or apply custom transformations to the styles at **compile time**.
|
460 |
|
461 | To register a plugin add an option `plugins` for `styled-jsx/babel` to your `.babelrc`. `plugins` must be an array of module names or *full* paths for local plugins.
|
462 |
|
463 | ```json
|
464 | {
|
465 | "plugins": [
|
466 | [
|
467 | "styled-jsx/babel",
|
468 | { "plugins": ["my-styled-jsx-plugin-package", "/full/path/to/local/plugin"] }
|
469 | ]
|
470 | ]
|
471 | }
|
472 | ```
|
473 |
|
474 | <details>
|
475 | <summary>Instructions to integrate with Next.js</summary>
|
476 | In order to register styled-jsx plugins in a Next.js app you need to create a custom .babelrc file:
|
477 |
|
478 | ```json
|
479 | {
|
480 | "presets": [
|
481 | [
|
482 | "next/babel",
|
483 | {
|
484 | "styled-jsx": {
|
485 | "plugins": [
|
486 | "styled-jsx-plugin-postcss"
|
487 | ]
|
488 | }
|
489 | }
|
490 | ]
|
491 | ]
|
492 | }
|
493 | ```
|
494 |
|
495 | This is a fairly new feature so make sure that you using a version of Next.js that supports passing options to `styled-jsx`.
|
496 | </details>
|
497 | <br>
|
498 |
|
499 | Plugins are applied in definition order left to right before styles are scoped.
|
500 |
|
501 | In order to resolve local plugins paths you can use NodeJS' [require.resolve](https://nodejs.org/api/globals.html#globals_require_resolve).
|
502 |
|
503 | N.B. when applying the plugins styled-jsx replaces template literals expressions with placeholders because otherwise CSS parsers would get invalid CSS E.g.
|
504 |
|
505 | ```css
|
506 | /* `ExprNumber` is a number */
|
507 | %%styled-jsx-placeholder-ExprNumber%%
|
508 | ```
|
509 |
|
510 | **Plugins won't transform expressions** (eg. dynamic styles).
|
511 |
|
512 | When publishing a plugin you may want to add the keywords: `styled-jsx` and `styled-jsx-plugin`.
|
513 | We also encourage you to use the following naming convention for your plugins:
|
514 |
|
515 | ```
|
516 | styled-jsx-plugin-<your-plugin-name>
|
517 | ```
|
518 |
|
519 | #### Plugin options
|
520 |
|
521 | Users can set plugin options by registering a plugin as an array that contains
|
522 | the plugin path and an options object.
|
523 |
|
524 | ```json
|
525 | {
|
526 | "plugins": [
|
527 | [
|
528 | "styled-jsx/babel",
|
529 | {
|
530 | "plugins": [
|
531 | ["my-styled-jsx-plugin-package", { "exampleOption": true }]
|
532 | ],
|
533 | "sourceMaps": true
|
534 | }
|
535 | ]
|
536 | ]
|
537 | }
|
538 | ```
|
539 |
|
540 | Each plugin receives a `options` object as second argument which contains
|
541 | the babel and user options:
|
542 |
|
543 | ```js
|
544 | (css, options) => { /* ... */ }
|
545 | ```
|
546 |
|
547 | The `options` object has the following shape:
|
548 |
|
549 | ```js
|
550 | {
|
551 | // user options go here
|
552 | // eg. exampleOption: true
|
553 |
|
554 | // babel options
|
555 | babel: {
|
556 | sourceMaps: boolean,
|
557 | vendorPrefixes: boolean,
|
558 | isGlobal: boolean,
|
559 | filename: ?string, // defined only when the filename option is passed to Babel, such as when using Babel CLI or Webpack
|
560 | location: { // the original location of the CSS block in the JavaScript file
|
561 | start: {
|
562 | line: number,
|
563 | column: number,
|
564 | },
|
565 | end: {
|
566 | line: number,
|
567 | column: number,
|
568 | }
|
569 | }
|
570 | }
|
571 | }
|
572 | ```
|
573 |
|
574 | #### Example plugins
|
575 |
|
576 | The following plugins are proof of concepts/sample:
|
577 |
|
578 | * [styled-jsx-plugin-sass](https://github.com/giuseppeg/styled-jsx-plugin-sass)
|
579 | * [styled-jsx-plugin-postcss](https://github.com/giuseppeg/styled-jsx-plugin-postcss)
|
580 | * [styled-jsx-plugin-stylelint](https://github.com/giuseppeg/styled-jsx-plugin-stylelint)
|
581 | * [styled-jsx-plugin-less](https://github.com/erasmo-marin/styled-jsx-plugin-less)
|
582 | * [styled-jsx-plugin-stylus](https://github.com/omardelarosa/styled-jsx-plugin-stylus)
|
583 |
|
584 | ## FAQ
|
585 |
|
586 | ### Warning: unknown `jsx` prop on <style> tag
|
587 |
|
588 | If you get this warning it means that your styles were not compiled by styled-jsx.
|
589 |
|
590 | Please take a look at your setup and make sure that everything is correct and that the styled-jsx transformation is ran by Babel.
|
591 |
|
592 | ### Can I return an array of components when using React 16?
|
593 |
|
594 | No, this feature is not supported. However we support React Fragments, which are available in React `16.2.0` and above.
|
595 |
|
596 | ```jsx
|
597 | const StyledImage = ({ src, alt = '' }) => (
|
598 | <React.Fragment>
|
599 | <img src={src} alt={alt} />
|
600 | <style jsx>{`img { max-width: 100% }`}</style>
|
601 | </React.Fragment>
|
602 | )
|
603 | ```
|
604 |
|
605 | ### Styling third parties / child components from the parent
|
606 |
|
607 | When the component accepts a `className` (or ad-hoc) prop that you can use to style those components then you can generate scoped styles locally in the parent component and resolve them to get a `className` and the actual scoped styles like so:
|
608 |
|
609 | ```jsx
|
610 | import Link from 'react-router-dom' // component to style
|
611 |
|
612 | // Generate a `scope` fragment and resolve it
|
613 | const scoped = resolveScopedStyles(
|
614 | <scope>
|
615 | <style jsx>{'.link { color: green }'}</style>
|
616 | </scope>
|
617 | )
|
618 |
|
619 | // Your component that uses Link
|
620 | export default ({ children }) => (
|
621 | <div>
|
622 | {children}
|
623 |
|
624 | {/* use the scoped className */}
|
625 | <Link to="/about" className={`link ${scoped.className}`}>
|
626 | About
|
627 | </Link>
|
628 |
|
629 | {/* apply the scoped styles */}
|
630 | {scoped.styles}
|
631 | </div>
|
632 | )
|
633 | ```
|
634 |
|
635 | `resolveScopedStyles` looks like this:
|
636 |
|
637 | ```jsx
|
638 | function resolveScopedStyles(scope) {
|
639 | return {
|
640 | className: scope.props.className,
|
641 | styles: scope.props.children
|
642 | }
|
643 | }
|
644 | ```
|
645 |
|
646 | When the component doesn't accept any `className` or doesn't expose any API to customize the component, then you only option is to use `:global()` styles:
|
647 |
|
648 | ```jsx
|
649 | export default () => (
|
650 | <div>
|
651 | <ExternalComponent />
|
652 |
|
653 | <style jsx>{`
|
654 | /* "div" will be prefixed, but ".nested-element" won't */
|
655 |
|
656 | div > :global(.nested-element) {
|
657 | color: red
|
658 | }
|
659 | `}</style>
|
660 | </div>
|
661 | )
|
662 | ```
|
663 |
|
664 | Please keep in mind that `:global()` styles will affect the entire subtree, so in many cases you may want to be careful and use the children (direct descendant) selector `>`.
|
665 |
|
666 | ## Syntax Highlighting
|
667 |
|
668 | When working with template literals a common drawback is missing syntax highlighting. The following editors currently have support for highlighting CSS inside `<style jsx>` elements.
|
669 |
|
670 | _If you have a solution for an editor not on the list_ __please [open a PR](https://github.com/zeit/styled-jsx/pull/new/master)__ _and let us now._
|
671 |
|
672 | ### Atom
|
673 |
|
674 | The [`language-babel`](https://github.com/gandm/language-babel) package for the [Atom editor](https://atom.io/) has an option to [extend the grammar for JavaScript tagged template literals](https://github.com/gandm/language-babel#javascript-tagged-template-literal-grammar-extensions).
|
675 |
|
676 | After [installing the package](https://github.com/gandm/language-babel#installation) add the code below to the appropriate settings entry. In a few moments you should be blessed with proper CSS syntax highlighting. ([source](https://github.com/gandm/language-babel/issues/324))
|
677 |
|
678 | ```
|
679 | "(?<=<style jsx>{)|(?<=<style jsx global>{)":source.css.styled
|
680 | ```
|
681 |
|
682 | ![babel-language settings entry](https://cloud.githubusercontent.com/assets/2313237/22627258/6c97cb68-ebb7-11e6-82e1-60205f8b31e7.png)
|
683 |
|
684 | ### Webstorm/Idea
|
685 |
|
686 | The IDE let you inject any language in place with _Inject language or reference_ in an _Intention Actions_ (default _alt+enter_).
|
687 | Simply perform the action in the string template and select CSS.
|
688 | You get full CSS highlighting and autocompletion and it will last until you close the IDE.
|
689 |
|
690 | Additionally you can use language injection comments to enable all the IDE language features indefinitely using the language comment style:
|
691 |
|
692 | ```jsx
|
693 | import { colors, spacing } from '../theme'
|
694 | import { invertColor } from '../theme/utils'
|
695 |
|
696 | const Button = ({ children }) => (
|
697 | <button>
|
698 | { children }
|
699 |
|
700 | { /*language=CSS*/ }
|
701 | <style jsx>{`
|
702 | button {
|
703 | padding: ${ spacing.medium };
|
704 | background: ${ colors.primary };
|
705 | color: ${ invertColor(colors.primary) };
|
706 | }
|
707 | `}</style>
|
708 | </button>
|
709 | )
|
710 | ```
|
711 |
|
712 | ### Emmet
|
713 |
|
714 | If you're using Emmet you can add the following snippet to `~/emmet/snippets-styledjsx.json` This will allow you to expand `style-jsx` to a styled-jsx block.
|
715 |
|
716 | ```json
|
717 | {
|
718 | "html": {
|
719 | "snippets": {
|
720 | "style-jsx": "<style jsx>{`\n\t$1\n`}</style>"
|
721 | }
|
722 | }
|
723 | }
|
724 | ```
|
725 |
|
726 | ### Syntax Highlighting [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=blanu.vscode-styled-jsx)
|
727 | Launch VS Code Quick Open (⌘+P), paste the following command, and press enter.
|
728 | ```
|
729 | ext install vscode-styled-jsx
|
730 | ```
|
731 |
|
732 | ### Autocomplete [Visual Studio Code Extension](https://marketplace.visualstudio.com/items?itemName=AndrewRazumovsky.vscode-styled-jsx-languageserver)
|
733 | Launch VS Code Quick Open (⌘+P), paste the following command, and press enter.
|
734 | ```
|
735 | ext install vscode-styled-jsx-languageserver
|
736 | ```
|
737 |
|
738 | ### Vim
|
739 |
|
740 | Install [vim-styled-jsx](https://github.com/alampros/vim-styled-jsx) with your plugin manager of choice.
|
741 |
|
742 | ## ESLint
|
743 | If you're using `eslint-plugin-import`, the `css` import will generate errors, being that it's a "magic" import (not listed in package.json). To avoid these, simply add the following line to your eslint configuration:
|
744 |
|
745 | ```
|
746 | "settings": {"import/core-modules": ["styled-jsx/css"] }
|
747 | ```
|
748 |
|
749 | ## Credits
|
750 |
|
751 | - **Pedram Emrouznejad** ([rijs](https://github.com/rijs/fullstack)) suggested attribute selectors over my initial class prefixing idea.
|
752 | - **Sunil Pai** ([glamor](https://github.com/threepointone/glamor)) inspired the use of `murmurhash2` (minimal and fast hashing) and an efficient style injection logic.
|
753 | - **Sultan Tarimo** built [stylis.js](https://github.com/thysultan), a super fast and tiny CSS parser and compiler.
|
754 | - **Max Stoiber** ([styled-components](https://github.com/styled-components)) proved the value of retaining the familiarity of CSS syntax and pointed me to the very efficient [stylis](https://github.com/thysultan/stylis.js) compiler (which we forked to very efficiently append attribute selectors to the user's css)
|
755 | - **Yehuda Katz** ([ember](https://github.com/emberjs)) convinced me on Twitter to transpile CSS as an alternative to CSS-in-JS.
|
756 | - **Evan You** ([vuejs](https://github.com/vuejs)) discussed his Vue.js CSS transformation with me.
|
757 | - **Henry Zhu** ([babel](https://github.com/babel)) helpfully pointed me to some important areas of the babel plugin API.
|
758 |
|
759 | ## Authors
|
760 |
|
761 | - Guillermo Rauch ([@rauchg](https://twitter.com/rauchg)) - [▲ZEIT](https://zeit.co)
|
762 | - Naoyuki Kanezawa ([@nkzawa](https://twitter.com/nkzawa)) - [▲ZEIT](https://zeit.co)
|
763 | - Giuseppe Gurgone ([@giuseppegurgone](https://twitter.com/giuseppegurgone))
|