Browser rendering pipeline — Fra HTML til pixels
Browser rendering pipeline: HTML → DOM, CSS → CSSOM, DOM + CSSOM → Render tree → Layout → Paint → Composite. Hvert trin har performance-implikationer. At kende pipelinen er fundamentet for performance-optimering.
Browseren gennemgår en veldefineret sekvens af trin for at konvertere HTML og CSS til pixels på skærmen: HTML-parsing, CSSOM-opbygning, render tree-konstruktion, layout, paint og compositing. At forstå disse trin og deres afhængigheder er fundamentet for al performance-optimering — det forklarer præcist hvorfor visse ændringer er dyre og andre gratis for browseren at udføre.
Trin 1: HTML-parsing og DOM-opbygning
Browseren downloader HTML og parser det linje for linje til Document Object Model (DOM) — en træstruktur af noder der repræsenterer alle HTML-elementer og deres relationer.
HTML-parsing er ikke blokerende — browseren kan parse og vise dele af siden mens resten downloades. Men JavaScript uden defer stopper parsingen: browseren er nødt til at afvente script-download og -eksekvering.
Speculative parsing (lookahead parsing) er en browser-optimering: parseren scanner fremad og identificerer ressourcer (billeder, scripts, stylesheets) der kan downloades parallelt.
Trin 2: CSS-parsing og CSSOM-opbygning
CSS-filer downloades og parses til CSS Object Model (CSSOM) — en lignende træstruktur for styles. CSSOM er render-blocking: browseren kan ikke fortsætte til render tree-opbygning inden al CSS er processeret.
Årsagen: CSS er “cascade first” — en sen regel kan overskrive en tidlig. Browseren skal kende alle CSS-regler inden den beregner finale styles.
/* Begge regler er nødvendige for at beregne final color */
.button { color: blue; }
.button { color: red; } /* override */
Trin 3: Render tree
Render tree kombinerer DOM og CSSOM. Det inkluderer kun synlige elementer — noder med display: none er ikke med. Hvert node i render tree har sine beregnede styles.
Render tree er inputtet til layout-steget.
Trin 4: Layout (reflow)
Layout beregner præcis position og størrelse på hvert element i render tree — i pixels, relativt til viewport. Det er en dyr operation fordi ét elements størrelse kan påvirke alle andre elementer.
Forced synchronous layout opstår når JavaScript læser layout-properties (offsetTop, clientWidth) efter at have modificeret DOM — browseren tvinges til at genberegne layout synkront. Undgå read-after-write patterns i hot paths.
Trin 5: Paint
Paint rasteriserer de beregnede elementer til pixels i lag. Tekst males. Baggrunde males. Borders males. Hvert lag males separat.
Paint er relativt dyrt sammenlignet med compositing, men billigere end layout. CSS-egenskaber der kun trigger paint (og ikke layout) inkluderer color, background-color og box-shadow.
Trin 6: Compositing
Compositor-threaden kombinerer de malede lag til det endelige billede der sendes til skærmen. Compositing kører på en separat thread fra main thread — det er grunden til at transform og opacity-animationer er hurtige: de håndteres udelukkende af compositor og blokerer ikke JavaScript-eksekvering.
/* Kun compositing — kører på compositor thread */
.fade { transition: opacity 0.3s; }
.slide { transition: transform 0.3s; }
/* Trigger paint — kører på main thread */
.color { transition: color 0.3s; }
GPU-acceleration
will-change: transform promoverer et element til sit eget compositor-lag, behandlet af GPU. Det eliminerer paint-overhead for animerede elementer — men bruger mere GPU-hukommelse. Brug det målrettet, ikke globalt.
Kritisk rendering path
Den korteste sekvens fra HTML til første pixels er: HTML-download → DOM-parse → CSS-download → CSSOM-build → Render tree → Layout → Paint → Composite. At forkorte denne vej er essensen af performance-optimering. → Denne artikel er en del af Web Performance — Core Web Vitals og teknisk hastighed.
Andre artikler i samme emne
- Animation performance — Frame rate og jank-fri bevægelse
- Billedoptimering — Formater, størrelser og SEO
- CLS-problemer — Årsager til Cumulative Layout Shift og løsninger
- Core Web Vitals — LCP, INP og CLS forklaret
- CSS — Cascading Style Sheets og SEO
- CSS containment — Isolér rendering og accelerér layout
- Font-optimering — Webfonts, FOUT og SEO
- HTTP/2 og HTTP/3 — Protokoller der eliminerer latency-overhead
- INP-optimering — Interaction to Next Paint og Core Web Vitals
- JavaScript bundle-optimering — Code splitting, tree shaking og analyse
- Kritisk renderingsti — Hvad browseren gør før du ser noget
- Latency — Forsinkelse i netværket og hvad du kan gøre ved det
- Lazy loading — Udskyd indlæsning af billeder og ressourcer
- LCP-optimering — Sådan forbedrer du Largest Contentful Paint
- Long Tasks og LoAF — Hvad blokerer main thread
- Navigation og resource timings — Browserens performance-API
- PageSpeed og SEO — Hastighed som rankingfaktor
- Performance budgets — Grænser der forhindrer regressioner
- Performance timings — Hvornår er det for langsomt?
- Resource hints — Preload, prefetch og preconnect til SEO
- Responsive images — srcset, sizes og art direction
- Responsivt design — Mobile-first og SEO
- RUM vs. syntetisk monitoring — To syn på web performance
- Service Workers — Offline caching og PWA performance
- Speculative loading — Prefetch og prerender af næste side
- Startup performance — Hurtig app-start og time to interactive
- Tredjeparts-scripts og performance — Impact og strategier
- Tredjepartsscripts — Analytics, ads og performance-konsekvenser
- TTFB og hosting — Server response time og SEO
- Video performance — Lazy loading, formater og indlæsningsstrategi
- Viewport tag — Meta viewport og mobil-rendering
- Web Workers — Parallel JavaScript uden main thread-blokning
Ofte stillede spørgsmål
- Hvad er forskellen på layout, paint og compositing?
- Layout (reflow) beregner position og størrelse på alle elementer. Paint rasteriserer elementer til pixels i lag. Compositing kombinerer de malede lag til det endelige billede der vises på skærmen. Layout er dyrest. Compositing er billigst. Animationer der kun kræver compositing (transform, opacity) kører uden at involvere layout eller paint.
- Hvornår blokerer JavaScript rendering?
- JavaScript-filer i `<head>` uden `defer` eller `async` stopper HTML-parsing og rendering. Browseren antager at scriptet kan modificere DOM og venter på download og eksekvering inden den fortsætter. CSS-filer blokerer rendering fordi CSSOM skal bygges inden render tree kan konstrueres.
- Hvad er forced synchronous layout og hvorfor er det et problem?
- Forced synchronous layout opstår når JavaScript læser layout-egenskaber som offsetTop eller clientWidth umiddelbart efter at have modificeret DOM. Browseren tvinges til at genberegne layout synkront på main thread — en dyr operation der blokerer alt andet. Det er en hyppig årsag til dårlig INP og lange tasks. Undgå read-after-write patterns i event handlers.
- Hvad er forskellen på paint og compositing i rendering pipeline?
- Paint rasteriserer elementer til pixels i separate lag — tekst, baggrunde, borders. Det kører på main thread. Compositing kombinerer de malede lag til det endelige billede og kører på compositor thread — en separat thread fra main thread. Animationer der bruger transform og opacity springer paint-trinnet over og kører udelukkende som compositing, hvilket giver jævne 60fps uden main thread-blokeringer.
- Hvad er render tree og hvad indeholder det?
- Render tree er kombinationen af DOM og CSSOM — et træ der kun indeholder synlige elementer med deres beregnede styles. Elementer med display:none er ikke med i render tree. Render tree er inputtet til layout-steget, hvor browseren beregner præcis position og størrelse på alle elementer. Render tree bygges forfra ved enhver DOM- eller CSSOM-ændring.
Placering i ordbogen
- Animation performance — Frame rate og jank-fri bevægelse
- Billedoptimering — Formater, størrelser og SEO
- CLS-problemer — Årsager til Cumulative Layout Shift og løsninger
- Core Web Vitals — LCP, INP og CLS forklaret
- CSS — Cascading Style Sheets og SEO
- CSS containment — Isolér rendering og accelerér layout
- Font-optimering — Webfonts, FOUT og SEO
- HTTP/2 og HTTP/3 — Protokoller der eliminerer latency-overhead
- INP-optimering — Interaction to Next Paint og Core Web Vitals
- JavaScript bundle-optimering — Code splitting, tree shaking og analyse
- Kritisk renderingsti — Hvad browseren gør før du ser noget
- Latency — Forsinkelse i netværket og hvad du kan gøre ved det
- Lazy loading — Udskyd indlæsning af billeder og ressourcer
- LCP-optimering — Sådan forbedrer du Largest Contentful Paint
- Long Tasks og LoAF — Hvad blokerer main thread
- Navigation og resource timings — Browserens performance-API
- PageSpeed og SEO — Hastighed som rankingfaktor
- Performance budgets — Grænser der forhindrer regressioner
- Performance timings — Hvornår er det for langsomt?
- Resource hints — Preload, prefetch og preconnect til SEO
- Responsive images — srcset, sizes og art direction
- Responsivt design — Mobile-first og SEO
- RUM vs. syntetisk monitoring — To syn på web performance
- Service Workers — Offline caching og PWA performance
- Speculative loading — Prefetch og prerender af næste side
- Startup performance — Hurtig app-start og time to interactive
- Tredjeparts-scripts og performance — Impact og strategier
- Tredjepartsscripts — Analytics, ads og performance-konsekvenser
- TTFB og hosting — Server response time og SEO
- Video performance — Lazy loading, formater og indlæsningsstrategi
- Viewport tag — Meta viewport og mobil-rendering
- Web Workers — Parallel JavaScript uden main thread-blokning