Hoppa till innehållet

Stilmall

filen som innehåller en sidas CSS

Vad det är

En stilmall, på engelska style sheet eller stylesheet och i dagligt tal ofta bara CSS-filen, är en samling CSS-regler som en webbläsare hämtar, tolkar och tillämpar på ett dokument som en enda enhet. I bestämd form heter den stilmallen, och i plural stilmallar.

En sida kan få sina stilmallar på fyra sätt. Ett link-element med rel="stylesheet" pekar på en separat fil. Ett style-element bär regler inuti själva HTML-koden. En @import-regel överst i en stilmall drar in en annan. Och ett skript kan bygga en med new CSSStyleSheet() och koppla den till ett dokument eller en shadow root genom adoptedStyleSheets. De två första ser ut så här i sidans head:

<link rel="stylesheet" href="/css/site.css" />
<link rel="stylesheet" href="/css/print.css" media="print" />
<style>
    .banner {
        border-block-end: 2px solid;
    }
</style>

Författarens stilmallar är inte de enda som spelar in. Varje webbläsare har med sig en standardstilmall, och det är därför en rubrik utan egen stil ändå blir stor och fet, och en läsare kan lägga till en egen användarstilmall. Kaskaden väger de tre ursprungen mot varandra. Attributet style på ett enskilt element är något annat: deklarationer utan selektor, som hör till just det elementet och inte till någon stilmall.

När en stilmall har laddats blir den ett CSSStyleSheet-objekt i CSS Object Model (CSSOM), den specifikation som definitionen av termen här kommer från. Objektet håller reda på elementet som äger stilmallen, vilka medier den gäller för, dess titel, om den är avstängd och dess lista med regler, och document.styleSheets räknar upp en sidas stilmallar i ordning. En flagga finns för integritetens skull: en stilmall som hämtats från ett annat ursprung utan CORS är inte origin-clean, och ett skript som frågar efter dess regler får i stället ett säkerhetsfel.

Attributet media begränsar en stilmall till en viss miljö. En stilmall märkt media="print" laddas fortfarande ned, men webbläsaren väntar bara på stilmallar vars medium matchar, så en stilmall för utskrift håller inte upp visningen på skärmen.

Varför det spelar roll

En stilmall avgör vad en webbläsare måste hämta innan den visar något alls. HTML-standarden behandlar en länk till en stilmall som parsern hittar som renderingsblockerande när dess medium matchar, så den första utritningen väntar tills filen har kommit fram och tolkats, i stället för att rita sidan utan stil och sedan rita om den framför läsaren. Filens storlek, servern den ligger på och de rundresor som krävs för att upptäcka den ligger alla mellan ett klick och det första som läsaren ser.

Antalet filer är det första beslutet. Ett gemensamt paket för alla sidor hämtas en gång och serveras sedan från cachen. En stilmall per sida skickar mindre i början och mer allteftersom läsaren rör sig på webbplatsen. Regler som bäddats in i ett style-element kostar ingen extra förfrågan, men de följer med på nytt med varje sida, eftersom de inte kan cachas skilt från dokumentet som bär dem. Varje @import lägger till en hel rundresa, eftersom webbläsaren får veta den importerade adressen först när den importerande filen har kommit fram.

Cachning är det andra. En stilmall som cachas i ett år gör varje senare sida snabbare, men en ändring måste då nå läsare som har den gamla kopian. Det vanliga svaret är ett filnamn med fingeravtryck, en hash av innehållet i själva namnet, så att en ändrad fil får en ny adress och en gammal kan ligga kvar i cachen hur länge som helst, medan HTML-koden som pekar på den hålls kortlivad.

Förtroende är det tredje. En stilmall avgör vad som syns och var. Den kan dölja en varning, ge en knapp ett nytt utseende eller begära bilder från vilken adress som helst som dess regler nämner. Att ladda en från en tredje part lämnar över den makten till tredje parten, tillsammans med en server som sidan inte kan visas utan. Subresource Integrity låter sidan ange en kryptografisk hash för filen, och webbläsaren vägrar använda en fil vars innehåll skiljer sig.

Så ser det ut i praktiken

Webbplatsens eget paket med stilmallar visar hur långt en enda inbäddad resurs kan tippa balansen. På 87 KB var det, för en dokumentwebbplats utan ramverk, större delen av en sidas vikt, förbrukad innan något innehåll kommit fram, och två tredjedelar av den största stilmallen visade sig vara ett enda base64-kodat typsnitt: ungefär 56 KB text som kodade ungefär 42 KB typsnitt. Det hade bäddats in för en fördel vid den första utritningen som en förladdad extern fil ändå får, och varje sida betalade för det oavsett om vikten behövdes eller inte. När det togs bort minskade den filen från 84 KB till 28 och hela paketet från 87 KB till 31 KB, och typsnittsvikterna förladdas i stället. Base64 skriver varje grupp om tre byte som fyra tecken, så en binär fil som bäddas in i en stilmall väger alltid ungefär en tredjedel mer än samma fil levererad för sig.

Papper är också ett medium som en stilmall måste betjäna. Webbplatsens fallstudier är det som någon skriver ut och tar med sig till ett möte, så en stilmall på 637 rader med en enda sidregel och ett utskriftsblock gör att de går att skriva ut på okänt papper i båda färgtemana. Sidregeln anger en marginal och avsiktligt ingen pappersstorlek, och en radlängd på ungefär sjuttiotvå tecken hindrar ett liggande ark från att få rader på ungefär hundratio tecken. Fyra beteenden hos webbläsarmotorer är nedskrivna som fällor, och vart och ett har orsakat ett verkligt fel: längder i viewport-enheter, som en motor löser upp mot sidrutan och en annan mot fönstret, vilket skar bort en tredjedel av varje rad; element med fast position som ritas ut på varje ark; en palett med vit text som standard för det mörka temat, som skrev ut fyra avsnittsetiketter vitt på vitt; och en flex- eller grid-ruta som paginerade medier inte kan dela, vilket gav ett tomt första ark. En kontroll i sex delar täcker sex kombinationer av papper och orientering, båda inställningarna för färgschema och det verkliga sidantalet, och det var den kontrollen som märkte när en vilsekommen kommentarsavslutning fick CSS-lintern att svälja en hel regel och passera utan anmärkning två gånger.

Webbplatsens säkerhetssida tar upp Subresource Integrity på stilmallen: paketet får ett fingeravtryck och en hash när webbplatsen byggs, så att läsarens webbläsare kan kontrollera att det kom fram oförändrat. Samma sida ber läsaren räkna värdarna i webbläsarens nätverkspanel och ger svaret: en, webbplatsens egen.

Var det går fel

En stilmall som webbläsaren får veta om sent kommer också fram sent. En länk i slutet av body, en stilmall som ett skript lägger in eller en kedja av @import-regler låter var och en sidan ritas ut innan stilarna har kommit, så att rå text hoppar in i en layout, eller en färdig layout flyttar sig. En kedja av importer ser harmlös ut i källkoden:

/* site.css: webbläsaren hittar base.css först när den här filen har kommit */
@import url("base.css");
@import url("theme.css");

Lägg länkarna till stilmallar i head och platta ut importerna till paketet när webbplatsen byggs.

En driftsättning kan para ihop ny märkning med gamla regler. Läsare vars cache har den förra stilmallen får HTML som förväntar sig klasser som den gamla filen aldrig har hört talas om, och deras layout går sönder tills cachen löper ut, medan den som testar med en tom cache ser en fungerande webbplats. Orsaken är ett namn på stilmallen som aldrig ändras i kombination med en lång livslängd i cachen, och ett filnamn med fingeravtryck tar bort den.

En stilmall som levereras med fel innehållstyp ignoreras. HTML-standarden tillämpar en länkad stilmall bara när den kommer fram som text/css, med ett undantag för en fil från samma ursprung på en sida i quirks-läge. En server som märker .css-filer som text/plain, eller som svarar på en fil som saknas med en HTML-sida och en statuskod för lyckad förfrågan, lämnar sidan utan stil medan nätverkspanelen visar en förfrågan som verkar ha fungerat. Kontrollera huvudet Content-Type på den driftsatta filen.

En integritetshash slutar stämma när filen ändras efter att hashen räknades fram: en handredigering på servern, ett CDN som minifierar filen på vägen, eller ett bygge som räknar fram hashen före sin sista omskrivning. Webbläsaren behandlar avvikelsen som ett nätverksfel och visar sidan utan stilmallen. Från ett annat ursprung kräver integritetskontrollen också CORS: ett crossorigin-attribut på länken och ett matchande huvud från servern. Räkna fram hashen i det steg som skriver den slutliga filen.

En stilmall för ett ramverk på ett publikt CDN motiverades förr med att läsarna redan hade den i cachen från andra webbplatser. Fetch-standarden delar upp HTTP-cachen efter webbplatsen på översta nivån, så varje webbplats egen kopia hämtas och lagras för sig, och det som återstår är en extra server på den kritiska vägen, under någon annans kontroll. Att leverera filen från webbplatsens egen server kostar lika många byte utan den extra anslutningen.

Läs mer

Ordlista