On Github mollerse / cssplt2
Hei, jeg heter Stian og jeg skal gi dere et skråblikk på CSS fra en programmeringsteoretisk synsvinkel.
Vi sier ofte at CSS ikke er et programmeringspråk, men likevel bruker vi det til å løse den samme typen problemer som vi bruker programmeringspråk til. Derfor er det nyttig å se på mekanismene i CSS på et mer teoretisk nivå og se hva vi kan ta med oss av lærdom fra programmeringspråk.
Hoved temaet i dag er komposisjon. Den kanskje mest fundamentale delen av programmering
I dag skal vi se litt på komposisjon. Den kanskje mest fundamentale delen av programmering som går igjen på tvers av alle programmeringspråk.
Komposisjon er å sette sammen løsninger på enklere delproblemer for å løse et mer komplekst problem.
Hovedtemaet i dag er komposisjon. Den kanskje mest fundamentale delen av programmering slik vi kjenner det. Komposisjon danner grunnlaget for det arbeidet vi gjør som utviklere. Muligheten til å kunne bryte ned komplekse problemer og bygge på tidligere løste problemer er helt essensiell. Uten denne muligheten er det ikke vært mulig å angripe problemer uten å til en hver tid ta inn over seg hele kompleksiteten til problemet. Dette er noe vi vet ikke skalerer særlig bra når kompleksiteten eller omfanget til et problem blir stort.
y = x * x + 1
function f(x) { return x + 1; } function g(x) { return x * x; }
var y = f(g(2)); //=> 5
Komposisjon i sin mest grunnleggende form stammer fra matematikken og måten komplekse regnestykker kan brytes opp og løses hver for seg før den endelige løsningen presenterer seg ved å sette sammen delløsningene.
.btn { color: red; background: silver; display: inline-block; }
.sidebar .btn { color: black; background: red; }
<div class="sidebar"> <button class="btn">Pressme</button> </div>
Selv om vi ofte ikke ser på CSS som et programmeringspråk så angriper vi ofte problemene vi blir møtt med ved å benytte taktikker vi kjenner godt fra andre kontekster.
Her har vi laget oss en løsning på hvordan buttons skal se ut. Og så lager vi oss en løsning på et spesialtilfelle av buttons som eksisterer i sidebars ved å bygge på løsningen for generelle buttons.
Så kan vi benytte oss av den løsningen på denne biten med markup. Dette er en ganske vanlig måte å angripe CSS-problemer på.
.sidebar .header { font-weight: 700; text-decoration: underline; } .news-item h2 { color: blue; }
<div class="sidebar"> <h1 class="header">Sidebar</h1> <div class="news-item"> <h2 class="header">News</h2> <p>There were news.</p> </div> </div>
Vi ser på et litt mer komplekst eksempel. Dette er en ganske uskyldig bit med CSS. Vi ønsker oss feite headers med understreker. Og i sidebars ønsker vi oss blå h2er.
Når vi anvender disse css-reglene på markup som ser slik ut får vi et resultat som kanskje ikke var helt tiltenkt. Den innerste h2'en i news-item-div'en har fått det samme utseende som den ytterste headeren.
Dette er ikke et helt uvanlig problem i CSS. En del av markupen gir match på to ulike CSS-regler og vi får en uønsket effekt ved at stilene fra begge reglene blir satt på elementet. Vi har nå komponert to løsninger fra CSS, uten å egentlig mene det!
Vi trenger å kontrollere effekten av en CSS-regel.
Vi ønsker ikke at stilene fra den første regelen skal påvirke effekten av den andre regelen. Det vi trenger er en måte å kontrollere effekten når vi komponerer løsninger ved å løse delproblemer.
Hadde CSS vært som andre programmeringspråk hadde vi kunnet begrense scopet til en av reglene. Vi kunne sagt at denne regelen kun gjelder for denne avgrensa biten med markup, men den muligheten har vi ikke per i dag.
.sidebar .header { font-weight: 700; text-decoration: underline; } .news-item h2 { font-weight: normal; text-decoration: none; color: blue; }
Alle CSS-regler eksisterer i praksis i samme namespace, og i en ytterste konsekvens er effekten av en CSS-regel avhengig av alle de andre CSS-reglene som er definert på en side. I dette eksempelet ser vi effekten av dette, da regelen for h2er i news-items blir påvirket av en annen regel.
Vi kan fikse dette ved å være eksplisitte med stilene vi ønsker å sette, men dette vil fortsatt ikke gi oss den effekten vi ønsker.
.sidebar .header { font-weight: 700; text-decoration: underline; } .news-item .header { font-weight: normal; text-decoration: none; color: blue; }
Vi er nødt til å benytte oss av den mekanismen vi faktisk har for å kontrollere effekten av komposisjon, som er spesifisitet. Vi kan kaste så mange preprosessorer på CSS som vi vil, men denne fundamentale egenskapen vil ikke endre seg.
Dette eksempelet er konstruert, men det illustrerer en viktig egenskap med CSS. Vi kan ikke løse problemer med CSS ved å angripe problemet med de samme teknikkene som fungerer i andre programmeringspråk.
Den fundamentale forutsetningen for at komposisjon skal fungere som strategi for problemløsning er ikke oppfylt av CSS. Vi kan ikke dele opp et problem i mindre problemer uten å alltid ha hele problemet i hodet til en hver tid. Jo mer kompleks problemet er jo vanskligere blir det å holde i hodet. Hvis vi angriper problemer i CSS uten å erkjenne de faktiske forhold vil vi ikke være istand til å utvikle løsninger effektivt.
Vi har to retninger vi kan velge:
1) Slutte med komposisjon.
2) Eliminere uønskede effekter fra komposisjon.
Er CSS håpløst og helt uegna til å løse de problemene vi ønsker å løse? Ikke nødvendigvis, men vi er nødt til å angripe problemer på en annen måte. La oss se på to mulige retninger.
Vi kan slutte å komponere CSS regler. Det vil si at vi heller lager regler som kun treffer akkurat de elementene vi ønsker gjennom feks unike eller nesten unike selectorer som inneholder alle attributter som skal settes for det elementet.
Eller vi forsøker å eliminere uønskede effekter ved komposisjon gjennom å begrense effekten av hver regel slik at når flere regler matcher samme element vil ikke reglene påvirke hverandre. Med andre ord, vi har ikke lengre har lov til å overskrive en stil fra en annen regel selv om du har høyere spesifisitet. Tatt til det ekstreme vil dette si at du kun kan sette en attributt per regel.
Vi må jobbe på CSS' premisser.
Det er håp. Vi trenger kanskje ikke å ta noen av de to retningene til sine ekstremer, men vi kan la de danne et grunnlag for hvordan vi vurderer struktureringen av løsninger på komplekse problemer med CSS.
Alt etter hvilken grad av kompleksitet vi er møtt med kan vi ta med oss elementer fra en eller begge retningene og angripe problemene på CSS' premisser. Vi blir i stand til å identifisere når løsningene våre trenger en omstrukturering, fremfor å ofre godt håndtverk. Og vi blir i stand til å vurdere hvorvidt en foreslått løsning vil kunne fungere for problemet vi har.
Når vi forstår hvilke begrensninger CSS har og hvordan de påvirker de løsningene vi lager blir vi i stand til å ta de rette valgene for hvordan vi utformer løsninger.
Stian Veum Møllersen / @mollerse
BEKK