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

The Road to Styled Components

The Road to Styled Components

Presented at Web Directions Code 2017

9f89c865453b5b9ae67e4f4d3989ea3b?s=128

Glen Maddern

August 04, 2017
Tweet

Transcript

  1. st yle d component s THE ROAD TO

  2. @glenmaddern

  3. None
  4. FRONT END C E N T E R https://frontend.center

  5. @glenmaddern https:/ /github.com/css-modules/css-modules https://styled-components.com https://github.com/geelen/react-snapshot react snapshot

  6. @glenmaddern STYLED COMPONENTS THE ROAD TO

  7. @glenmaddern STYLED COMPONENTS AND THE ROAD AHEAD THE ROAD TO

  8. STYLED COMPONENTS • CSS-in-React library • 300K+ downloads/month • 9000+

    stars on GitHub • 130 contributors but core team: @_philpl @mxstbr @glenmaddern
  9. @glenmaddern CSS-IN-JS

  10. • Scoped styles • Critical CSS • Smarter optimisations •

    Package management • Non-browser styling BENEFITS OF CSS-IN-JS https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660 @markdalgleish
  11. @glenmaddern WHY BUILD A CSS-IN-JS LIBRARY WHAT DO YOU PUT

    IN IT &
  12. @glenmaddern WHY BUILD A CSS-IN-JS LIBRARY WHAT DO YOU PUT

    IN IT &
  13. @glenmaddern DESIGN GOAL #1 CODIFY BEST PRACTICES

  14. https://speakerdeck.com/didoo/let-there-be-peace-on-css @areaweb Separation of Concerns Separation of Concerns (only, from

    a different point of view) JS CSS HTML BUTTON DATE PICKER MODAL LIST LIST-ITEM MEDIA
  15. @glenmaddern components/ submit-button/ submit-button.js submit-button.scss nav-bar/ nav-bar.js nav-bar.scss nav-icon.svg signup-form/

    signup-form.js signup-form.scss form-backdrop.jpg
  16. @glenmaddern

  17. @glenmaddern /* styles.css */ .Headline { padding: 4em; background: papayawhip;

    } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } <!-- my_page.html --> <!-- ... --> <header class="Headline"> <h1 class="Headline_Text"> My Page Title </h1> </header> <!-- ... --> REACT & WEBPACK
  18. @glenmaddern /* styles.css */ .Headline { padding: 4em; background: papayawhip;

    } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } <!-- my_page.html --> <!-- ... --> <header class="Headline"> <h1 class="Headline_Text"> My Page Title </h1> </header> <!-- ... --> /* src/components/Headline.css */ .Headline { padding: 4em; background: papayawhip; } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } REACT & WEBPACK
  19. @glenmaddern /* styles.css */ .Headline { padding: 4em; background: papayawhip;

    } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } <!-- my_page.html --> <!-- ... --> <header class="Headline"> <h1 class="Headline_Text"> My Page Title </h1> </header> <!-- ... --> /* src/components/Headline.css */ .Headline { padding: 4em; background: papayawhip; } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } /* src/components/Headline.js */ import './Headline.css' export default ({ text }) => ( <header className="Headline"> <h1 className="Headline_Text"> { text } </h1> </header> ) REACT & WEBPACK
  20. @glenmaddern

  21. @glenmaddern /* src/components/Headline.css */ .Headline { padding: 4em; background: papayawhip;

    } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } /* src/components/Headline.js */ import './Headline.css' export default ({ text }) => ( <header className="Headline"> <h1 className="Headline_Text"> { text } </h1> </header> ) CSS MODULES
  22. @glenmaddern /* src/components/Headline.css */ .Headline { padding: 4em; background: papayawhip;

    } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } /* src/components/Headline.js */ import './Headline.css' export default ({ text }) => ( <header className="Headline"> <h1 className="Headline_Text"> { text } </h1> </header> ) /* src/components/Headline.module.css */ .wrapper { padding: 4em; background: papayawhip; } .text { font-size: 1.5em; text-align: center; color: palevioletred; } CSS MODULES
  23. @glenmaddern /* src/components/Headline.css */ .Headline { padding: 4em; background: papayawhip;

    } .Headline_Text { font-size: 1.5em; text-align: center; color: palevioletred; } /* src/components/Headline.js */ import './Headline.css' export default ({ text }) => ( <header className="Headline"> <h1 className="Headline_Text"> { text } </h1> </header> ) /* src/components/Headline.js */ import styles from './Headline.css' export default ({ text }) => ( <header className={ styles.wrapper }> <h1 className={ styles.text }> { text } </h1> </header> ) /* src/components/Headline.module.css */ .wrapper { padding: 4em; background: papayawhip; } .text { font-size: 1.5em; text-align: center; color: palevioletred; } CSS MODULES
  24. @glenmaddern https:/ /styled-components.com/ https:/ /styled-components.com/docs

  25. @glenmaddern /* src/components/Headline.js */ import styles from './Headline.css' export default

    ({ text }) => ( <header className={ styles.wrapper }> <h1 className={ styles.text }> { text } </h1> </header> ) /* src/components/Headline.module.css */ .wrapper { padding: 4em; background: papayawhip; } .text { font-size: 1.5em; text-align: center; color: palevioletred; } STYLED COMPONENTS
  26. @glenmaddern /* src/components/Headline.js */ import styled from 'styled-components' const Wrapper

    = styled.header` padding: 4em; background: papayawhip; `; const Text = styled.h1` font-size: 1.5em; text-align: center; color: palevioletred; `; export default ({ text }) => ( <Wrapper> <Text>{ text }</Text> </Wrapper> ) /* src/components/Headline.js */ import styles from './Headline.css' export default ({ text }) => ( <header className={ styles.wrapper }> <h1 className={ styles.text }> { text } </h1> </header> ) /* src/components/Headline.module.css */ .wrapper { padding: 4em; background: papayawhip; } .text { font-size: 1.5em; text-align: center; color: palevioletred; } STYLED COMPONENTS
  27. @glenmaddern <Button /> <Button primary/> <Button disabled/> <Link to="..."/> <Link

    to="... " subtle/> <Link to="..." external/> <Media object={ ... }/> <Media object={ ... } alignment="right"/> <Media object={ ... } size="large"/>
  28. @glenmaddern <Button /> <Button primary/> <Button disabled/> <Link to="..."/> <Link

    to="... " subtle/> <Link to="..." external/> <Media object={ ... }/> <Media object={ ... } alignment="right"/> <Media object={ ... } size="large"/> <button type="button" class="btn"/> <button type="submit" class="btn btn--primary"/> <button type="button" disabled class="btn btn--disabled"/> <a href="..." class="link"/> <a href="..." class="link link--subtle"/> <a href="..." target="_blank" class="link link--external"/> <div class="media"> <figure class="media__image">...</figure> <div class="media__description">...</div> </div> <div class="media"> <div class="media__description">...</div> <figure class="media__image">...</figure> </div> <div class="media media--large"> <figure class="media__image">...</figure> <div class="media__description">...</div> </div>
  29. @glenmaddern DESIGN GOAL #1 CODIFY BEST PRACTICES • Component encapsulation

    • Semantic naming • Style co-location
  30. @glenmaddern DESIGN GOALS #2 BRING PEOPLE ALONG

  31. @glenmaddern /* EqualDivider.scss */ .EqualDivider { display: flex; margin: 0.5rem;

    padding: 1rem; background: papayawhip; > * { flex: 1; &:not(:first-child) { margin-left: 1rem; } } } .Box { padding: 0.25rem 0.5rem; background: palevioletred; }
  32. @glenmaddern /* EqualDivider.scss */ .EqualDivider { display: flex; margin: 0.5rem;

    padding: 1rem; background: papayawhip; > * { flex: 1; &:not(:first-child) { margin-left: 1rem; } } } .Box { padding: 0.25rem 0.5rem; background: palevioletred; } /* EqualDivider.sass */ .EqualDivider display: flex margin: 0.5rem padding: 1rem background: papayawhip > * flex: 1 &:not(:first-child) margin-left: 1rem .Box padding: 0.25rem 0.5rem background: palevioletred
  33. @glenmaddern /* EqualDivider.css.js */ const equalDivider = { display: 'flex',

    margin: '0.5rem', padding: '1rem', background: 'papayawhip', '> *': { flex: 1, '&:not(:first-child)': { marginLeft: '1rem' } } } const box = { padding: '0.25rem 0.5rem', background: 'palevioletred' }
  34. @glenmaddern /* EqualDivider.css.js */ const equalDivider = { display: 'flex',

    margin: '0.5rem', padding: '1rem', background: 'papayawhip', '> *': { flex: 1, '&:not(:first-child)': { marginLeft: '1rem' } } } const box = { padding: '0.25rem 0.5rem', background: 'palevioletred' } /* EqualDivider.js */ const EqualDivider = styled.div` display: flex; margin: 0.5rem; padding: 1rem; background: papayawhip; > * { flex: 1; &:not(:first-child) { margin-left: 1rem; } } ` const Box = styled.div` padding: 0.25rem 0.5rem; background: palevioletred; `
  35. @glenmaddern DESIGN GOALS #2 BRING PEOPLE ALONG INCREASE THE NUMBER

    OF PEOPLE WHO CAN GET VALUE FROM YOUR IDEA STRAIGHT AWAY
  36. @glenmaddern DESIGN GOALS #3 FOLLOW THE PATH OF LEAST RESISTANCE

  37. @glenmaddern <Button>Option A</Button> <Button className="primary">Option B</Button> const Button = styled.button`

    font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; background: palevioletred; color: white; &.primary { background: white; color: palevioletred; } `
  38. @glenmaddern <Button>Option A</Button> <Button className="primary">Option B</Button> const Button = styled.button`

    font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; background: palevioletred; color: white; ${props => props.primary && css` background: white; color: palevioletred; `} ` <Button>Option A</Button> <Button primary>Option B</Button> const Button = styled.button` font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; background: palevioletred; color: white; &.primary { background: white; color: palevioletred; } `
  39. @glenmaddern const Button = styled.button` font-size: 1em; margin: 1em; padding:

    0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; background: palevioletred; color: white; ${props => props.primary && css` background: white; color: palevioletred; `} ` <Button>Option A</Button> <Button primary>Option B</Button>
  40. @glenmaddern const Button = styled.button` font-size: 1em; margin: 1em; padding:

    0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; background: palevioletred; color: white; ${props => props.primary && css` background: white; color: palevioletred; `} ` <Button>Option A</Button> <Button primary>Option B</Button> const vars = { primary: 'palevioletred', secondary: 'white' } const Button = styled.button` font-size: 1em; margin: 1em; padding: 0.25em 1em; border: 2px solid palevioletred; border-radius: 3px; background: ${ vars.primary }; color: ${ vars.secondary }; ${props => props.primary && css` background: ${ vars.secondary }; color: ${ vars.primary }; `} `
  41. REACT NATIVE

  42. @glenmaddern import styled from 'styled-components/native' const Wrapper = styled.View` background-color:

    papayawhip; flex: 1; justify-content: center; align-items: center; ` const Title = styled.Text` font-size: 20px; text-align: center; margin: 10px; color: palevioletred; font-weight: bold; `
  43. @glenmaddern class StyledComponentsNative extends React.Component { render() { return (

    <Wrapper> <Title> Hello World, this is my first native styled component! </Title> </Wrapper> ) } }
  44. https://microsoft.github.io/reactxp/

  45. https://github.com/airbnb/react-sketchapp @jongold

  46. @glenmaddern DESIGN GOALS #3 FOLLOW THE PLATFORM

  47. @glenmaddern DESIGN GOAL #4 ZERO CONFIGURATION

  48. @glenmaddern

  49. @glenmaddern

  50. https://medium.com/reloading/javascript-start-up-performance-69200f43b201

  51. https://medium.com/reloading/javascript-start-up-performance-69200f43b201

  52. @glenmaddern STYLED COMPONENTS

  53. @glenmaddern STYLED COMPONENTS • 100% JavaScript

  54. @glenmaddern STYLED COMPONENTS • 100% JavaScript • No Webpack/Babel changes

    needed
  55. @glenmaddern STYLED COMPONENTS • 100% JavaScript • No Webpack/Babel changes

    needed • babel-plugin-styled-components
  56. @glenmaddern STYLED COMPONENTS • 100% JavaScript • No Webpack/Babel changes

    needed • babel-plugin-styled-components • Improves dev tooling
  57. @glenmaddern STYLED COMPONENTS • 100% JavaScript • No Webpack/Babel changes

    needed • babel-plugin-styled-components • Improves dev tooling • Makes server-rendering deterministic
  58. @glenmaddern STYLED COMPONENTS • 100% JavaScript • No Webpack/Babel changes

    needed • babel-plugin-styled-components • Improves dev tooling • Makes server-rendering deterministic • Better performance (v3 onwards)
  59. @glenmaddern DESIGN GOALS #5 DON'T MAKE THINGS WORSE

  60. https://medium.com/reloading/javascript-start-up-performance-69200f43b201 @addyosmani Parse times for 1MB JavaScript file

  61. https://medium.com/reloading/javascript-start-up-performance-69200f43b201 @addyosmani Parse times for 1MB JavaScript file iPHONE 5C

    1429MS
  62. @glenmaddern BET ON JS IF YOU LIKE, BUT ALWAYS SERVE

    HTML
  63. @glenmaddern https://github.com/gatsbyjs/gatsby https://learnnextjs.com https://github.com/geelen/react-snapshot react snapshot

  64. @glenmaddern WHY BUILD A CSS-IN-JS LIBRARY

  65. “IT SHOULD BE EASIER. THESE TOOLS ARE MAKING THINGS HARDER...

    WHEN YOU MAKE SOMETHING ACCESSIBLE TO NOVICES, IT BECOMES EASIER FOR EVERYBODY” @leaverou
  66. @leaverou

  67. @leaverou

  68. @glenmaddern LANDING PAGE WEB APP • Static HTML & CSS

    • Unobtrusive or no JavaScript • Meta tags designed for SEO and social sharing • Simple build step if any • Performance-sensitive • Fully client-rendered • Built using a JS framework • No extraneous metadata • Complex, all-inclusive build & optimisation process • Development-speed- sensitive VS
  69. @glenmaddern LANDING PAGE WEB APP • Static HTML & CSS

    • Unobtrusive or no JavaScript • Meta tags designed for SEO and social sharing • Simple build step if any • Performance-sensitive • Fully client-rendered • Built using a JS framework • No extraneous metadata • Complex, all-inclusive build & optimisation process • Development-speed- sensitive VS Sharing assets difficult or impossible
  70. LANDING PAGE WEB APP • Built with the same JS

    framework • Interactive components built the same way as static ones • Shared build process & optimisations • Real HTML & CSS served to all users • Components, assets, knowledge & workflow now shareable &
  71. https://medium.com/seek-blog/a-unified-styling-language-d0c208de2660 @markdalgleish “WE’VE ALREADY GONE THROUGH A SIMILAR CHANGE WITH

    HTML... WE ALMOST NEVER SHARE RAW HTML DIRECTLY— WE SHARE HTML-IN-JS.”
  72. @glenmaddern EVERYTHING-IN-JS ✨

  73. @glenmaddern UNIFICATION OF SKILLS & UNIFICATION OF PLATFORM

  74. @glenmaddern THE ROAD AHEAD: A UNIFIED UI LANGUAGE • It

    codifies best practices • It brings people along • It's expressive & powerful • It's universally usable
  75. t hank you! @glenmaddern

  76. t hank you! @glenmaddern https://frontend.center