20. jan 2009
CSS-spesifisitet. Hvordan fungerer det?
Tema: Webrelatert Stikkord: CSS, Spesifisitet, Webdesign, XHTML
Innlegg med samme stikkord
Har du noen gang irritert deg grønn over at stilreglene du prøver å gi et element ikke vil fungere? Og har du erfart at dette problemer øker i takt med lengden på stilarket? Eller er du en av dem som løser alt dette med !Important? Vel, da bør du lese videre. Jeg inviterer deg også til å komme med din forståelse av hvordan spesifisitet fungerer.
CSS står for Cascading Style Sheets. Delen Style Sheets er jo forståelig nok, men tenker du over hva Cascading betyr? En kjapp kikk i ordboken viser at Cascade er et substantiv og betyr liten foss, eller kanskje mer korrekt kaskade. Kaskade igjen er en kunstig oppbygd foss eller vannfall i trinn. Cascading vil da være vannet som trinnvis fosser nedover i denne kaskaden. Det samme prinsippet gjelder for stilregler. Hvilket trinn stilregelen er plassert på — eller rettere sagt hvor høy spesifisitet stilregelen har — har betydning for om den i det hele tatt har effekt. Hvor høy spesifisitet en stilregel har, finner man ut om man er klar over det hierarkiske systemet som råder i CSS. En kan også tildels finne det ut med enkel matematikk, men mer om det senere.
Et brutalt, men rettferdig hierarki
Når man skriver CSS må man altså ta hensyn til et bestemt hierarki. Hierarkiet er grovt sett som følger:
- Stilregler som er skrevet direkte i html-tagger har høyest spesifisitet. Eks: <p style=”color: #999;”>….</p>
- Stilregler med ID’er kommer på andreplass Eks: #menyfelt {}
- Tredjeplass går til klasser, attributter og pseudoklasser Eks: a:hover {}
- Fjerdeplass går til elementer og pseudoelementer Eks: h1 {}
- Om to stilregler i et stilark har samme spesifisitet, vil stilregelen som er skrevet sist gjelde.
Så har man altså også !important som vil overskrive alle disse, og kanskje burde vært plassert på førsteplass, men !important er ikke ment som et designhjelpemiddel, og derfor unngår jeg bruken av denne i størst mulig grad. !important kan derimot fungere som en midlertidig test mot en stilregel for å se om det er spesifisitetsproblemer som gjør at den ikke trer i kraft.
Et par andre viktige faktorer å være klar over:
Om en har både et internt og et eksternt stilark, vil stilarket som er nevnt sist gjelde dersom to stilregler har lik spesifisitet.
Eksempel:
<head> <title>Tittel</title> <link href="url til stilark" /> <style type="text/css"> <!-- stilregler her } --> </style> </head>
Her vil det interne stilarket ha førsterett om det oppstår konflikter (les: to stilregler med samme spesifisitet). Om linkingen til det eksterne stilarket derimot er plassert under det interne stilarket — altså under </style> — vil det eksterne stilarket har førsterett om det oppstår konflikter.
En matematisk veiledning
Så over til matematikken. Det er viktig å være klar over at verdiene jeg viser til i listen nedenfor, bare er en veiledning og ikke noe absolutt fasit. Det viktigste er å huske på hierarkiet. Gjør en det, kan man bruke veiledningen under som en kjapp test dersom noen stilregler ikke vil fungere. Desto høyere verdi, desto høyere spesifisitet.
- ID’er har en verdi på 100. Eks: #menyfelt {}
- Attributter, klasser og pseudoklasser har en verdi på 10. Eks: a:hover {}
- Elementer og pseudoelementer har en verdi på 1. Eks: h1 {}
Husk; hierarkiet er det viktigste. Det vil si at en samling av klasser som skulle få en tallverdi høyere enn en ID, likevel ikke vil overstyre ID’en.
Eksempel på utregning:
#menyfelt .menyelementer a:hover {}
#menyfelt (en ID = 100) + .menyelementer (en klasse = 10) + a (et element = 1) + :hover (en pseudoklasse = 10)
100+10+1+10 = 121.
Eksempel på hvordan man kan bruke dette:
HTML:
<div id="ramme"> <div id="toppfelt"></div> <div id="innholdsfelt"> <h1 class="viktig">Overskrift h1</h1> <p>Brødtekst</p> <h2>Overskrift h2</h2> <p>brødtekst</p> </div> <div id="bunnfelt"></div> </div>
CSS:
#ramme #innholdsfelt h1, #ramme #innholdsfelt h2 {
color: #0000ff; /*Blå farge*/
}
#innholdsfelt h1.viktig {
color: #ff0000; /*Rød farge*/
}
Det som vil skje her, er at begge overskriftene blir blå, selv om jeg har lagt på en klasse til <h1> som sier at den er viktig og skal være rød, og selv om denne stilregelen kommer sist i stilarket. Grunnen er enkel og grei at den første stilregelen har en høyere verdi/spesifisitet enn den andre. Den første stilregelen har en verdi på 201, den andre har en verdi på 111.
Om vi utvider den siste stilregelen litt og skriver den slik:
#ramme #innholdsfelt h1.viktig {
color: #ff0000;
}
..da har den plutselig en verdi på 211, og vil dermed tre i kraft og gjøre <h1 class=”viktig”> rød. Jeg kunne også løst dette med å heller bare putte en !important bak fargekoden, men som jeg nevnte tidligere i innlegget, så unngår jeg bruken av denne i størst mulig grad.
Med disse retningslinjene å forholde meg til, klarer jeg som regel raskt å feilsøke i stilarkene mine. Om en er bevisst på hierarkiet så kan man bygge gode og forutsigbare stilark.
Er det noe du savner, eller mener er feil i dette innlegget? Eller har du kanskje en bedre måte å finne ut av spesifisiteten? Si gjerne ifra.
Innlegg med samme stikkord


11 kommentarer til “CSS-spesifisitet. Hvordan fungerer det?”
Tusen takk for denne veiledningen! Jeg hadde nesten gitt opp å finne ut hvorfor enkelte CSS-koder ikke virker som jeg vil. Nå kan jeg gjøre et nytt forsøk på å finne det ut. Flottings!
Håper du finner ut av det nå. Det hadde vært artig om du ga en liten lyd om veiledningen faktisk hjalp.
Det skal jeg gjøre!
Genialt. Har vist lenge at plaseringen har mye å si men har liksom aldri orket å undersøke så alt for mye på akkurat det der. Denne guiden kan komme til god nytte neste gang jeg sitter fast i CSS’en.
En lettere (på vondt og godt) forklaring er som følger:
Nærhet er alt. Nærmest er sterkest. Men det er ikke styrke, det er allsidighet du ønsker.
Elementer som ligger i HTML-dokumentet, i html-elementene (f.eks. ) går foran elementer som ligger i . Regler som ligger i header går foran eksterne egne css-filer.
Reglene leses ovenifra, så regler som ligger i toppen av et css dokument likker “lengre vekk” enn regler som ligger i bunnen av dokumentet, da css-filen leses før html’n.
id (#) går foran klasser (.) som går foran generelle typer (h1).
IDer skal være unike (max 1 pr html-side), klasser kan brukes mange ganger, “typer” er bare et ord jeg putta inn her for html-elementer. Du treger mange av disse også :).
Det er ikke styrke men allsidighet du ønsker.
Du vil ikke ha “sterke” regler, du vil ha gjenbrukbare allsidige regler. Når du legger til mer informasjon på siden, så skal dette ikke trenge spesiell tilpassing i css.
Regler av typen #MedId div.MedKlasse h1.MedKlasse vil bare gjelde et ytterst spesielt utvalg elementer (h1-elementer av klassen .MedKlasse som ligger inne en div med klassen .MedKlasse som ligger inni et element med id=”MedId”. Vi kan si at lange statments (#div #div .klasse element {/*ting:her;*/}) nøster seg nærmere elementet. Og nærmere er sterkere.
Bare h1 {/*ting:sak;*/} vil gjelde alle h1-elementer så lenge det ikke finnes noen sterkere (nærmere) regler.
PS: !important betyr “drit i ting som kommer etter dette, dette er viktig(st). Du kunne med andre ord bare lagt den viktigste stilen nærmer html-elementet du vil style. !important kan sees på som en magnet som trekker stilen nærmere (og forbi) andre stiler som krangler om å komme nærmest. Brukes så lite som mulig.
Som samfunnsviter og ikke naturviter, fungerer dette bilde bedre for meg. Avstand er lettere enn tall.
Fin forklaring Eirik! Er helt enig i at det ikke nødvendigvis er styrke en ønsker når det gjelder css-regler. Alsidighet er selvsagt et mål. Men noen ganger ønsker en jo å lage stilregler til en spesifikk del av websiden, og da hjelper det ofte - ihvertfall for meg - å tenke styrke. Spesielt ettersom jeg alltid bruker eksterne stilark (holder meg altså langt unna stilregler direkte på html-tagger, selv om en nøster seg nærmere elementet på den måten. Jeg liker heller ikke å lage interne stilark innenfor head-taggen).
Du skriver: “Regler som ligger i header går foran eksterne egne css-filer.”
Akkurat der tror jeg du bommer litt. Om du plasserer linken til det eksterne stilarket under det interne stilarket (alt innenfor head-taggen så klart), så vil det eksterne stilarket ha førsterett om to stilregler har samme spesifisitet. Men som regel plasserer folk linkene til de eksterne stilarkene over det interne stilarket, og dermed vil jo det interne stilarket være nærmere enn det eksterne.
“Om du plasserer linken til det eksterne stilarket under det interne stilarket (alt innenfor head-taggen så klart), så vil det eksterne stilarket ha førsterett om to stilregler har samme spesifisitet.”
det har du rett i. Det er mulig jeg alltid har lagt til eksterne stilark først. Det er det forresten god grunn til, som du sier:
Det er best å ha stilene i eksterne filer. Alt annet blir unntakhåndtering.. ..som igjen er noe som børe minimeres.
Hei igjen!
Jeg tok omsider tak i dette i dag. Og nå klarte jeg å fikse stilene slik jeg ville ha det. Oppdaget at jeg hadde glemt å tilføye “class” i en img-tag, en class hvor border er satt til 0. I tillegg fikk jeg laget større avstand mellom hvert avsnitt i blogginnlegg (.post p), uten at det innvirket på avsnittene i sidebaren!
Denne veiledningen hjalp meg til å forstå noen prinsipper, så takk igjen
Ellers lurer jeg på hva pseudoklasser og pseudoelementer er. Har du et par eksempler?
Kjempeflott! Det skal ikke store glippen til i css’en før det kan ha store innvirkninger på layouten.
En pseudoklasse kan foreksempel være :hover. Oftes brukt i kombinasjon med a —> a:hover. Et annet eksempel er :first-child. Om du bruker :first-child i kombinasjon med p —> p:first-child, så kan du spesifisere hvilke egenskaper den første paragrafen i et gitt område skal ha. Foreksempel den første paragrafen til hvert blogginnlegg:
.bloggpost p:first-child {stilregler her}
Med denne kan du altså gi den første paragrafen/avsnittet et annet utseende enn resten av teksten. Praktisk dersom du alltid har med en ingress som du ønsker å gjøre uthevet el.
Et pseudoelement er enda mer avgrenset. Et eksempel på et pseudoelement er :first-letter. Om du bruker den i kombinasjon med p —> p:first-letter, så kan du spesifisere stilregler til den første bokstaven i paragrafen/avsnittet. Eksempel:
p:first-letter {
font-size: 2em;
color: #ff0000;
}
Her vil første bokstav i hver paragraf/avsnitt bli rød og 2em stor.
Pseudoklasser påvirker altså hele elementet, mens pseudoelementer påvirker en spesifikk del av elementet.
Aha, jeg skjønner. Takk for svar!
Det er så mye spennende å lære. Jeg likte den der p:first-child, som styrer det første avsnittet. Veldig praktisk.
p:first-letter har jeg faktisk vært borti. Jeg brukte tidligere
p.begynn:first-letter {
float:left;
font-size:40px;
osv..
}
og startet det første avsnittet med å skrive p class=”begynn”, slik at innlegget fikk en svær bokstav i starten. Litt kult
Websider som linker til dette innlegget