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

Glen Maddern

August 04, 2017
Tweet

More Decks by Glen Maddern

Other Decks in Technology

Transcript

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

    stars on GitHub • 130 contributors but core team: @_philpl @mxstbr @glenmaddern
  2. • 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
  3. 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
  4. @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
  5. @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
  6. @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
  7. @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
  8. @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
  9. @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
  10. @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
  11. @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
  12. @glenmaddern <Button /> <Button primary/> <Button disabled/> <Link to="..."/> <Link

    to="... " subtle/> <Link to="..." external/> <Media object={ ... }/> <Media object={ ... } alignment="right"/> <Media object={ ... } size="large"/>
  13. @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>
  14. @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; }
  15. @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
  16. @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' }
  17. @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; `
  18. @glenmaddern DESIGN GOALS #2 BRING PEOPLE ALONG INCREASE THE NUMBER

    OF PEOPLE WHO CAN GET VALUE FROM YOUR IDEA STRAIGHT AWAY
  19. @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; } `
  20. @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; } `
  21. @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>
  22. @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 }; `} `
  23. @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; `
  24. @glenmaddern class StyledComponentsNative extends React.Component { render() { return (

    <Wrapper> <Title> Hello World, this is my first native styled component! </Title> </Wrapper> ) } }
  25. @glenmaddern STYLED COMPONENTS • 100% JavaScript • No Webpack/Babel changes

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

    needed • babel-plugin-styled-components • Improves dev tooling • Makes server-rendering deterministic
  27. @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)
  28. “IT SHOULD BE EASIER. THESE TOOLS ARE MAKING THINGS HARDER...

    WHEN YOU MAKE SOMETHING ACCESSIBLE TO NOVICES, IT BECOMES EASIER FOR EVERYBODY” @leaverou
  29. @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
  30. @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
  31. 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 &
  32. @glenmaddern THE ROAD AHEAD: A UNIFIED UI LANGUAGE • It

    codifies best practices • It brings people along • It's expressive & powerful • It's universally usable