├── .gitignore
├── LICENSE
├── README.md
├── images
├── css-in-js.png
└── emotion-source-maps.gif
├── package.json
├── talks.md
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://vshymanskyy.github.io/StandWithUkraine)
2 |
3 | # CSS-in-JS 101 [](https://twitter.com/stereobooster)
4 |
5 | 
6 |
7 |
8 |
9 | - [What is CSS-in-JS?](#what-is-css-in-js)
10 | - [Inline styles](#inline-styles)
11 | * [Pros](#pros)
12 | * [Cons](#cons)
13 | * [Inline styles vs CSS-in-JS](#inline-styles-vs-css-in-js)
14 | - [Style tag](#style-tag)
15 | * [Pros](#pros-1)
16 | * [Cons](#cons-1)
17 | - [CSS Modules](#css-modules)
18 | * [Pros](#pros-2)
19 | * [Cons](#cons-2)
20 | * [Dead Code Elimination, Critical CSS](#dead-code-elimination-critical-css)
21 | - [Global Name Space, Globally Unique Identifier](#global-name-space-globally-unique-identifier)
22 | - [Dependencies](#dependencies)
23 | - [Minification](#minification)
24 | * [Traditional CSS minification](#traditional-css-minification)
25 | * [Minification of class name](#minification-of-class-name)
26 | * [Dead Code Elimination](#dead-code-elimination)
27 | * [Critical CSS](#critical-css)
28 | * [Automatic Atomic CSS](#automatic-atomic-css)
29 | - [Sharing Constants, variables in CSS](#sharing-constants-variables-in-css)
30 | * [Sharing variables inside CSS](#sharing-variables-inside-css)
31 | * [Sharing variables in CSS and exposing it to JS](#sharing-variables-in-css-and-exposing-it-to-js)
32 | * [Passing variable from JS to CSS](#passing-variable-from-js-to-css)
33 | - [Non-deterministic Resolution](#non-deterministic-resolution)
34 | - [Isolation](#isolation)
35 | - [Theming](#theming)
36 | * [Overriding styles](#overriding-styles)
37 | * [Overriding theme variables](#overriding-theme-variables)
38 | - [SSR, Server-Side Rendering](#ssr-server-side-rendering)
39 | * [HTML SSR](#html-ssr)
40 | * [CSS SSR](#css-ssr)
41 | - [Zero runtime dependency](#zero-runtime-dependency)
42 | - [CSS-in-JS implementation specific features](#css-in-js-implementation-specific-features)
43 | * [Non-DOM targets](#non-dom-targets)
44 | * [CSS as object (object literal)](#css-as-object-object-literal)
45 | * [CSS as template literal](#css-as-template-literal)
46 | * [Framework agnostic](#framework-agnostic)
47 | * [Build step](#build-step)
48 | * [Dynamic](#dynamic)
49 | * [Generate components based on CSS](#generate-components-based-on-css)
50 | * [Developer tools integration](#developer-tools-integration)
51 | - [Progressive enhancement, graceful degradation](#progressive-enhancement-graceful-degradation)
52 | - [Uncovered subjects](#uncovered-subjects)
53 | * [Security](#security)
54 | * [Async components](#async-components)
55 | * [CSS-in-JS and Async components](#css-in-js-and-async-components)
56 | * [Atomic CSS](#atomic-css)
57 | * [Animations](#animations)
58 |
59 |
60 |
61 | ## What is CSS-in-JS?
62 |
63 | CSS-in-JS is an umbrella term for technologies which help you define styles in JS in more component-approach-way. The idea was introduced by `@vjeux` in 2014. Initially, it was described as inline styles, but since then battlefield changed a lot. There are about 50 different solutions in this area.
64 |
65 | #### References
66 |
67 | - [@vjeux, 2014][@vjeux, 2014]
68 | - [Big list of CSS-in-JS solutions](http://michelebertoli.github.io/css-in-js/)
69 | - [Comparison of CSS-in-JS by styled-components](https://github.com/styled-components/comparison/pull/44)
70 | - [Yet another comparison](http://seifi.org/css/sxsw-slides-css-in-react-the-good-the-bad-and-the-ugly.html)
71 |
72 | ## Inline styles
73 |
74 | This is built in feature of React. You can pass styles as an object to the component and it will be converted to the string and attached as style attribute to the element.
75 |
76 | ### Pros
77 |
78 | - No `global namespace`
79 | - `Full isolation`
80 | - No `non-deterministic resolution`
81 | - Clear `dependencies`
82 | - `Dead code elimination`
83 | - `Variables, Passing variable from JS to CSS`
84 |
85 | ### Cons
86 |
87 | - Code duplication in case of SSR.
88 | - Additional costs in JS payload. Remember that styles which are embedded in JS are not for free. It is not only about download time, it is also about parsing and compiling. See [this detailed explanation by Addy Osmani, why JS is expensive](https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e)
89 | - No media queries (`@media`)
90 | - No CSS animations (`@keyframes`)
91 | - No pseudo classes (`:hover`)
92 | - No web fonts (`@font`)
93 | - No autoprefixer (well there is [inline-style-prefixer](https://github.com/rofrischmann/inline-style-prefixer))
94 |
95 | #### Example
96 |
97 | **TODO**: verify
98 |
99 | JSX:
100 |
101 | ```jsx
102 | hundred_length_array
103 | .map(x =>
)
104 | ```
105 |
106 | Generated HTML:
107 |
108 | ```html
109 |
110 | ...(98 times)
111 |
112 | ```
113 |
114 | ### Inline styles vs CSS-in-JS
115 |
116 | `@mxstbr` differentiate `Inline styles` and `CSS-in-JS`. By `Inline styles` he means React built-in support for style attribute and by `CSS-in-JS` he means a solution which generates CSS and injects it via style tag.
117 |
118 | On the other hand, `CSS-in-JS` is the term coined by `@vjeux` in 2014 and he meant `Inline styles`. `Inline styles` is not React-only feature. There is, for example, Radium which also uses `inline styles`.
119 |
120 | So I would suggest to use `CSS-in-JS` as an umbrella term and specify implementation:
121 | - inline styles
122 | - style tag. Also can be referred as "style element" or "real CSS"
123 | - mixed (like Radium)
124 |
125 | #### References
126 |
127 | - [@mxstbr, 2016][@mxstbr, 2016]
128 |
129 | ## Style tag
130 |
131 | This approach is alternative to `Inline styles`. Instead of attaching styles as property to the element you are inserting real CSS in style tag and append style tag to the document.
132 |
133 | Pros and cons can vary from implementation to implementation. But basically, it looks like this:
134 |
135 | ### Pros
136 |
137 | - (Almost) No `global namespace`
138 | - (Almost) `Full isolation`
139 | - (Almost) No `non-deterministic resolution`
140 | - Clear `dependencies`
141 | - `Dead code elimination`
142 | - `Variables` (depends on implementation)
143 | - No code duplication in case of SSR
144 | - Additional costs in JS payload (depends on implementation)
145 | - Media queries (`@media`)
146 | - CSS animations (`@keyframes`)
147 | - Pseudo-classes (`:hover`)
148 | - Web fonts (`@font`)
149 |
150 | ### Cons
151 |
152 | Cons depend on implementation.
153 |
154 | #### Example
155 |
156 | [from this blog post](https://medium.learnreact.com/the-style-tag-and-react-24d6dd3ca974):
157 |
158 | ```js
159 | const MyStyledComponent = props =>
160 |
175 | ```
176 |
177 | ## CSS Modules
178 |
179 | A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. All URLs (url(...)) and @imports are in module request format (./xxx and ../xxx means relative, xxx and xxx/yyy means in modules folder, i. e. in node_modules).
180 |
181 | ### Pros
182 |
183 | - (Almost) No `global namespace`
184 | - (Almost) `Full isolation`
185 | - (Almost) No `non-deterministic resolution`
186 | - Clear `dependencies`
187 | - (Almost) `Dead code elimination`
188 | - `Variables, Sharing variables in CSS and exposing it to JS`
189 | - No Code duplication in case of SSR
190 | - No Additional costs in JS payload.
191 | - Media queries (`@media`)
192 | - CSS animations (`@keyframes`)
193 | - Pseudo-classes (`:hover`)
194 | - Web fonts (`@font`)
195 | - Autoprefixer
196 |
197 | ### Cons
198 |
199 | See all points with "(Almost)"
200 |
201 | ### Dead Code Elimination, Critical CSS
202 |
203 | Strictly speaking, there are no official solutions to those problems in `CSS Modules`, but there is some work in this direction. Correct me if I'm wrong if there is one, why isn't it promoted?
204 |
205 | - [Comment by @sokra on critical CSS](https://github.com/webpack-contrib/style-loader/pull/159#issuecomment-286729044)
206 | - [isomorphic-style-loader](https://github.com/kriasoft/isomorphic-style-loader)
207 | - [Support Tree shaking of CSS ](https://github.com/webpack-contrib/css-loader/issues/506)
208 | - [Atomic CSS a la styletron](https://github.com/deamme/styletron-loader)
209 | - [CSSO scopes](https://github.com/css/csso#scopes)
210 |
211 | #### References
212 |
213 | - [css-modules](https://github.com/css-modules/css-modules)
214 | - [@markdalgleish, 2015][@markdalgleish, 2015]
215 |
216 | ## Global Name Space, Globally Unique Identifier
217 |
218 | All declarations in CSS are global, which is bad because you never know what part of application change in global scope will affect.
219 |
220 | #### Possible solutions
221 |
222 | - Attach styles to each element (`Inline styles`)
223 | - Use Globally Unique Identifiers for classes (`CSS modules`)
224 | - Use naming conventions (BEM and others)
225 |
226 | #### References
227 |
228 | - [@vjeux, 2014][@vjeux, 2014]
229 |
230 | ## Dependencies
231 |
232 | Ability to programmatically resolve dependency between component (JS and HTML) and styles, to decrease error of forgetting to provide appropriate styles, to decrease fear of renaming CSS classes or moving them between files.
233 |
234 | #### Possible solutions
235 |
236 | - bundle styles with-in component (CSS-in-JS)
237 | - `import styles from "styles.css"` (CSS modules)
238 |
239 | #### Related
240 | - `Dead Code Elimination`
241 |
242 | ## Minification
243 |
244 | There is more than one aspect of minification. Let's explore:
245 |
246 | ### Traditional CSS minification
247 |
248 | This is the simplest approach - remove whitespace, minify color name, remove unnecessary quotes, collapse CSS rules etc. See big list of minifiers [here](https://goalsmashers.github.io/css-minification-benchmark/)
249 |
250 | ### Minification of class name
251 |
252 | In CSS modules and CSS-in-JS you do not use class names directly, instead, you use JS variables, so class names can be easily mangled.
253 |
254 | Note: This type of minification is not possible for traditional CSS.
255 |
256 | #### Example
257 |
258 | ```js
259 | import styles from "styles.css";
260 |
261 |
262 | ```
263 |
264 | `styles` compiles to `{ example: "hASh"}`
265 |
266 | ### Dead Code Elimination
267 |
268 | Because there is no connection between JS/HTML and CSS, you cannot be sure if it is safe to remove some parts of CSS or not. If it is stale or not? If it is used somewhere or not?
269 |
270 | `CSS-in-JS` solves this problem because of a link between JS/HTML and CSS is known, so it is easy to track if this CSS rule required or not.
271 |
272 | #### Related
273 | - `Dependencies`
274 | - `Critical CSS`
275 |
276 | ##### References
277 |
278 | - [@vjeux, 2014][@vjeux, 2014]
279 |
280 | ### Critical CSS
281 |
282 | The ability of a system to extract and inline styles in head required for current page viewed by the user not more nor less.
283 |
284 | Note: this is slightly different from the definition by `@addyosmani`, [which defines critical as above-the-fold](https://github.com/addyosmani/critical).
285 |
286 | ##### Example
287 |
288 | [aphrodite](https://github.com/Khan/aphrodite):
289 |
290 | ```js
291 | import { StyleSheet, css } from 'aphrodite'
292 |
293 | const styles = StyleSheet.create({
294 | heading: { color: 'blue' }
295 | })
296 |
297 | const Heading = ({ children }) => (
298 |
299 | { children }
300 |
301 | )
302 | ```
303 |
304 | ```js
305 | import { StyleSheetServer } from 'aphrodite'
306 |
307 | const { html, css } = StyleSheetServer.renderStatic(
308 | () => ReactDOMServer.renderToString()
309 | )
310 | ```
311 |
312 | #### Related
313 |
314 | - `Dependencies`
315 | - `Dead Code Elimination`
316 | - `SSR`
317 |
318 | ##### References
319 |
320 | - [@markdalgleish, 2017][@markdalgleish, 2017]
321 |
322 | ### Automatic Atomic CSS
323 |
324 | In CSS modules and CSS-in-JS you do not use class names directly, instead, you use JS variables, so class names can be easily mangled. The same as in "Minification of class name". But we can go further - generate smaller classes and reuse them to achieve smaller CSS
325 |
326 | Note: This type of minification is not possible for traditional CSS.
327 |
328 | #### Example
329 |
330 | [styletron](https://github.com/rtsao/styletron)
331 |
332 | ```js
333 | import {injectStyle} from 'styletron-utils';
334 | injectStyle(styletron, {
335 | color: 'red',
336 | display: 'inline-block'
337 | });
338 | // → 'a d'
339 | injectStyle(styletron, {
340 | color: 'red',
341 | fontSize: '1.6em'
342 | });
343 | // → 'a e'
344 | ```
345 |
346 | #### Related
347 |
348 | - [Atomic CSS](#atomic-css)
349 |
350 | ##### References
351 |
352 | - [@markdalgleish, 2017][@markdalgleish, 2017]
353 |
354 | ## Sharing Constants, variables in CSS
355 |
356 | There are different approaches.
357 |
358 | ### Sharing variables inside CSS
359 |
360 | - [CSS variables](https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_variables)
361 | - [Can I use css variables](https://caniuse.com/#feat=css-variables)
362 | - CSS variables in preprocessors, like PostCSS, SASS etc.
363 |
364 | ### Sharing variables in CSS and exposing it to JS
365 |
366 | This is mainly a feature of `CSS modules` with variables.
367 |
368 | #### Example
369 |
370 | [postcss-icss-values](https://github.com/css-modules/postcss-icss-values)
371 |
372 | ```css
373 | /* colors.css */
374 | @value primary: #BF4040;
375 | ```
376 |
377 | Sharing variables in CSS:
378 | ```css
379 | @value primary from './colors.css';
380 |
381 | .panel {
382 | background: primary;
383 | }
384 | ```
385 |
386 | Exposing it to JS:
387 |
388 | ```js
389 | import { primary } from './colors.css';
390 | // will have similar effect
391 | console.log(primary); // -> #BF4040
392 | ```
393 |
394 | ### Passing variable from JS to CSS
395 |
396 | This is only possible with `CSS-in-JS`. This approach gives maximum flexibility and dynamics.
397 |
398 | #### Example
399 |
400 | [styling](https://github.com/andreypopp/styling)
401 |
402 | ```js
403 | import styling from 'styling'
404 | import {baseColor} from './theme'
405 |
406 | export let button = styling({
407 | backgroundColor: baseColor
408 | })
409 | ```
410 |
411 | #### Related
412 |
413 | - `Overriding theme variables`
414 |
415 | ## Non-deterministic Resolution
416 |
417 | Resolution depends on the order of declarations in stylesheets (if declarations have the same specificity).
418 |
419 | ##### References
420 |
421 | - [@vjeux, 2014][@vjeux, 2014]
422 |
423 | ## Isolation
424 |
425 | Because of CSS cascading nature and Global Name Space, there is no way to isolate things. Any other part code can use more specificity or use `!important` to override your "local" styles and it is hard to prevent this situation
426 |
427 | Strictly speaking, only inline styles gives full isolation. Every other solution gives just a bit more isolation over pure CSS, because of solving Global Name Space problem.
428 |
429 | ##### References
430 |
431 | - [@vjeux, 2014][@vjeux, 2014]
432 |
433 |
Two CSS properties walk into a bar.
A barstool in a completely different bar falls over.
— Thomas "Kick Nazis out, @jack" Fuchs (@thomasfuchs) July 28, 2014
434 |
435 | ## Theming
436 |
437 | The idea is to be able to change the look of existing components without the need to change actual code.
438 |
439 | ### Overriding styles
440 |
441 | This way you can override styles based on "class names" (keys of objects in case of inline styles).
442 |
443 | #### Example
444 |
445 | [react-themeable](https://github.com/markdalgleish/react-themeable)
446 |
447 | With `CSS modules`:
448 |
449 | ```js
450 | import theme from './MyComponentTheme.css';
451 |
452 | ```
453 |
454 | Same with inline styles:
455 |
456 | ```js
457 | const theme = {
458 | foo: {
459 | 'color': 'red'
460 | },
461 | bar: {
462 | 'color': 'blue'
463 | }
464 | };
465 |
466 | ```
467 |
468 | ### Overriding theme variables
469 |
470 | This way you can override styles based on variables passed to the theme. The theme basically works like a function - accepts variables as input and produce styles as a result.
471 |
472 | #### Related
473 | - `Variables, Passing variable from JS to CSS`
474 |
475 | ## SSR, Server-Side Rendering
476 |
477 | ### HTML SSR
478 | Make sure that `CSS-in-JS` solution doesn't brake default React isomorphism e.g. you are able to generate HTML on the server, but not necessary CSS.
479 |
480 | ### CSS SSR
481 | Be able to prerender CSS on the server the same way as HTML can be prerendered for React.
482 |
483 | #### Example
484 |
485 | [aphrodite](https://github.com/Khan/aphrodite):
486 |
487 | ```js
488 | import { StyleSheet, css } from 'aphrodite'
489 |
490 | const styles = StyleSheet.create({
491 | heading: { color: 'blue' }
492 | })
493 |
494 | const Heading = ({ children }) => (
495 |
496 | { children }
497 |
498 | )
499 | ```
500 |
501 | ```js
502 | import { StyleSheetServer } from 'aphrodite'
503 |
504 | const { html, css } = StyleSheetServer.renderStatic(
505 | () => ReactDOMServer.renderToString()
506 | )
507 | ```
508 |
509 | **TODO**: add example with `Inline Styles`
510 |
511 | #### Related
512 | - `Critical CSS`
513 |
514 | ## Zero runtime dependency
515 |
516 | Almost all `CSS-in-JS` solutions have runtime dependency e.g. library required to generate styles at runtime and CSS encoded as JS.
517 |
518 | Some solutions do not have this issue, they basically vanished after build step. Examples: `CSS modules`, linaria.
519 |
520 | #### Example
521 |
522 | [linaria](https://github.com/callstack/linaria)
523 |
524 | ```js
525 | import React from 'react';
526 | import { css, styles } from 'linaria';
527 |
528 | const title = css`
529 | text-transform: uppercase;
530 | `;
531 |
532 | export function App() {
533 | return ;
534 | }
535 | ```
536 |
537 | Transpiled to:
538 |
539 | ```css
540 | .title__jt5ry4 {
541 | text-transform: uppercase;
542 | }
543 | ```
544 |
545 | ```js
546 | import React from 'react';
547 | import { styles } from 'linaria/build/index.runtime';
548 |
549 | const title = 'title__jt5ry4';
550 |
551 | export function App() {
552 | return ;
553 | }
554 | ```
555 |
556 | ## CSS-in-JS implementation specific features
557 |
558 | ### Non-DOM targets
559 |
560 | React can target different platforms, not just DOM. It would be nice to have `CSS-in-JS` solution which supports different platforms too. For example: [React Native](https://facebook.github.io/react-native/), [Sketch](https://github.com/airbnb/react-sketchapp).
561 |
562 | ### CSS as object (object literal)
563 |
564 | ```js
565 | const color = "red"
566 | const style = {
567 | color: 'red',
568 | }
569 | ```
570 |
571 | ### CSS as template literal
572 |
573 | ```js
574 | const color = "red"
575 | const style = `
576 | color: ${color};
577 | `
578 | ```
579 |
580 | ### Framework agnostic
581 |
582 | Does it depend on React or not?
583 |
584 | ### Build step
585 |
586 | If build step required or not?
587 |
588 | #### Related
589 |
590 | - `SSR`
591 | - `Progressive enhancement`
592 | - `Dynamic`
593 |
594 | ### Dynamic
595 |
596 | If you can pass values to CSS at runtime.
597 |
598 | Note: it is not the same as `Variables, Passing variable from JS to CSS`, for example in [linaria](https://github.com/callstack/linaria) you can pass variables from JS to CSS, but only at build time.
599 |
600 | Note 2: cannot stop myself from drawing analogy between static and dynamic type systems.
601 |
602 | #### Related
603 |
604 | - `Build step`
605 | - `Variables, Passing variable from JS to CSS`
606 |
607 | ### Generate components based on CSS
608 |
609 | If your component has pretty simple structure and you care more about how it looks instead of markup (which most likely will be `div` anyway). You can go straight to write CSS and library will generate components for you.
610 |
611 | #### Examples
612 |
613 | [decss](https://github.com/kossnocorp/decss)
614 |
615 | ```js
616 | import React from 'react'
617 | import { Button } from './style.css'
618 |
619 |
622 | ```
623 |
624 | [styled-components](https://github.com/styled-components/styled-components)
625 |
626 | ```js
627 | import React from 'react'
628 | import styled from 'styled'
629 |
630 | const Button = styled.button`
631 | background-color: red;
632 | `;
633 |
634 |
637 | ```
638 |
639 | ### Developer tools integration
640 |
641 | If there are special perks for developer tools?
642 |
643 | #### Example
644 |
645 | [emotion](https://emotion.sh/) supports source maps for styles authored in javascript
646 |
647 | [GIF of source maps in action](images/emotion-source-maps.gif)
648 |
649 | ## Progressive enhancement, graceful degradation
650 |
651 | If you do not know what is it read this [article](https://www.shopify.com/partners/blog/what-is-progressive-enhancement-and-why-should-you-care).
652 |
653 | In the context of `CSS-in-JS` it boils down to one question - will your website be styled with disabled JS.
654 |
655 | The first requirement would be to have some HTML rendered on the server (SSR or [snapshoting](https://github.com/stereobooster/react-snap)). After this you have two options:
656 |
657 | - prebuild CSS e.g. `Build step` required
658 | - rendered CSS e.g. `CSS SSR` required
659 |
660 | #### Related
661 |
662 | - `SSR`
663 | - `Build step`
664 |
665 | ## Uncovered subjects
666 |
667 | ### Security
668 |
669 | See [this post](https://reactarmory.com/answers/how-can-i-use-css-in-js-securely)
670 |
671 | ### Async components
672 |
673 | Also known as `code splitting`, `dynamic import`
674 |
675 | Async component is a technique (typically implemented as a higher order component) for loading components with `dynamic import`. There are a lot of solutions in this field here are some examples:
676 |
677 | - [`loadable-components`](https://github.com/smooth-code/loadable-components)
678 | - [`react-loadable`](https://github.com/thejameskyle/react-loadable)
679 | - [`react-async-component`](https://github.com/ctrlplusb/react-async-component)
680 | - [`react-code-splitting`](https://github.com/didierfranc/react-code-splitting)
681 |
682 | #### References
683 |
684 | - [Dynamic import](https://github.com/tc39/proposal-dynamic-import) is the TC39 proposal.
685 |
686 | > Webpack has a feature to split your codebase into “chunks” which are loaded on demand. Some other bundlers call them “layers”, “rollups”, or “fragments”. This feature is called “code splitting”.
687 | >
688 | > — [Code splitting](https://webpack.github.io/docs/code-splitting.html)
689 |
690 | ### CSS-in-JS and Async components
691 |
692 | This works for most `CSS-in-JS` solutions because CSS is bundled inside JS. This is a more complicated task for CSS modules. See: [Guide To JavaScript Async Components](https://github.com/stereobooster/guide-to-async-components).
693 |
694 | ### Atomic CSS
695 |
696 | Also known as `immutable`, `functional`, `utility-class`.
697 |
698 | Idea boils down to use one property per class, so you create required look by composing more than one class. Because each class contains only one property, you do not override those properties and this can be interpreted as immutability.
699 |
700 | Do not confuse with [Atomic CSS](https://acss.io/) framework.
701 |
702 | #### References
703 |
704 | - [Functional CSS - The Good, The Bad, and Some Protips for React.js Users](https://github.com/chibicode/react-functional-css-protips#sunglasses-act-i-what-is-functional-css-and-why-would-i-want-to-use-it-sunglasses)
705 | - [immutable-css](https://github.com/johnotander/immutable-css)
706 |
707 | ### Animations
708 |
709 | #### Sequential
710 |
711 | Basically CSS3 animations. Pros: can be GPU accelerated.
712 |
713 | #### Interruptible
714 |
715 | Also known as `interactive`.
716 |
717 | Basically JS animations. Pros: can be interrupted.
718 |
719 | #### References
720 |
721 | - [Building Interruptible and Responsive Interactions](https://developer.apple.com/videos/play/wwdc2014/236/)
722 |
723 | ---
724 |
725 | [@vjeux, 2014]: http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html
726 | [@markdalgleish, 2015]: https://www.youtube.com/watch?v=zR1lOuyQEt8
727 | [@mxstbr, 2016]: https://www.youtube.com/watch?v=19gqsBc_Cx0
728 | [@markdalgleish, 2017]: https://www.youtube.com/watch?v=X_uTCnaRe94
729 |
--------------------------------------------------------------------------------
/images/css-in-js.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stereobooster/css-in-js-101/e7e50cf29488edaeb4577840d3104cf702428aae/images/css-in-js.png
--------------------------------------------------------------------------------
/images/emotion-source-maps.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/stereobooster/css-in-js-101/e7e50cf29488edaeb4577840d3104cf702428aae/images/emotion-source-maps.gif
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "css-in-js-101",
3 | "version": "1.0.0",
4 | "main": "index.js",
5 | "repository": "https://github.com/stereobooster/css-in-js-101.git",
6 | "author": "stereobooster ",
7 | "license": "MIT",
8 | "dependencies": {},
9 | "devDependencies": {
10 | "markdown-toc": "^1.2.0"
11 | },
12 | "scripts": {
13 | "toc": "yarn run markdown-toc -i --maxdepth 3 README.md"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/talks.md:
--------------------------------------------------------------------------------
1 | # CSS in JS: talks
2 |
3 | Disclaimer: information on this page can be a bit outdated. See [Readme](README.md) for latest vision.
4 |
5 | ## CSS in JS by Christopher Chedeau (@vjeux), 2014
6 |
7 | [presentation](https://speakerdeck.com/vjeux/react-css-in-js), [video](http://blog.vjeux.com/2014/javascript/react-css-in-js-nationjs.html)
8 |
9 | ### 1. Global Name Space
10 |
11 | All declarations in CSS are global.
12 |
13 | **Example**: you declared `.button` in `a.css` other developer declared `.button` in `b.css`. You both have no idea you used the same name until you will get a bug.
14 |
15 | **CSS solution**: naming convention, like BEM.
16 |
17 | ### 2. Dependencies
18 |
19 | No connection between HTML/JS and CSS.
20 |
21 | **Example**: you used ``, but forgot to load css file where it is declared.
22 |
23 | **CSS solution**: webpack's `require("a.css")` (kind of).
24 |
25 | ### 3. Dead Code Elimination
26 |
27 | Other consequences of "no connection between HTML/JS and CSS".
28 |
29 | **Example**: in your code, you use ``, but in styles, you loaded much more classes and/or keyframes
30 |
31 | **CSS solution**: you can use something like critical, but it is hard.
32 |
33 | ### 4. Minification
34 |
35 | @vjeux talks about minification of class names. Obviously, there are a lot of general [CSS minifiers](https://goalsmashers.github.io/css-minification-benchmark/), but none of those can minify class names.
36 |
37 | **Note**: in the end, @vjeux suggests to use inline styles, so there are no class names anymore, and this point doesn't make sense `¯\_(ツ)_/¯`.
38 |
39 | **CSS solution**: none
40 |
41 | ### 5. Sharing Constants
42 |
43 | The point is that you can share variables between CSS in JS.
44 |
45 | **Example**: breakpoints or duration of animations.
46 |
47 | **CSS solution**: closest options are SASS, CSS variables, CSS preprocessor.
48 |
49 | ### 6. Non-deterministic Resolution
50 |
51 | Resolution depends on the order of declarations in stylesheets (if declarations have the same specificity).
52 |
53 | **Example**: you declared `.button` in `a.css` other developer declared `.button` in `b.css`. Depending on order of inclusion of files `.button` can be resolved to `a.css` or to `b.css`.
54 |
55 | **CSS solution**: increase specificity (which will increase fragility and decrease portability).
56 |
57 | ### 7. Isolation
58 |
59 | Because of CSS cascading nature and Global Name Space, there is no way to isolate things.
60 |
61 | **Example**: you declared class `.button`, but other developer declared CSS for `div`.
62 |
63 |
Two CSS properties walk into a bar.
A barstool in a completely different bar falls over.
— Thomas "Kick Nazis out, @jack" Fuchs (@thomasfuchs) July 28, 2014
64 |
65 | ### Prposed solution: inline styles
66 |
67 | React:
68 |
69 | ```js
70 |
71 | ```
72 |
73 | Generated HTML:
74 |
75 | ```html
76 |
77 | ```
78 |
79 | **Downsides**:
80 | 1. Code duplication in case of SSR - imagine you have inline style for a repetitive element.
81 | 2. Additional costs in JS payload. Remember that styles which are embedded in JS are not for free. It is not only about download time, it is also about parsing and compiling. See [this detailed explanation by Addy Osmani, why JS is expensive](https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e)
82 | 3. No media queries
83 | 4. No CSS animations
84 | 5. No pseudo classes
85 | 6. No autoprefixer
86 | 7. No standard CSS minifiers
87 |
88 | ## The case for CSS modules by Mark Dalgleish (@markdalgleish), 2015
89 |
90 | [video](https://www.youtube.com/watch?v=zR1lOuyQEt8), [presentation](https://github.com/markdalgleish/presentation-the-case-for-css-modules/blob/master/src/index.jade)
91 |
92 | ### proposed solution: [CSS modules](https://github.com/css-modules/css-modules)
93 |
94 | **Editor note**: if you treat CSS-in-JS as an umbrella term than CSS modules fails into this category too.
95 |
96 | Please read the specification, but basic idea is to have local CSS declarations by default and expose them as JS module, which is basically a hash which maps local CSS values to globally unique values.
97 |
98 | Solves:
99 |
100 | 1. Global Name Space
101 | 2. Dependencies. With `import "a.css"` you will not forget to load your CSS file. Even more you can check if actual classes are declared in CSS file with [TypeScript](https://github.com/Quramy/typed-css-modules) or [Flow](https://github.com/skovhus/css-modules-flow-types).
102 | 3. Dead Code Elimination. **Not quite** - see section below.
103 | 4. Minification
104 | 5. Sharing Constants. Yes with variables
105 | 6. Non-deterministic Resolution. **No** - possible solution is to use linter
106 | 7. Isolation. **Yes and no**. You still can get yourself into troubles with `:global`, but this is antipattern
107 |
108 | And also:
109 |
110 | 1. No Code duplication in case of SSR
111 | 2. No Additional costs in JS payload, except objects with class names, like `import style from "a.css"`, where `style == {'a': ''}`
112 | 3. Media queries
113 | 4. CSS animations
114 | 5. Pseudo-classes
115 | 6. Autoprefixer
116 | 7. Standard CSS minifiers
117 |
118 | ### Dead Code Elimination
119 |
120 | Lets define some terminology:
121 |
122 | **Critical CSS** - critical-path (above-the-fold) CSS (according to **@addyosmani**)
123 |
124 | **Critical CSS** - CSS required to generate current page e.g. all components on the page (according to **@markdalgleish**).
125 |
126 | **Dead Code Elimination** - remove stale code not used anywhere in the project, still serving more than required per current page (according to **@vjuex**, based on screenshots). **Note**: he showed this in screenshots, but proposed solution (e.g. inline styles) is actually in the realm of Critical CSS `¯\_(ツ)_/¯`.
127 |
128 | Ordered by size (`>` stands for "is more than"):
129 |
130 | ```
131 | CSS after Dead Code Elimination > Critical CSS according to @markdalgleish > Critical CSS according to @addyosmani
132 | ```
133 |
134 | **Note** in further discussion I will stick to the definition of Critical CSS according to @markdalgleish.
135 |
136 | It is (almost) possible to do Dead Code Elimination in CSS modules. See [webpack-contrib/css-loader#506](https://github.com/webpack-contrib/css-loader/issues/506), [dead-css-loader](https://github.com/simlrh/dead-css-loader).
137 |
138 | To do Critical CSS, we need some solution to track what actually is required to render the current page at runtime. It could look something like this:
139 |
140 | ```js
141 | import { criticalTracker } from 'criticalModules'
142 | import { a, b } from "a.css";
143 |
144 | // it should track styles on server,
145 | // but can be no-op at the client
146 | criticalTracker({ a, b }, "a.css");
147 |
148 | const Heading = ({ children }) => (
149 |
150 | { children }
151 |
152 | )
153 | ```
154 |
155 | And SSR will look like:
156 |
157 | ```js
158 | import { StyleSheetServer } from 'criticalModules'
159 |
160 | const { html, css } = StyleSheetServer.renderStatic(
161 | () => ReactDOMServer.renderToString()
162 | )
163 | ```
164 |
165 | **Related**: [CSS modulues in c-r-a](https://github.com/facebookincubator/create-react-app/pull/2285), [comment by @sokra](https://github.com/webpack-contrib/style-loader/pull/159#issuecomment-286729044)
166 |
167 | ### Theming
168 |
169 | #### Overriding styles
170 |
171 | Proposed solution: [react-themeable](https://github.com/markdalgleish/react-themeable)
172 |
173 | With CSS modules:
174 |
175 | ```js
176 | import theme from './MyComponentTheme.css';
177 |
178 | ```
179 |
180 | Same with inline styles:
181 |
182 | ```js
183 | const theme = {
184 | foo: {
185 | 'color': 'red'
186 | },
187 | bar: {
188 | 'color': 'blue'
189 | }
190 | };
191 |
192 | ```
193 |
194 | #### Overriding theme variables
195 |
196 | For this you need CSS-in-JS.
197 |
198 | ## Styling React.JS applications by Max Stoiber (@mxstbr), 2016
199 |
200 | [video](https://www.youtube.com/watch?v=19gqsBc_Cx0), [code](https://github.com/styled-components/comparison)
201 |
202 | ### Inline styles vs CSS-in-JS
203 | @mxstbr differentiate `Inline styles` and `CSS-in-JS`. By `inline styles` he means React built-in support for style property and by `CSS-in-JS` he means a solution which generates CSS and injects via style tag. On the other hand, `CSS-in-JS` is the term coined by @vjeux in 2014 and he meant `Inline styles`. But there is Radium which also uses inline styles. Also sometimes people tend to use `CSS-in-JS` as an umbrella term and CSS modules fell into this category too `¯\_(ツ)_/¯`
204 |
205 | So I would suggest to use CSS-in-JS as an umbrella term and specify technique behind the implementation, like inline styles, style element, mixed (like Radium).
206 |
207 | ### No build requirements
208 | The title is pretty self-explanatory. You still need build step for JSX though.
209 |
210 | ### Small and lightweight
211 | This is a pretty hand-wavy category. @mxstbr never defines how much is a small size.
212 |
213 | Note: it doesn't make sense to measure gzipped KB of download - because this doesn't account the cost of JS parsing and compiling. See [this post by @addyosmani for details](https://medium.com/dev-channel/the-cost-of-javascript-84009f51e99e)
214 |
215 | Note: in the end, he will remove this column from comparison anyway `¯\_(ツ)_/¯`
216 |
217 | ### Supports global CSS
218 | @mxstbr mentions `@font-face`. I suppose all HTML elements and `@keyframes` fall into this category.
219 |
220 | Also, `@media` queries fall into this category. Important is to distinguish between real CSS and JS simulated `@media` queries. Second can't be prerendered as CSS at a server.
221 |
222 | ### Supports entirety of CSS
223 | @mxstbr mentions `:hover`, `:focus` (pseudo-classes). Important is to distinguish between real CSS and JS simulated pseudo-classes. Second can't be prerendered as CSS at a server. And not all of the pseudo-classes is easy to simulate with JS.
224 |
225 | ### Colocoted
226 | @mxstbr didn't explicitly explained it, but I suppose this is the same approach as BEM - CSS lives near the corresponding JS file.
227 |
228 | ### Isolated
229 | See "Isolation" according to @vjeux
230 |
231 | ### Easy to override
232 | Not sure what that suppose to mean.
233 |
234 | ### Theming
235 | I suppose @mxstbr keep in mind "Overriding theme variables" as explained by `@markdalgleish`
236 |
237 | ### SSR
238 | This requirement can mean two things:
239 |
240 | First. Be able to run React in server environment e.g. do not use `window` or any other browser specific APIs for injecting CSS.
241 |
242 | Second. Be able to prerender CSS on the server the same way as HTML can be prerendered for React (example Aphrodite).
243 | If you will prerender HTML, but not prerender CSS, you basically lose performance boost which you can have from prerendering HTML. But there is still a benefit for crawlers who cares mainly about HTML and not CSS.
244 |
245 | ### No wrapper components
246 | @mxstbr complains that it is kind of clumsy - you need to place wrappers everywhere and you need to remember the exact syntax.
247 |
248 | ## A Unified Styling Language by Mark Dalgleish (@markdalgleish), 2017
249 |
250 | [presentation](https://markdalgleish.github.io/presentation-a-unified-styling-language/), [video](https://www.youtube.com/watch?v=X_uTCnaRe94), [blog](https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660)
251 |
252 | ### Real CSS
253 |
254 | When the library doesn't do inline styles - they generate real CSS. It means you can use pseudo-classes and media queries.
255 |
256 | Example (JSS):
257 |
258 | ```js
259 | const styles = {
260 | button: {
261 | padding: '10px',
262 | '&:hover': {
263 | background: 'blue'
264 | }
265 | },
266 | '@media (min-width: 1024px)': {
267 | button: {
268 | padding: '20px'
269 | }
270 | }
271 | }
272 | ```
273 |
274 | ### Critical CSS
275 |
276 | **Critical CSS** - CSS required to generate current page e.g. all components on the page
277 |
278 | Example (Aphrodite):
279 |
280 | ```js
281 | import { StyleSheet, css } from 'aphrodite'
282 |
283 | const styles = StyleSheet.create({
284 | heading: { color: 'blue' }
285 | })
286 |
287 | const Heading = ({ children }) => (
288 |