CSS preprocessors for the best of both worlds

A presentation at From The Front and the Temple of DOM in September 2014 in Bologna, Metropolitan City of Bologna, Italy by Gunnar Bittersmann

Slide 1

Slide 1

CSS PREPROCESSORS OF BOTH WORLDS

Slide 2

Slide 2

CSS PREPROCESSORS

Slide 3

Slide 3

OF BOTH WORLDS

Slide 4

Slide 4

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

Slide 5

Slide 5

<html id=”page-products”> <ul class=”product-list”> <li class=”product-item”> <img class=”product-image” src=”…” alt=”…”/> <span class=”product-brand”>…</span> <span class=”product-model”>…</span> <span class=”product-description”>…</span> <span class=”product-price”>…</span> <button class=”btn btn-cta”>Pick me!</button> </li> ⁝ </ul>

Slide 6

Slide 6

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

Slide 7

Slide 7

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

Slide 8

Slide 8

<html id=”page-checkout”> <ul class=”checkout-list”> <li class=”checkout-item”> <img class=”checkout-image” src=”…” alt=”…”/> <span class=”checkout-brand”>…</span> <span class=”checkout-model”>…</span> <span class=”checkout-description”>…</span> <span class=”checkout-price”>…</span> </li> ⁝ </ul>

Slide 9

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 { … }

Slide 10

Slide 10

<html id=”page-products”> <ul class=”product-list”> <li> <img class=”product-image” src=”…” alt=”…”/> <span class=”brand”>…</span> <span class=”model”>…</span> <span class=”description”>…</span> <span class=”price”>…</span> <button>Pick me!</button> </li> ⁝ </ul>

Slide 11

Slide 11

<html id=”page-checkout”> <ul class=”product-list”> <li> <img class=”product-image” src=”…” alt=”…”/> <span class=”brand”>…</span> <span class=”model”>…</span> <span class=”description”>…</span> <span class=”price”>…</span> </li> ⁝ </ul>

Slide 12

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 { … }

Slide 13

Slide 13

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

Slide 14

Slide 14

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

Slide 15

Slide 15

@import “_page-products”; @import “_page-checkout”; ⁝ modularization

Slide 16

Slide 16

@import “_colors”; @import “_type”; @import “_image-replacement”; @import “_page-layout”; @import “_page-products”; @import “_page-checkout”; ⁝ modularization

Slide 17

Slide 17

Atomic design (Brad Frost)

Slide 18

Slide 18

Atomic design (Brad Frost) ATOMS MOLECULES ORGANISMS TEMPLATES PAGES

Slide 19

Slide 19

Look ma, no classes!

Slide 20

Slide 20

<html id=”page-products” vocab=”http://schema.org/”> <ul class=”product-list”> <li typeof=”Product”> <img property=”image” src=”…” alt=”…”/> <span property=”name”>…</span> <span property=”brand”>…</span> <span property=”model”>…</span> </span> <span property=”description”>…</span> <span property=”offers” typeof=”Offer”> <span class=”price”>…</span> <link property=”availability” href=”http://schema.org/InStock”/> </span> <button>Pick me!</button> </li> ⁝ </ul>

Slide 21

Slide 21

#page-products { ⁝ .product-list { ⁝ li { … } [property=”image”] { … } [property=”brand”] { … } [property=”model”] { … } [property=”description”] { … } [property=”price”] { … } button { … } } }

Slide 22

Slide 22

Slide 23

Slide 23

One more cup of coffee, please! <html lang=”en”> <h1>One more cup of coffee, please!</h1>

Slide 24

Slide 24

ONE MORE CUP OF COFFEE, PLEASE! <html lang=”en”> <h1 class=”uppercase”>One more cup of coffee, please!</h1> .uppercase { text-transform: uppercase }

Slide 25

Slide 25

one more cup of coffee, please! <html lang=”en”> <h1 class=”lowercase”>One more cup of coffee, please!</h1> .uppercase { text-transform: uppercase } .lowercase { text-transform: lowercase }

Slide 26

Slide 26

UN’ ALTRA TAZZA DI CAFFÈ, PER FAVORE! <html lang=”it”> <h1 class=”uppercase”>Un’ altra tazza di caffè, per favore!</h1> .uppercase { text-transform: uppercase } .lowercase { text-transform: lowercase }

Slide 27

Slide 27

un’ altra tazza di caffè, per favore! <html lang=”it”> <h1 class=”lowercase”>Un’ altra tazza di caffè, per favore!</h1> .uppercase { text-transform: uppercase } .lowercase { text-transform: lowercase }

Slide 28

Slide 28

NOCH EIN TÄSSCHEN KAFFEE, BITTE! <html lang=”de”> <h1 class=”uppercase”>Noch ein Tässchen Kaffee, bitte!</h1> .uppercase { text-transform: uppercase } .lowercase { text-transform: lowercase }

Slide 29

Slide 29

noch ein tässchen kaffee, bitte! <html lang=”de”> <h1 class=”lowercase”>Noch ein Tässchen Kaffee, bitte!</h1> .uppercase { text-transform: uppercase } .lowercase { text-transform: lowercase }

Slide 30

Slide 30

Noch ein Tässchen Kaffee, bitte! <html lang=”de”> <h1 class=”lowercase”>Noch ein Tässchen Kaffee, bitte!</h1> .uppercase { text-transform: uppercase } .lowercase { text-transform: lowercase } .lowercase:lang(de) { text-transform: none } ✘  

Slide 31

Slide 31

PRESENTATIONAL MARKUP

Slide 32

Slide 32

Noch ein Tässchen Kaffee, bitte! <html lang=”de”> <h1>Noch ein Tässchen Kaffee, bitte!</h1> h1 { text-transform: lowercase } h1:lang(de) { text-transform: none } ✔  

Slide 33

Slide 33

QA’VIN LATLH TU’LUM HINOBNES! <html lang=”tlh”> <h1>qa’vIn latlh tu’lum HInobneS!</h1> h1 { text-transform: uppercase }

Slide 34

Slide 34

qa’vin latlh tu’lum hinobnes! <html lang=”tlh”> <h1>qa’vIn latlh tu’lum HInobneS!</h1> h1 { text-transform: lowercase }

Slide 35

Slide 35

qa’vIn latlh tu’lum HInobneS! <html lang=”tlh”> <h1>qa’vIn latlh tu’lum HInobneS!</h1> h1 { text-transform: lowercase } :lang(tlh) { text-transform: none !important} ✔  

Slide 36

Slide 36

<div id=”pick-me” class=”hidden”> .hidden { display: none }

Slide 37

Slide 37

<div id=”pick-me” class=”hidden”> .hidden { display: none !important }

Slide 38

Slide 38

<div id=”pick-me” class=”hidden”> .hidden { display: none !important } $(‘#pick-me’).show(); document.querySelector(‘#pick-me’).style.display = ‘block’;

Slide 39

Slide 39

<div id=”pick-me” class=”hidden”> .hidden { display: none !important } $(‘#pick-me’).show(); document.querySelector(‘#pick-me’).style.display = ‘block’;

Slide 40

Slide 40

<div id=”pick-me” class=”hidden”> .hidden { display: none !important } $(‘#pick-me’).removeClass(‘hidden’); document.querySelector(‘#pick-me’).classList.remove(‘hidden’);

Slide 41

Slide 41

<div id=”pick-me” hidden> $(‘#pick-me’).removeAttr(‘hidden’); document.querySelector(‘#pick-me’).removeAttribute(‘hidden’);

Slide 42

Slide 42

<div id=”pick-me” hidden> [hidden] { display: none !important } $(‘#pick-me’).removeAttr(‘hidden’); document.querySelector(‘#pick-me’).removeAttribute(‘hidden’);

Slide 43

Slide 43

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

Slide 44

Slide 44

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

Slide 45

Slide 45

SEND ORDER CHANGE ADDRESS OOCSS CHANGE BASKET <button type=”submit” class=”btn btn-large btn-red”>send order</button> <button type=”button” class=”btn btn-small btn-black”>change address</button> <button type=”button” class=”btn btn-small btn-black”>change basket</button>

Slide 46

Slide 46

SEND ORDER CHANGE ADDRESS CHANGE BASKET <button type=”submit” class=”btn btn-large btn-red”>send order</button> <button type=”button” class=”btn btn-small btn-black”>change address</button> <button type=”button” class=”btn btn-small btn-black”>change basket</button>

Slide 47

Slide 47

Stylesheet .btn { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } .btn-large { padding: 0.375em; font-size: 1.25rem; } OOCSS .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(…); }

Slide 48

Slide 48

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 OOCSS 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

Slide 49

Slide 49

Markup { class attribute btn class selector } <button> “CSS classes” { btn-large } OOCSS <button> { btn-small <button> } { btn-red } { btn-black } Stylesheet 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(…);

Slide 50

Slide 50

Markup { class attribute btn class selector } <button> “CSS classes” { btn-large } OOCSS <button> { btn-small <button> } { btn-red } { btn-black } Stylesheet 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(…);

Slide 51

Slide 51

PRESENTATIONAL MARKUP

Slide 52

Slide 52

Slide 53

Slide 53

Slide 54

Slide 54

OOCSS

Slide 55

Slide 55

“CSS CLASSES”

Slide 56

Slide 56

Slide 57

Slide 57

Slide 58

Slide 58

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 OOCSS 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

Slide 59

Slide 59

Slide 60

Slide 60

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

Slide 61

Slide 61

Slide 62

Slide 62

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

Slide 63

Slide 63

Slide 64

Slide 64

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

Slide 65

Slide 65

Slide 66

Slide 66

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

Slide 67

Slide 67

Markup { btn } <button> { btn-large } OOCSS <button> { btn-small <button> } { btn-red } { btn-black } Stylesheet 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(…);

Slide 68

Slide 68

Markup btn Stylesheet { } <button> { btn-large } <button> { btn-small } <button> { 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(…);

Slide 69

Slide 69

Markup btn Stylesheet { } <button> { btn-large } <button> { btn-small } <button> { 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(…);

Slide 70

Slide 70

mixins [type=”submit”] { } @include btn; @include btn-large; @include btn-red; [type=”button”] { } @include btn; @include btn-small; @include btn-black; @mixin btn { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } @mixin btn-large { padding: 0.375em; font-size: 1.25rem; } @mixin btn-small { padding: 0.25em font-size: 1rem; } @mixin btn-red { background-color: hsl(2, 42%, 39%); background-image: linear-gradient(…); } @mixin btn-black { background-color: hsl(0, 0%, 20%); background-image: linear-gradient(…); }

Slide 71

Slide 71

mixins [type=”submit”] { } @include btn; @include btn-large; @include btn-red; [type=”button”] { } @include btn; @include btn-small; @include btn-black; <button type=”submit”>send order</button> <button type=”button”>change address</button> <button type=”button”>change basket</button> @mixin btn { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } @mixin btn-large { padding: 0.375em; font-size: 1.25rem; } @mixin btn-small { padding: 0.25em font-size: 1rem; } @mixin btn-red { background-color: hsl(2, 42%, 39%); background-image: linear-gradient(…); } @mixin btn-black { background-color: hsl(0, 0%, 20%); background-image: linear-gradient(…); }

Slide 72

Slide 72

[type=”submit”] { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; [type=”submit”] { } @include btn; @include btn-large; @include btn-red; [type=”button”] { } @include btn; @include btn-small; @include btn-black; 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(…);

Slide 73

Slide 73

extends [type=”submit”] { @extend .btn; @extend .btn-large; @extend .btn-red; } [type=”button”] { @extend .btn; @extend .btn-small; @extend .btn-black; } .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(…); }

Slide 74

Slide 74

extends [type=”submit”] { @extend .btn; @extend .btn-large; @extend .btn-red; } [type=”button”] { @extend .btn; @extend .btn-small; @extend .btn-black; } .btn, [type=”submit”], [type=”button”] { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } .btn-large, [type=”submit”] { padding: 0.375em; font-size: 1.25rem; } .btn-small, [type=”button”] { padding: 0.25em font-size: 1rem; } .btn-red, [type=”submit”] { background-color: hsl(2, 42%, 39%); background-image: linear-gradient(…); } .btn-black, [type=”button”] { background-color: hsl(0, 0%, 20%); background-image: linear-gradient(…); }

Slide 75

Slide 75

extends [type=”submit”] { @extend .btn; @extend .btn-large; @extend .btn-red; } [type=”button”] { @extend .btn; @extend .btn-small; @extend .btn-black; } <button type=”submit”>send order</button> <button type=”button”>change address</button> <button type=”button”>change basket</button> .btn, [type=”submit”], [type=”button”] { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } .btn-large, [type=”submit”] { padding: 0.375em; font-size: 1.25rem; } .btn-small, [type=”button”] { padding: 0.25em font-size: 1rem; } .btn-red, [type=”submit”] { background-color: hsl(2, 42%, 39%); background-image: linear-gradient(…); } .btn-black, [type=”button”] { background-color: hsl(0, 0%, 20%); background-image: linear-gradient(…); }

Slide 76

Slide 76

placeholders [type=”submit”] { @extend %btn; @extend %btn-large; @extend %btn-red; } [type=”button”] { @extend %btn; @extend %btn-small; @extend %btn-black; } %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(…); }

Slide 77

Slide 77

placeholders [type=”submit”] { @extend %btn; @extend %btn-large; @extend %btn-red; } [type=”button”] { @extend %btn; @extend %btn-small; @extend %btn-black; } [type=”submit”], [type=”button”] { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } [type=”submit”] { padding: 0.375em; font-size: 1.25rem; } [type=”button”] { padding: 0.25em font-size: 1rem; } [type=”submit”] { background-color: hsl(2, 42%, 39%); background-image: linear-gradient(…); } [type=”button”] { background-color: hsl(0, 0%, 20%); background-image: linear-gradient(…); }

Slide 78

Slide 78

placeholders [type=”submit”] { @extend %btn; @extend %btn-large; @extend %btn-red; } [type=”button”] { @extend %btn; @extend %btn-small; @extend %btn-black; } [type=”submit”], [type=”button”] { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } [type=”submit”] { padding: 0.375em; font-size: 1.25rem; } [type=”button”] { padding: 0.25em font-size: 1rem; } [type=”submit”] { background-color: hsl(2, 42%, 39%); background-image: linear-gradient(…); } [type=”button”] { background-color: hsl(0, 0%, 20%); background-image: linear-gradient(…); }

Slide 79

Slide 79

Markup Sass { %btn } <button> { %btn-large } <button> { %btn-small } <button> { %btn-red } { %btn-black } min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; CSS 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(…);

Slide 80

Slide 80

%btn { min-width: 8rem; font-family: “League Gothic”; text-align: center; border-radius: 0.375em; } #page-checkout [type=”submit”] { @extend %btn; @extend %btn-large; @extend %btn-red; } #page-checkout [type=”button”] { @extend %btn; @extend %btn-small; @extend %btn-black; } #page-other [type=”submit”] { @extend %btn; @extend %btn-small; @extend %btn-red; } %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(…); }

Slide 81

Slide 81

SEND ORDER CHANGE ADDRESS CHANGE BASKET <button type=”submit” id=”ctrl-send-order”>send order</button> <button type=”button” id=”ctrl-change-address”>change address</button> <button type=”button” id=”ctrl-change-basket”>change basket</button>

Slide 82

Slide 82

#ctrl-send-order { @extend %btn; @extend %btn-large; @extend %btn-red; } #ctrl-change-address, #ctrl-change-basket { @extend %btn; @extend %btn-small; @extend %btn-black; } %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(…); }

Slide 83

Slide 83

mixins and extends @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; } ⁝

Slide 84

Slide 84

Slide 85

Slide 85

Slide 86

Slide 86

OOSass nesting modularization mixins extends placeholders

Slide 87

Slide 87

Slide 88

Slide 88

PRESENTATIONAL MARKUP

Slide 89

Slide 89

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

Slide 90

Slide 90

Markup btn Stylesheet { } <button> { btn-large } <button> { btn-small } <button> { 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(…);

Slide 91

Slide 91

Slide 92

Slide 92

WHICH SIDE ARE YOU ON?

Slide 93

Slide 93