CSS PREPROCESSORS OF BOTH WORLDS

CSS PREPROCESSORS

OF BOTH WORLDS

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

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

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

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

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

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

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

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

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

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

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

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

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

Atomic design (Brad Frost)

Atomic design (Brad Frost) ATOMS MOLECULES ORGANISMS TEMPLATES PAGES

Look ma, no classes!

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

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

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

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

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 }

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 }

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 }

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 }

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 }

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 } ✘  

PRESENTATIONAL MARKUP

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 } ✔  

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

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

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} ✔  

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

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

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

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

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

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

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

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

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

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>

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>

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(…); }

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

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(…);

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(…);

PRESENTATIONAL MARKUP

OOCSS

“CSS CLASSES”

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

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

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

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

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

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(…);

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(…);

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(…);

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(…); }

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(…); }

[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(…);

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(…); }

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(…); }

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(…); }

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(…); }

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(…); }

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(…); }

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(…);

%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(…); }

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>

#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(…); }

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; } ⁝

OOSass nesting modularization mixins extends placeholders

PRESENTATIONAL MARKUP

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

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(…);

WHICH SIDE ARE YOU ON?