Hur man skriver bättre CSS med prestation i åtanke
I dagens inlägg kommer vi att fundera över de kodval som vi kan göra i CSS för förbättrad prestanda på webbplatsen. Men innan vi dyker in i dessa val, låt oss först ta en kort, närmare titt på webbsidan som gör arbetsflödet för att fokusera påproblematiska (performance-wise) områden som kan lösas via CSS.
Här är det grova flödet av operationer som utförs av webbläsaren efter skapandet av DOM-träd:
- Räkna om stil (och gör trädskapelse). Browser beräknar de stilar som ska tillämpas på elementen i DOM-trädet. Ett render träd skapas senare medan nodarna (elementen) släpps från DOM-trädet som inte ska återges (element med
display: none
) och de som är (pseudo-element). - Layout (aka Reflow). Med hjälp av den beräknade stilen från tidigare beräknar webbläsaren positionen och geometrin för varje element på sidan.
- Måla om. När layouten är mappad dras pixlar till skärmen.
- Sammansatta lager. Under målning kan målningen göras i olika lager autonomt; dessa lager kombineras då äntligen.
Låt oss fortsätta med vad vi kan göra i de tre första stegen i operationen för att skriva bättre CSS-koder.
1. Minska stilberäkningar
Som tidigare nämnts beräknar webbläsaren de stilar som ska tillämpas på elementen i "Recalculate Style" -steget. För att göra detta upptäcker webbläsaren först alla väljare i CSS som pekar på en given elementnod i DOM-trädet. Då går det igenom alla stilreglerna i dessa väljare och bestämmer vilka som faktiskt ska tillämpas på elementet.
För att undvika kostsamma stilberäkningar, minska komplexa och djupt nestade selektorer så att det är lättare för webbläsaren att ta reda på vilket element en väljare hänvisar till. Detta minskar beräkningstiden.
Andra sätt att anställa inkluderar vilket minskar antalet stilregler (om möjligt), avlägsna oanvänd CSS och undviker redundans och överklaganden, så att webbläsaren inte behöver gå igenom samma stil igen och igen under stilberäkningar.
2. Minska Reflows
Reflows eller Layout förändringar i ett element är mycket "dyra" processer, och de kan vara ett ännu större problem när det element som gick igenom layoutändringar har en betydande mängd barn (sedan Reflows kaskad ner hierarkin).
Reflows utlöses av layoutändringar till ett element, till exempel förändringar i geometriska egenskaper som höjd- eller teckenstorlek, tillägg eller borttagning av klasser till element, fönsterändring, aktiverad :sväva
, DOM ändras med JavaScript, etc.
Precis som i stilberäkning, för att minska Reflows, undvik komplexa väljare och djupa DOM-träd (igen, detta är för att förhindra överdriven cascading av Reflows).
Om du måste ändra layoutformat för en komponent på din sida, rikta in stilen på elementet som är lägst i elementets hierarki att komponenten är tillverkad av. Det här är så att layoutändringarna inte utlöser (nästan) några andra Reflows.
Om du animerar ett element som går igenom layoutändringar, ta ut det från sidflödet av placera den absorpsivt, eftersom Reflow i absolut positionerade element inte påverkar resten av elementen på sidan.
För att sammanfatta:
- Målelement som är lägre i DOM-trädet när layoutändringar ändras
- Välj absolut positionerade element för layoutändrings animationer
- Undvik att animera layoutegenskaper när det är möjligt
3. Minska Repaints
Repaint hänvisar till teckning av pixlar på skärmen, och är en dyr process precis som Reflow. Repaints kan utlösas av Reflows, sidrullning, ändringar i egenskaper som färg, synlighet och opacitet.
För att undvika frekventa och stora repaints, Använd mindre av de egenskaper som orsakar kostsamma repaints som skuggor.
Om du animerar egenskaper hos ett element som kan utlösa Repaint direkt eller indirekt, kommer det att vara till stor nytta om det här elementet är i sitt eget lager förhindrar att dess målningsprocess påverkar resten av sidan och utlöser hårdvaruacceleration. Vid maskinvaruacceleration tar GPU uppgiften att utföra animationsändringar i skiktet, vilket sparar CPU-extraarbete samtidigt som processen påskyndas.
I vissa webbläsare, opacitet
(med ett värde mindre än 1
) och omvandla
(annat värde än ingen
) marknadsförs automatiskt till nya lager, och hårdvaruacceleration tillämpas för animeringar och övergångar. Att föredra dessa egenskaper för animeringar är således bra.
Att tvingas främja ett element till nytt lager och gå in i hårdvaruacceleration för animering finns det två tekniker invovled:
- Lägg till
transformera: translate3d (0, 0, 0);
till elementet, lurar webbläsaren på att utlösa maskinvaruaccelerationen för animeringar och övergångar. - Lägg till
kommer att ändras
egenskap till elementet, vilket informerar webbläsaren om de egenskaper som sannolikt kommer att förändras i elementet i framtiden. Notera: Sara Soueidan har en djupgående och superhjälpsam artikel om detta på Dev.Opera-webbplatsen.
För att sammanfatta:
- Undvik dyra stilar som orsakar Repaints
- Sök lagkampanj och hårdvaruacceleration för kraftiga animeringar och övergångar.
Notera
(1) Så fram till nu har vi inte berört CSS-filstorleksminskningen. Vi har nämnt att minskningen av stilregler (och DOM-element) ger en betydande förbättring av prestanda på grund av hur mycket webbläsaren kommer att fungera mindre på processen att beräkna stilar. Som en konsekvens av denna kodminskning, skriver du bättre väljare och radering av oanvänd CSS, Filstorleken minskar automatiskt.
(2) Det är också tillrådligt att Gör inte för många följdändringar på ett elements stilar i JavaScript. Lägg istället en klass i elementet (med hjälp av JavaScript) som innehåller de nya formaten för att göra dessa ändringar - detta förhindrar onödiga återflöden.
(3) Du kommer att vilja Undvik Layout Thrashing samt (tvångs synkrona Reflows) som uppstår på grund av åtkomst och modifiering av Layoutegenskaperna hos element som använder JavaScript. Läs mer om hur detta dödar prestanda här.