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

CSS preprocessors for the best of both worlds (From the Front 2014)

CSS preprocessors for the best of both worlds (From the Front 2014)

While purists propagate to not mix content structure (HTML), presentation (CSS) and behavior (JavaScript) layers for the reason of maintainability, concepts like OOCSS aim at the same goal, but from a different angle: reusable CSS code, at the expense of bloated, presentational mark-up, violating the separation of concerns. Can’t we have both, clean mark-up and reusable CSS? The benefits of both approaches without the drawbacks?
Yes, we can. This talk shows how to take the OO concept out of the HTML and put it where it belongs to: into the style sheet. Not directly into the CSS though, but into an intermediate layer provided by a CSS preprocessor like Sass.
Like Ogers and onions, concepts have layers. Unlike Ogers and onions, they don’t always stink, but eventually lead to the best of both worlds.

Video: https://www.youtube.com/watch?v=ot-LoU0MGb0

Gunnar Bittersmann

September 18, 2014
Tweet

More Decks by Gunnar Bittersmann

Other Decks in Programming

Transcript

  1. OF BOTH WORLDS
    CSS PREPROCESSORS

    View Slide

  2. CSS PREPROCESSORS

    View Slide

  3. OF BOTH WORLDS

    View Slide

  4. OUT OF YOUR BEANS
    COFFEE GRINDERS
    98 € PICK
    Peugeot
    Coffee grinder
    76 € PICK
    Kalita
    Coffee grinder
    54 € PICK
    Heyde
    Coffee grinder

    View Slide










  5. Pick me!



    View Slide


  6. .product-list { … }
    .product-item { … }
    .product-image { … }
    .product-brand { … }
    .product-model { … }
    .product-description { … }
    .product-price { … }
    .btn { … }
    .btn-cta { … }

    View Slide

  7. OUT OF YOUR BEANS
    COFFEE GRINDERS
    BUY
    Peugeot Coffee grinder
    Kalita Coffee grinder
    98 €
    76 €
    In your basket:
    total amount 174 €

    View Slide














  8. View Slide


  9. .product-list { … }
    .product-item { … }
    .product-image { … }
    .product-brand { … }
    .product-model { … }
    .product-description { … }
    .product-price { … }
    .btn { … }
    .btn-cta { … }
    .checkout-list { … }
    .checkout-item { … }
    .checkout-image { … }
    .checkout-brand { … }
    .checkout-model { … }
    .checkout-description { … }
    .checkout-price { … }

    View Slide










  10. Pick me!



    View Slide














  11. View Slide


  12. #page-products .product-list { … }
    #page-products .product-list li { … }
    #page-products .product-list .product-image { … }
    #page-products .product-list .brand { … }
    #page-products .product-list .model { … }
    #page-products .product-list .description { … }
    #page-products .product-list .price { … }
    #page-products .product-list button { … }

    #page-checkout .product-list { … }
    #page-checkout .product-list li { … }
    #page-checkout .product-list .product-image { … }
    #page-checkout .product-list .brand { … }
    #page-checkout .product-list .model { … }
    #page-checkout .product-list .description { … }
    #page-checkout .product-list .price { … }

    View Slide


  13. #page-products
    {

    .product-list
    {


    li { … }
    .product-image { … }
    .brand { … }
    .model { … }
    .description { … }
    .price { … }
    button { … }
    }
    }
    nesting

    View Slide


  14. #page-checkout
    {

    .product-list
    {


    li { … }
    .product-image { … }
    .brand { … }
    .model { … }
    .description { … }
    .price { … }

    }
    }
    nesting

    View Slide






  15. @import "_page-products";
    @import "_page-checkout";


    modularization

    View Slide






  16. @import "_page-products";
    @import "_page-checkout";


    modularization

    @import "_colors";
    @import "_type";
    @import "_image-replacement";
    @import "_page-layout";

    View Slide

  17. Atomic design (Brad Frost)

    View Slide

  18. Atomic design (Brad Frost)
    ATOMS MOLECULES ORGANISMS TEMPLATES PAGES

    View Slide

  19. no classes!
    Look ma,

    View Slide















  20. Pick me!



    View Slide


  21. #page-products
    {

    .product-list
    {


    li { … }
    [property="image"] { … }
    [property="brand"] { … }
    [property="model"] { … }
    [property="description"] { … }
    [property="price"] { … }
    button { … }
    }
    }

    View Slide

  22. View Slide

  23. One more cup of coffee, please!

    >One more cup of coffee, please!

    View Slide

  24. ONE MORE CUP OF COFFEE, PLEASE!

    One more cup of coffee, please!
    .uppercase { text-transform: uppercase }

    View Slide

  25. one more cup of coffee, please!

    One more cup of coffee, please!
    .uppercase { text-transform: uppercase }
    .lowercase { text-transform: lowercase }

    View Slide

  26. UN’ ALTRA TAZZA DI CAFFÈ, PER FAVORE!

    Un’ altra tazza di caffè, per favore!
    .uppercase { text-transform: uppercase }
    .lowercase { text-transform: lowercase }

    View Slide

  27. un’ altra tazza di caffè, per favore!

    Un’ altra tazza di caffè, per favore!
    .uppercase { text-transform: uppercase }
    .lowercase { text-transform: lowercase }

    View Slide

  28. NOCH EIN TÄSSCHEN KAFFEE, BITTE!

    Noch ein Tässchen Kaffee, bitte!
    .uppercase { text-transform: uppercase }
    .lowercase { text-transform: lowercase }

    View Slide

  29. noch ein tässchen kaffee, bitte!

    Noch ein Tässchen Kaffee, bitte!
    .uppercase { text-transform: uppercase }
    .lowercase { text-transform: lowercase }

    View Slide

  30. Noch ein Tässchen Kaffee, bitte!

    Noch ein Tässchen Kaffee, bitte!
    .uppercase { text-transform: uppercase }
    .lowercase { text-transform: lowercase }
    .lowercase:lang(de) { text-transform: none }
    ✘  

    View Slide

  31. PRESENTATIONAL
    MARKUP

    View Slide

  32. Noch ein Tässchen Kaffee, bitte!

    >Noch ein Tässchen Kaffee, bitte!

    h1 { text-transform: lowercase }
    h1:lang(de) { text-transform: none }
    ✔  

    View Slide

  33. QA'VIN LATLH TU'LUM HINOBNES!

    qa'vIn latlh tu'lum HInobneS!

    h1 { text-transform: uppercase }

    View Slide

  34. qa'vin latlh tu'lum hinobnes!

    qa'vIn latlh tu'lum HInobneS!

    h1 { text-transform: lowercase }

    View Slide

  35. qa'vIn latlh tu'lum HInobneS!

    qa'vIn latlh tu'lum HInobneS!

    h1 { text-transform: lowercase }
    :lang(tlh) { text-transform: none !important}
    ✔  

    View Slide




  36. .hidden { display: none }

    View Slide




  37. .hidden { display: none !important }

    View Slide




  38. .hidden { display: none !important }
    $('#pick-me').show();
    document.querySelector('#pick-me').style.display = 'block';

    View Slide




  39. .hidden { display: none !important }
    $('#pick-me').show();
    document.querySelector('#pick-me').style.display = 'block';

    View Slide

  40. $('#pick-me').removeClass('hidden');
    document.querySelector('#pick-me').classList.remove('hidden');



    .hidden { display: none !important }

    View Slide


  41. $('#pick-me').removeAttr('hidden');
    document.querySelector('#pick-me').removeAttribute('hidden');

    View Slide


  42. $('#pick-me').removeAttr('hidden');
    document.querySelector('#pick-me').removeAttribute('hidden');
    [hidden] { display: none !important }

    View Slide

  43. Structure
    (HTML/DOM)
    Behavior
    (JavaScript)
    Presentation
    (CSS)

    View Slide

  44. Structure
    (HTML/DOM)
    Presentation
    (CSS)
    Behavior
    (JavaScript)
    Separation of concerns

    View Slide

  45. OOCSS
    SEND ORDER CHANGE ADDRESS
    send order
    change address
    change basket
    CHANGE BASKET

    View Slide

  46. SEND ORDER CHANGE ADDRESS
    send order
    change address
    change basket
    CHANGE BASKET

    View Slide


  47. .btn
    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }

    .btn-large
    {
    padding: 0.375em;
    font-size: 1.25rem;
    }

    .btn-small
    {
    padding: 0.25em
    font-size: 1rem;
    }

    .btn-red
    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }

    .btn-black
    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }
    Stylesheet
    OOCSS

    View Slide

  48. OOCSS
    Object Oriented CSS
    CSS “object”: a repeating visual pattern, which can be abstracted into an independent
    snippet of HTML, CSS, and possibly JavaScript.

    Goal: reusable code, maintainability, performance
    Principles:
    1.  Separate structure and skin
    2.  Separate container and content
    Means:
    •  class selectors
    •  no element type selectors
    •  no ID selectors
    •  no descendant combinators
    •  presentational classes in the mark-up

    View Slide

  49. OOCSS


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    btn







    btn-large





    btn-small





    btn-red





    btn-black






















    Markup Stylesheet
    class selector
    class attribute
    “CSS classes”

    View Slide

  50. OOCSS


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    btn







    btn-large





    btn-small





    btn-red





    btn-black






















    Markup Stylesheet
    class selector
    class attribute
    “CSS classes”

    View Slide

  51. PRESENTATIONAL
    MARKUP

    View Slide

  52. View Slide

  53. View Slide

  54. OOCSS

    View Slide

  55. “CSS CLASSES”

    View Slide

  56. View Slide

  57. View Slide

  58. OOCSS
    Object Oriented CSS
    CSS “object”: a repeating visual pattern, which can be abstracted into an independent
    snippet of HTML, CSS, and possibly JavaScript.

    Goal: reusable code, maintainability, performance
    Principles:
    1.  Separate structure and skin
    2.  Separate container and content
    Means:
    •  class selectors
    •  no element type selectors
    •  no ID selectors
    •  no descendant combinators
    •  presentational classes in the mark-up

    View Slide

  59. View Slide

  60. OOCSS
    Pros
    •  presentational markup
    •  bigger HTML files
    •  reusable code units
    •  smaller CSS file
    •  selector specificity
    •  selector performance
    Cons

    View Slide

  61. View Slide

  62. OOCSS
    Pros
    •  presentational markup
    •  bigger HTML files
    •  reusable code units
    •  selector specificity
    •  selector performance
    Cons

    View Slide

  63. View Slide

  64. OOCSS
    Pros
    •  presentational markup
    •  bigger HTML files
    •  reusable code units
    •  selector performance
    Cons

    View Slide

  65. View Slide

  66. OOCSS
    Pros
    •  presentational markup
    •  bigger HTML files
    •  reusable code units
    Cons

    View Slide

  67. OOCSS


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    btn







    btn-large





    btn-small





    btn-red





    btn-black






















    Markup Stylesheet

    View Slide



  68. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    btn







    btn-large





    btn-small





    btn-red





    btn-black






















    Markup Stylesheet

    View Slide



  69. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    btn







    btn-large





    btn-small





    btn-red





    btn-black






















    Markup Stylesheet

    View Slide



  70. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }










    {
    @include btn;
    @include btn-large;
    @include btn-red;
    }


    {
    @include btn;
    @include btn-small;
    @include btn-black;
    }

    @mixin btn







    @mixin btn-large





    @mixin btn-small





    @mixin btn-red





    @mixin btn-black









    [type="submit"]






    [type="button"]
    mixins

    View Slide



  71. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }










    {
    @include btn;
    @include btn-large;
    @include btn-red;
    }


    {
    @include btn;
    @include btn-small;
    @include btn-black;
    }

    @mixin btn







    @mixin btn-large





    @mixin btn-small





    @mixin btn-red





    @mixin btn-black









    [type="submit"]






    [type="button"]
    send order
    change address
    change basket
    mixins

    View Slide



  72. [type="submit"]
    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;

    padding: 0.375em;
    font-size: 1.25rem;

    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }

    [type="button"]
    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;

    padding: 0.25em;
    font-size: 1rem;

    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }










    {
    @include btn;
    @include btn-large;
    @include btn-red;
    }


    {
    @include btn;
    @include btn-small;
    @include btn-black;
    }









    [type="submit"]






    [type="button"]

    View Slide


  73. .btn







    .btn-large





    .btn-small





    .btn-red





    .btn-black


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }
















    [type="button"]









    [type="submit"]
    extends










    {
    @extend .btn;
    @extend .btn-large;
    @extend .btn-red;
    }


    {
    @extend .btn;
    @extend .btn-small;
    @extend .btn-black;
    }

    View Slide


  74. .btn







    .btn-large





    .btn-small





    .btn-red





    .btn-black


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }
















    [type="button"]









    [type="submit"]
    extends










    {
    @extend .btn;
    @extend .btn-large;
    @extend .btn-red;
    }


    {
    @extend .btn;
    @extend .btn-small;
    @extend .btn-black;
    }

    , [type="submit"], [type="button"]







    , [type="submit"]





    , [type="button"]





    , [type="submit"]





    , [type="button"]

    View Slide


  75. .btn







    .btn-large





    .btn-small





    .btn-red





    .btn-black


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }
















    [type="button"]









    [type="submit"]
    extends










    {
    @extend .btn;
    @extend .btn-large;
    @extend .btn-red;
    }


    {
    @extend .btn;
    @extend .btn-small;
    @extend .btn-black;
    }

    , [type="submit"], [type="button"]







    , [type="submit"]





    , [type="button"]





    , [type="submit"]





    , [type="button"]
    send order
    change address
    change basket

    View Slide











  76. {
    @extend %btn;
    @extend %btn-large;
    @extend %btn-red;
    }


    {
    @extend %btn;
    @extend %btn-small;
    @extend %btn-black;
    }

    %btn







    %btn-large





    %btn-small





    %btn-red





    %btn-black


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }
















    [type="button"]









    [type="submit"]









    [type="submit"]
    placeholders

    View Slide



  77. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    [type="submit"], [type="button"]







    [type="submit"]





    [type="button"]





    [type="submit"]





    [type="button"]










    {
    @extend %btn;
    @extend %btn-large;
    @extend %btn-red;
    }


    {
    @extend %btn;
    @extend %btn-small;
    @extend %btn-black;
    }
















    [type="button"]









    [type="submit"]









    [type="submit"]
    placeholders

    View Slide



  78. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    [type="submit"], [type="button"]







    [type="submit"]





    [type="button"]





    [type="submit"]





    [type="button"]










    {
    @extend %btn;
    @extend %btn-large;
    @extend %btn-red;
    }


    {
    @extend %btn;
    @extend %btn-small;
    @extend %btn-black;
    }
















    [type="button"]









    [type="submit"]









    [type="submit"]
    placeholders

    View Slide



  79. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    %btn







    %btn-large





    %btn-small





    %btn-red





    %btn-black






















    Markup CSS
    Sass

    View Slide


  80. %btn







    %btn-large





    %btn-small





    %btn-red





    %btn-black























    #page-other [type="submit"]
    {
    @extend %btn;
    @extend %btn-small;
    @extend %btn-red;
    }










    {
    @extend %btn;
    @extend %btn-large;
    @extend %btn-red;
    }


    {
    @extend %btn;
    @extend %btn-small;
    @extend %btn-black;
    }









    #page-checkout






    #page-checkout


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }









    [type="submit"]






    [type="button"]

    View Slide

  81. SEND ORDER CHANGE ADDRESS
    send order
    change address
    change basket
    CHANGE BASKET

    View Slide









  82. #ctrl-send-order






    #ctrl-change-address,
    #ctrl-change-basket









    {
    @extend %btn;
    @extend %btn-large;
    @extend %btn-red;
    }



    {
    @extend %btn;
    @extend %btn-small;
    @extend %btn-black;
    }


    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    %btn







    %btn-large





    %btn-small





    %btn-red





    %btn-black

    View Slide


  83. @mixin btn
    {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }

    %btn
    {
    @include btn;
    }


    @mixin %btn-large
    {
    padding: 0.375em;
    font-size: 1.25rem;
    }

    %btn-large
    {
    @include btn-large;
    }


    mixins and extends

    View Slide

  84. View Slide

  85. View Slide

  86. nesting
    modularization
    mixins
    extends
    placeholders
    OOSass

    View Slide

  87. View Slide

  88. PRESENTATIONAL
    MARKUP

    View Slide

  89. Structure
    (HTML/DOM)
    Presentation
    (CSS)
    Behavior
    (JavaScript)
    Separation of concerns

    View Slide



  90. {
    min-width: 8rem;
    font-family: "League Gothic";
    text-align: center;
    border-radius: 0.375em;
    }


    {
    padding: 0.375em;
    font-size: 1.25rem;
    }


    {
    padding: 0.25em
    font-size: 1rem;
    }


    {
    background-color: hsl(2, 42%, 39%);
    background-image: linear-gradient(…);
    }


    {
    background-color: hsl(0, 0%, 20%);
    background-image: linear-gradient(…);
    }

    btn







    btn-large





    btn-small





    btn-red





    btn-black






















    Markup Stylesheet

    View Slide

  91. View Slide

  92. WHICH SIDE
    ARE YOU ON?

    View Slide

  93. View Slide