Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modular CSS v2 (CSS-in-JS edition)

Modular CSS v2 (CSS-in-JS edition)

Slides of my evolved "Modular CSS" talk from React Alicante

Andrey Okonetchnikov

September 29, 2017
Tweet

More Decks by Andrey Okonetchnikov

Other Decks in Programming

Transcript

  1. View Slide

  2. Thanks to our sponsors!

    View Slide

  3. Andrey Okonetchnikov
    @okonetchnikov

    View Slide

  4. View Slide

  5. ColorSnapper
    http://colorsnapper.com

    View Slide

  6. View Slide

  7. Past Current time Future

    View Slide

  8. A brief history of CSS

    View Slide

  9. CSS 1.0
    Present Future
    CSS 2.1 Proposed
    1996 2004

    View Slide

  10. Present Future
    1996 2004

    View Slide

  11. CSS was designed for
    documents

    View Slide

  12. How many of you have ever re-designed
    a web-site with CSS changes only?

    View Slide

  13. Present Future
    1996 2004

    View Slide

  14. Present Future
    1996 2004 2005

    View Slide

  15. 2005 Present Future
    1996 2004

    View Slide

  16. View Slide

  17. View Slide

  18. View Slide

  19. Web-applications are built
    with UI Components

    View Slide

  20. UI Components
    Button

    View Slide

  21. Button
    UI Components

    View Slide

  22. 20+ years since the release
    of CSS 1.0

    View Slide

  23. CSS was designed for documents,
    not for web-applications

    View Slide

  24. Best practices

    View Slide

  25. Separation of concerns

    View Slide

  26. Separation of concerns
    JS
    CSS
    HTML

    View Slide

  27. Separation of concerns
    JS
    CSS
    HTML
    Checkbox
    Button
    Dropdown
    List
    Modal

    View Slide

  28. View Slide

  29. Natural mapping

    View Slide

  30. Natural mapping

    View Slide

  31. Past Current time Future

    View Slide

  32. HTML-in-JS
    a.k.a. JSX

    View Slide

  33. View Slide

  34. View Slide

  35. View Slide

  36. View Slide

  37. https://trends.google.com/trends/explore?q=%2Fm%2F012l1vxv,
    %2Fm%2F0268gyp

    View Slide

  38. View Slide

  39. Everything is a component!

    View Slide

  40. f(state) => UI

    View Slide

  41. What about styles?

    View Slide

  42. • Logic
    • HTML
    • Styles
    Button
    • Logic
    • HTML
    • Styles
    • Logic
    • HTML
    • Styles

    View Slide

  43. • Logic
    • HTML
    • Styles
    Button
    • Logic
    • HTML
    • Styles
    • Logic
    • HTML
    • Styles
    Global styles

    View Slide

  44. • Logic
    • HTML
    • Styles
    Button
    • Logic
    • HTML
    • Styles
    • Logic
    • HTML
    • Styles
    Global styles

    View Slide

  45. View Slide

  46. Global CSS
    1 .btn {
    2 /* styles for button */
    3 }
    4
    5 .active {
    6 /* styles for active button */
    7 background-color: blue;
    8 }
    9
    10 .label {
    11 /* styles for button label */
    12 }
    1 .star {
    2 /* styles for star */
    3 }
    4
    5 .active {
    6 /* styles for active star
    7 background-color: orange;
    8 }
    9

    View Slide

  47. .btn.active

    View Slide

  48. .content .albums .btn.active

    View Slide

  49. View Slide

  50. View Slide

  51. BEM
    https://en.bem.info/

    View Slide

  52. B
    E
    M

    View Slide

  53. .Block
    .Block --element
    .Block --element __modifier
    Block
    Element
    Modifier

    View Slide

  54. BEM


    Click me!


    View Slide

  55. BEM


    Click me!


    View Slide

  56. Manual work

    View Slide



  57. One


    Two


    Three


    View Slide

  58. .nav __item {
    padding: 4px 10px;
    color: black;
    }
    .nav __item_active {
    font-weight: bold;
    background: #ffc7c7;
    }
    .navigation __item {
    padding: 4px 10px;
    color: black;
    }
    .navigation __item_active {
    font-weight: bold;
    background: #ffc7c7;
    }

    View Slide

  59. View Slide

  60. View Slide

  61. Manual work

    View Slide

  62. View Slide

  63. +

    View Slide

  64. https://github.com/css-modules/css-modules

    View Slide

  65. Before: BEM-style
    const Button = ({ children }) => (


    { children }


    )

    View Slide

  66. After: CSS-modules
    import styles from './Button.css'
    const Button = ({ children }) => (


    { children }


    )

    View Slide

  67. After: CSS-modules
    import styles from './Button.css'
    const Button = ({ children }) => (


    { children }


    )

    View Slide

  68. How CSS-modules work?

    View Slide

  69. Before: BEM-style
    /* Button.css */
    .Button { /* general rules */ }
    .Button --disabled { /* disabled rules */ }
    .Button --active { /* active rules */ }
    .Button __label { /* label rules */ }

    View Slide

  70. After: CSS-modules
    /* Button.css */
    .root { /* general rules */ }
    .disabled { /* disabled rules */ }
    .active { /* active rules */ }
    .label { /* label rules */ }

    View Slide

  71. The result
    1 styles: {
    2 root: "Button __root __abc5436",
    3 disabled: "Button __disabled __def65
    4 active: "Button __active __1638bcd",
    5 label: "Button __label __5dfg462"
    5 }
    1 /* Button.css */
    2
    3 .root { }
    4 .disabled { }
    5 .active { }
    6 .label { }

    View Slide

  72. CSS-modules
    import styles from './Button.css'
    const Button = ({ children }) => (


    { children }


    )

    View Slide

  73. BEM for free!

    View Slide

  74. CSS-modules
    ✅ Explicit imports
    ✅ Scoped & fast selectors
    ✅ True rules isolation
    ✅ Code reuse, expressiveness
    ✅ Framework agnostic
    Non standard syntax
    (compose, vals, etc.)
    Build step is required
    No dead code elimination
    No automatic vendor prefixing

    View Slide

  75. View Slide

  76. +

    View Slide

  77. https://cssinjs.org

    View Slide

  78. export const styles = {
    button: {
    padding: '10px',
    '&:hover': {
    background: 'blue'
    }
    },
    '@media (min-width: 1024px)': {
    button: {
    padding: '20px'
    }
    }
    }

    View Slide

  79. Before: CSS-modules
    import styles from './Button.css'
    const Button = ({ children }) => (


    { children }


    )

    View Slide

  80. After: JSS
    import injectSheet from 'react-jss'
    import styles from './styles'
    const Button = ({ classes, children }) => (


    {children}


    )
    export default injectSheet(styles)(Button)

    View Slide

  81. CSS-in-JS (JSS)
    ✅ Explicit imports
    ✅ Scoped & fast selectors
    ✅ True rules isolation
    ✅ Code reuse, expressiveness
    ✅ Framework agnostic
    ✅ Uses w3c standard
    ✅ No build step is required
    ✅ Dead code elimination
    ✅ Automatic vendor prefixing

    View Slide

  82. —If we generate class names,
    why do we still use class attribute?

    View Slide

  83. https://www.styled-components.com/

    View Slide

  84. // Create a Title component that'll
    render an tag with some styles
    const Title = styled.h1`
    font-size: 1.5em;
    text-align: center;
    color: palevioletred;
    `;
    render(

    Hello React Alicante!

    );

    View Slide

  85. const Button = styled.button`
    /* Adapt the colors based on primary prop */
    background: ${props => props.primary ? 'palevioletred' : 'white'};
    color: ${props => props.primary ? 'white' : 'palevioletred'};
    font-size: 1em;
    margin: 1em;
    padding: 0.25em 1em;
    border: 2px solid palevioletred;
    border-radius: 3px;
    `;
    render(

    Normal
    Primary

    );

    View Slide

  86. styled-components
    ✅ No messing with classNames (implementation detail)
    ✅ Same mental model and structure for the whole
    application

    View Slide

  87. “styled-components […] removes the
    mapping between components and styles.”
    https://www.styled-components.com/

    View Slide

  88. Styled Components

    View Slide

  89. Styled Primitives

    View Slide

  90. styled-components for react-native
    import styled from 'styled-components/native';
    const StyledView = styled.View`
    background-color: papayawhip;
    `;
    const StyledText = styled.Text`
    color: palevioletred;
    `;
    class MyReactNativeComponent extends React.Component {
    render() {
    return (

    Hello World!

    )
    }
    }

    View Slide

  91. styled-components for Sketch

    View Slide

  92. View Slide

  93. Past Current time Future

    View Slide

  94. Universal
    rendering

    View Slide

  95. import React from 'react';
    import {AppRegistry, Pano, Text, View} from 'react-vr';
    class WelcomeToVR extends React.Component {
    render() {
    // Displays "hello" text on top of a loaded 360 panorama image.
    // Text is 0.8 meters in size and is centered three meters in front
    of you.
    return (


    style={{
    fontSize: 0.8,
    layoutOrigin: [0.5, 0.5],
    transform: [{translate: [0, 0, -3]}],
    }}>
    hello


    );
    }
    };
    AppRegistry.registerComponent('WelcomeToVR', () => WelcomeToVR);

    View Slide

  96. View Slide

  97. View Slide

  98. View Slide

  99. View Slide

  100. Design systems shared between
    designers and developers!

    View Slide

  101. View Slide

  102. Wait! But…
    Myths & misconceptions about CSS-in-JS

    View Slide

  103. “CSS-in-JS is slow”

    View Slide

  104. View Slide

  105. 1. CSS-in-JS ≠ inline styles!

    View Slide

  106. import { css } from 'glamor'
    const title = css({
    fontSize: '1.8em',
    fontFamily: 'Comic Sans MS',
    color: 'blue'
    })
    console.log(title)
    // → 'css-1pyvz'

    View Slide

  107. 2. CSS-in-JS is fast enough

    View Slide

  108. http://cssinjs.org/function-values/

    View Slide

  109. 3. Maintanability > Speed

    View Slide

  110. https://twitter.com/dan_abramov/status/842329893044146176

    View Slide

  111. View Slide

  112. https://codepen.io/malyw/pen/XRRgeB

    View Slide

  113. View Slide

  114. “Crafted CSS is better for performance”

    View Slide

  115. View Slide

  116. https://meiert.com/en/blog/20170531/70-percent-css-repetition/
    “In CSS, we repeat ourselves too much.
    While it’s absolutely, practically possible
    to limit declaration repetition to 10–
    20%, reality averages 72% (median
    66%).”

    View Slide

  117. Functional CSS?

    View Slide

  118. http://tachyons.io

    View Slide

  119. Tachyons


    Title


    Lorem ipsum dolor sit amet.


    View Slide

  120. View Slide

  121. View Slide

  122. Manual work

    View Slide

  123. View Slide

  124. Enables CSS optimisations

    View Slide

  125. …but uses very simple API
    import {styled} from 'styletron-react';
    const Panel = styled('div', (props) => ({
    backgroundColor: props.alert ? 'orange' : 'lightblue',
    fontSize: '12px'
    }));
    Danger!

    View Slide

  126. airbnb.com CSS output size

    View Slide

  127. Use functional CSS

    View Slide

  128. Generate functional CSS

    View Slide

  129. View Slide

  130. View Slide

  131. “It’s not real CSS!”

    View Slide

  132. View Slide

  133. SASS has variables, mixins, etc.

    View Slide

  134. JavaScript has variables, functions

    View Slide

  135. https://una.im/sass-es2015/#

    View Slide

  136. Variables
    let color = "red";
    $color: "red";

    View Slide

  137. Lists
    const colorArray = ["red", "yellow", "green"];
    for (let color of colorArray) {
    console.log(color);
    }
    $colorList: "red", "yellow", "green";
    @each $color in $colorList {
    @debug $color;
    }

    View Slide

  138. Functions
    function PrintMe(firstArg, ...theRest) {
    console.log(firstArg, theRest);
    }
    @mixin funCircle($size, $gradient ...) {
    width: $size;
    height: $size;
    background: radial-gradient($gradient);
    }

    View Slide

  139. https://polished.js.org/

    View Slide

  140. // Styles as object usage
    const styles = {
    background: lighten(0.2, '#CCCD64'),
    background: lighten(0.2, 'rgba(204,205,100,0.7)'),
    }
    // styled-components usage
    const div = styled.div`
    background: ${lighten(0.2, '#FFCD64')};
    background: ${lighten(0.2, 'rgba(204,205,100,0.7)')};
    `
    // Output
    element {
    background: "#e5e6b1";
    background: "rgba(229,230,177,0.7)";
    }

    View Slide

  141. “You should use the Platform”*
    * Or, just Google Chrome?

    View Slide

  142. View Slide

  143. View Slide

  144. View Slide

  145. View Slide

  146. View Slide

  147. styled-jsx
    export default () => (

    only this paragraph will be red
    {`<br/>p {<br/>color: red;<br/>}<br/>`}

    )

    View Slide

  148. styled-jsx
    import _JSXStyle from 'styled-jsx/style'
    export default () => (

    only this paragraph will get the
    style :)
    <_JSXStyle styleId='cn2o3j' css={`p[data-jsx=cn2o3j]
    {color: red;}`} />

    )

    View Slide

  149. View Slide

  150. “CSS is simple”

    View Slide

  151. CSS is simple

    View Slide

  152. CSS is simple CSS is easy

    View Slide

  153. https://adactio.com/journal/12571
    “It is simple in the sense of “not complex”,
    but that doesn’t mean it’s easy. Mistaking
    “simple” for “easy” will only lead to
    heartache.”

    View Slide

  154. How many of you know how to
    extract critical CSS or doing that?

    View Slide

  155. Critical CSS with <>
    import { renderToString } from 'react-dom/server'
    import { ServerStyleSheet } from 'styled-components'
    const sheet = new ServerStyleSheet()
    const html = renderToString(sheet.collectStyles())
    const css = sheet.getStyleTags()

    View Slide

  156. https://medium.com/seek-blog/a-unified-styling-language-
    d0c208de2660
    “If you build your app with progressive
    enhancement in mind, despite being
    written entirely in JavaScript, it might not
    require JavaScript on the client at all.”

    View Slide

  157. Takeaways

    View Slide

  158. View Slide

  159. “CSS-in-JS enforces the best practices
    trough technology and shared knowledge.”

    View Slide

  160. It’s still CSS and you still
    have to learn it!

    View Slide

  161. It’s not about how fast you can write code,
    it’s about how fast you can read it.

    View Slide

  162. Stay open-minded &
    keep experimenting!

    View Slide

  163. View Slide

  164. Thank you!

    View Slide

  165. Andrey Okonetchnikov
    @okonetchnikov
    http://okonet.ru
    https://github.com/okonet
    UI Engineer @ Feedly

    View Slide