Slide 1

Slide 1 text

1 JavaScript Style JavaScript Style Sheets Sheets by Oleg Slobodskoi jss React Amsterdam 2016

Slide 2

Slide 2 text

2 Plan Plan 1. React and CSS. 2. What are inline styles. 3. Problems solved by inline styles. 4. Interesting CSS in JS libs. 5. What is JSS. 6. Problems solved by JSS. 7. Unsolved problems.

Slide 3

Slide 3 text

3 React and CSS React and CSS React is about React is about components components. . CSS is for CSS is for documents. documents.

Slide 4

Slide 4 text

4 First JSS release First JSS release

Slide 5

Slide 5 text

5

Slide 6

Slide 6 text

6 Inline styles Inline styles const style = {color: red}
HTML React const element = document.createElement('div') element.style.color = 'red' DOM

Slide 7

Slide 7 text

7 Global Namespace Global Namespace Selectors are the evil. Try to write an application inside of one function.

Slide 8

Slide 8 text

8 Implicit Implicit Dependencies Dependencies My Button /* buttons.css */ .default-button { cursor: pointer; } /* my-component.css */ .my-button { color: red; }

Slide 9

Slide 9 text

9 Dead code Dead code A task for a compiler. function module() { var styles = { button: { color: 'green' }, myButton: { color: 'red' } } // Renders a button. button({style: styles.myButton}) } function module(){button({style:{color:"red"}})};

Slide 10

Slide 10 text

10 Minification Minification function test(a) { var obj = {a: a, b: 2}; return obj.a + obj.b; } window.a = test(1) window.a=3; No selectors to minify. JavaScript compressor for the rest.

Slide 11

Slide 11 text

11 Sharing Constants Sharing Constants Data driven styling Shared Breakpoints Javascript Layouts

Slide 12

Slide 12 text

12 Non-deterministic Non-deterministic Resolution Resolution CSS Specificity Concept. /* my-button-1.css */ .my-button.my-blue-button { color: blue; } /* my-button-2.css */ button.my-button { color: red; } My Button

Slide 13

Slide 13 text

13 Isolation Isolation No access to external components. Very high specificity.

Slide 14

Slide 14 text

14 Complex Selectors Complex Selectors .article #comments ul > li > a.button

Slide 15

Slide 15 text

15 Redundancy Redundancy Smaller payload.

Slide 16

Slide 16 text

16 Can we do even Can we do even better? better? YES. YES.

Slide 17

Slide 17 text

17 Other alternatives? Other alternatives?

Slide 18

Slide 18 text

18 And more ... And more ...

Slide 19

Slide 19 text

19 And more ... And more ... Text https://github.com/MicheleBertoli/css-in-js

Slide 20

Slide 20 text

20 3 Categories 3 Categories 1. Pure Inline 2. Mixed Mode 3. Pure Style Sheets

Slide 21

Slide 21 text

21 Pure Pure Inline Inline Already built in React No support for @media, @keyframes etc. Performance Downsides

Slide 22

Slide 22 text

22 Mixed Mode Mixed Mode Radium is using: React Events for Pseudo Selectors. Style Sheets for @media and co. Inline for everything else.

Slide 23

Slide 23 text

23 Pure Pure Style Sheets Style Sheets Aphrodite JSS

Slide 24

Slide 24 text

24 What is JSS. What is JSS. Good parts of CSS only. Designed with components in mind. Declarative JavaScript. JavaScript to CSS compiler. Easy to reason about.

Slide 25

Slide 25 text

25 How does it work. How does it work. Virtual CSS Tree Process Render Run plugins on every VRule Output with CSS. Abstraction for CSS Rules Manipulation

Slide 26

Slide 26 text

26 React-JSS React-JSS Lazy compilation Ref counting

Slide 27

Slide 27 text

27 Example with React Example with React import React from 'react' import {useSheet} from 'react-jss' @useSheet({ button: { color: 'green' } }) export default function Button(props) { const {classes} = props.sheet return {props.text} } No magic in code.

Slide 28

Slide 28 text

28

Slide 29

Slide 29 text

29 Boring CSS output. Boring CSS output.

Slide 30

Slide 30 text

30 Problems it solves. Problems it solves. 1. All issues solved by Inline Styles. 2. Issues introduced by Inline Styles. 3. More CSS Issues.

Slide 31

Slide 31 text

31 Plan Plan 1. Media Queries 2. Keyframes Animation 3. Font Face 4. Pseudo Selectors 5. Fallbacks 6. Rules Caching 7. Rules Sharing 8. Extensible Architecture 9. Tools Agnostic 10. Vendor Prefixer 11. Inheritance DSL Library

Slide 32

Slide 32 text

32 Media Queries Media Queries export default { '@media (min-width: 1024px)': { button: { minWidth: 200 } } } const breakpoint = 1024 export default { [`@media (min-width: ${breakpoint}px)`]: { button: { minWidth: 200 } } } @media (min-width: 1024px) { .button-jss-0 { min-width: 200px; } } JSS in ES5 JSS in ES6 CSS Not possible Inline.

Slide 33

Slide 33 text

33 Keyframes Animation Keyframes Animation export default { '@keyframes my-animation': { from: {opacity: 0}, to: {opacity: 1} } } const identifier = random() export default { [`@keyframes ${identifier}`]: { from: {opacity: 0}, to {opacity: 1} } } @keyframes my-animation { from { opacity: 0; } to { opacity: 1; } } JSS in ES5 JSS in ES6 CSS Not possible Inline.

Slide 34

Slide 34 text

34 Font Face Font Face export default { '@font-face': { fontFamily: 'MyWebFont', src: [ 'url(webfont.eot)', 'url(webfont.eot?#iefix) format(embedded-opentype)', 'url(webfont.woff2) format(woff2)' ] } } @font-face { font-family: 'MyWebFont'; src: url('webfont.eot'); src: url('webfont.eot?#iefix') format('embedded-opentype'), url('webfont.woff2') format('woff2'); } JSS CSS Not possible Inline.

Slide 35

Slide 35 text

35 Pseudo Selectors Pseudo Selectors export default { button: { color: 'green' '&:hover': { color: 'red' }, '&:active': { color: blue }, '&:before': { content: '"icon"' }, '& span': { verticalAlign: 'middle' } } } .jss-0-1 { color: green; } .jss-0-1:hover { color: red; } .jss-0-1:active { color: blue; } .jss-0-1:before { content: "icon"; } .jss-0-1 span { vertical-align: middle; } JSS CSS Not possible Inline. Inspired by Sass.

Slide 36

Slide 36 text

36 Fallbacks Fallbacks export default { container: { display: ['box', 'flexbox','flex'] } } .jss-0-1 { display: box; display: flexbox; display: flex; } JSS CSS Not possible Inline.

Slide 37

Slide 37 text

37 Rules Caching Rules Caching Not possible Inline. CSS Rules are created just once.

Slide 38

Slide 38 text

38 Rules Sharing Rules Sharing Not possible Inline. One rule applies to all list items

Slide 39

Slide 39 text

39 Class Names are fast. Class Names are fast. 1. Find modified props. 2. Find props to unset. 3. Ensure valid property name, value, default unit. 4. Apply each property to an element

Slide 40

Slide 40 text

40 Smaller Payload Smaller Payload Up to 50% smaller payload when rendered at runtime.

Slide 41

Slide 41 text

41 Tools Agnostic Tools Agnostic Library agnostic. Infrastructure agnostic.

Slide 42

Slide 42 text

42 Extensible Extensible Small Core Plugins API.

Slide 43

Slide 43 text

43 Vendor Prefixer Vendor Prefixer Plugin export default { container: { display: 'flex' } } .jss-0-1 { display: -webkit-flex; } JSS CSS

Slide 44

Slide 44 text

44 Inheritance Inheritance Styles inherit from parent. Still no TRUE Isolation.

Slide 45

Slide 45 text

45 JSS-ISOLATE JSS-ISOLATE Created a JSS plugin. and SOLVED INHERITANCE PROBLEM Maxim Koretskiy “ This plugin protects styles from inheritance. It automatically creates a reset rule and applies it to every user's rule.

Slide 46

Slide 46 text

46 Unsolved Problems Unsolved Problems :( :(

Slide 47

Slide 47 text

47 Overengineered Overengineered Solution Solution If you feel it - don't use it.

Slide 48

Slide 48 text

48 Wrong Language? Wrong Language? import color from 'color' import fonts from 'theme/fonts' import mixins from 'jss-mixins' import {gainsboroLight, grapeTypo, grey, blue, white} from 'theme/colors' const grapeTypoSemi = color(grapeTypo).alpha(0.5).rgbaString() export default { datalist: { background: white, border: `1px solid ${gainsboroLight}`, boxShadow: `0px 3px 4px 0 ${grapeTypoSemi}`, overflow: 'auto' }, item: { extend: [fonts.normal, mixins.ellipsis], padding: `5px 7px`, color: grey, cursor: `pointer` }, `@media (min-width: 1024px)`: { item: { color: blue } } }

Slide 49

Slide 49 text

49 Let's experiment! Let's experiment! export default css` datalist { background: ${white}; border: 1px solid ${gainsboroLight}; box-shadow: 0px 3px 4px 0 ${grapeTypoSemi}; overflow: auto } item { extend: ${[fonts.normal, mixins.ellipsis]}; padding: 5px 7px; color: ${grey}; cursor: ${pointer}; } @media (min-width: 1024px) { item { color: ${blue} } } ` Tagged template literals

Slide 50

Slide 50 text

50 No standard DSL No standard DSL Styles reuse only together with the lib.

Slide 51

Slide 51 text

51 Missing dev tools Missing dev tools There is no autocomplete tools like Emmet or IntelliSense. There is no CSS specific highlighting. No linters.

Slide 52

Slide 52 text

52 Blocks initial Blocks initial rendering. rendering. Use it where it doesn't matter. Use server-side rendering. Use a hybrid approach.

Slide 53

Slide 53 text

53 Takeaways Takeaways CSS in JS is not only for big projects, it's for any maintainable project. Use Inline Styles for: 1. State styles. For e.g. when a "width" of a component depends on its state. 2. Animations. Don't be religious. Keep an open mind. Use tools that solve your problems!

Slide 54

Slide 54 text

54 Thank You Thank You #reactamsterdam @oleg008 https://github.com/jsstyles/jss