Når nettleseren laster siden din, leser den HTML-koden linje for linje. Når den møter <script src="stor-fil.js"> eller <link rel="stylesheet">, stopper den alt annet, laster ned filen og kjører den.
Først da rendrer den resten av siden. Dette er “Render-Blocking”.
I 2026, når Core Web Vitals teller (spesielt LCP - Largest Contentful Paint), må du fikse dette.
Hvordan nettleseren rendrer en side
For å forstå hvorfor enkelte filer stopper renderingen, hjelper det å se på rekkefølgen nettleseren bygger en side i.
Hvordan nettleseren bygger DOM og CSSOM
- Nedlasting av HTML. Nettleseren laster ned HTML-dokumentet fra serveren.
- Parsing av HTML. Parseren går gjennom HTML-en linje for linje og bygger DOM (Document Object Model), trestrukturen til siden.
- Møte med CSS. Når parseren finner
<link rel="stylesheet">, må filen lastes ned og behandles for å bygge CSSOM (CSS Object Model). Imens står renderingen stille, fordi nettleseren trenger stilene for å vite hvordan elementene skal tegnes. web.dev oppsummerer det slik: nettleseren må laste ned og parse CSS-filer før den kan vise siden, og det gjør CSS til en render-blokkerende ressurs. - Møte med JavaScript. Ved
<script src="...">uten attributter stopper parseren helt. Den laster ned filen, parser den og kjører den, og først da fortsetter den med resten av HTML-en. Grunnen er at JavaScript kan endre DOM-en som er under oppbygging. - Render tree. Først når DOM og CSSOM er klare, kombinerer nettleseren dem til et render tree og tegner siden.
Hver CSS- eller JavaScript-fil i <head> uten spesielle attributter holder igjen denne prosessen. Med 5 CSS-filer og 8 skript i head må nettleseren laste ned og behandle alle 13 før brukeren ser en eneste piksel.
Hvordan render-blocking påvirker Core Web Vitals
Render-blocking slår direkte inn på to målinger:
FCP (First Contentful Paint): øyeblikket nettleseren tegner det første innholdet (tekst, bilde, SVG). Jo flere ressurser som blokkerer, desto senere skjer det. Målet er en FCP under 1,8 sekunder.
LCP (Largest Contentful Paint): øyeblikket det største synlige elementet på skjermen er rendret. Hindrer en tung CSS-fil nettleseren i å tegne hero-bildet eller hovedteksten, stiger LCP. Målet er en LCP under 2,5 sekunder.
I WordPress kan hver plugin legge sitt eget stilark og sitt eget skript i køen på alle sider, også der de ikke brukes, så listen i PageSpeed Insights vokser med hver plugin du installerer. Så lenge filene ikke har kommet, ser den besøkende en hvit skjerm. På mobil tar hver forespørsel lengre tid på grunn av nettverksforsinkelsen, og det samme antallet filer koster mer tid enn på desktop.
Async og defer i JavaScript for WordPress
Gammel skole sa: “legg skript i bunnen (wp_footer)”. Ny skole sier: “bruk attributter”.
<script async>: Laster i bakgrunnen, kjører umiddelbart etter nedlasting (risikabelt for avhengigheter, f.eks. jQuery).<script defer>: Laster i bakgrunnen, kjører først etter HTML er lastet (trygt, bevarer rekkefølge).
Hvordan legge til defer i WordPress? Cache-plugins (WP Rocket, Autoptimize, LiteSpeed Cache) har en “Defer JS” alternativ. Aktiver det.
Sjekk deretter nettleserkonsollen på sider med slidere, skjemaer og gallerier.
Hva er critical CSS
CSS er vanskeligere. Du kan ikke “forsinke” det fordi siden vil se ut som “rå tekst” et øyeblikk (ustylet - FOUC-effekt).
Løsningen er Critical CSS.
- Ta bare CSS som trengs for “over folden” innhold (synlig uten scrolling).
- Lim det inn inline i
<style>i headeren. - Last resten av CSS (bunntekst, nedre seksjoner) asynkront i bakgrunnen.
De fleste moderne optimaliseringsplugins genererer Critical CSS automatisk.
Strategioppsummering
- JS: Alt med
defer(bortsett fra absolutt kritiske analyse/cookie-skript). Aldriasyncpå skript som trenger jQuery. - CSS: Critical CSS inline per sidetype (forside, innlegg, produkt, kategori) + resten asynkront.
- Fonter: Hostet lokalt, i WOFF2, med
font-display: swapog preload av hovedfonten. - Bilder: LCP-bildet med
fetchpriority="high", resten av bildene med native lazy loading. - Tredjeparter: Analyse, chat og sosiale widgets med
defereller først etter at brukeren gjør noe. - Minifisering: Alle CSS- og JS-filer minifisert, slått sammen bare når det beviselig hjelper.
På denne måten ser brukeren innhold umiddelbart mens tunge galleri- eller kartskript lastes i bakgrunnen.
Hvordan finne render-blocking ressurser med DevTools
Lighthouse gir deg en liste over blokkerende filer, men listen sier ingenting om hvor mye av hver fil som faktisk brukes. Åpne DevTools, kjør “Show Coverage” fra kommandopaletten, last siden på nytt og se på kolonnen “Unused Bytes”. Andelen ubrukte bytes er viktigere enn filstørrelsen alene, fordi den skiller mellom to helt ulike problemer: for mye CSS, eller CSS lastet på feil tidspunkt. Lighthouse-dokumentasjonen anbefaler Coverage-fanen nettopp for å finne CSS og JS som ikke er kritisk.
Nettverksfanen forteller resten. Sorter etter waterfall og let etter små filer som starter nedlastingen sent. De er nesten alltid ressurser nettleseren først oppdaget etter å ha parset en annen fil, og nettopp de er kandidater for preload.
Lighthouse markerer et <script> i <head> uten defer og uten async som blokkerende, og det samme gjelder en <link rel="stylesheet"> uten disabled der media passer til enheten. media="all" regnes som blokkerende.
Finne render-blocking i PageSpeed Insights
PageSpeed Insights lister filene under “Fjern ressurser som blokkerer gjengivelse”. For hver fil ser du URL, størrelse og mulig besparelse i millisekunder, og det gir en arbeidsliste sortert etter effekt.
Finne render-blocking i WebPageTest
WebPageTest viser et detaljert fossefallsdiagram der hver forespørsel er delt opp i DNS, tilkobling, TLS og nedlasting. Let etter CSS- og JS-filene som blir ferdige før den loddrette linjen for Start Render: det er dem nettleseren ventet på før den tegnet.
Forskjellen på async og defer
| Attributt | Nedlasting | Kjøring | Rekkefølge bevart | Bruk når |
|---|---|---|---|---|
| ingen | blokkerer parsing | umiddelbart | ja | helst aldri i <head> |
async | parallelt | så snart filen er nede | nei | frittstående skript uten avhengigheter |
defer | parallelt | etter at HTML er parset | ja | alt som bruker jQuery eller andre skript |
type="module" | parallelt | etter parsing | ja | ES-moduler, defer er innebygd |
Regelen i praksis: defer er standardvalget og async er unntaket. Grunnen er at async kjører i den rekkefølgen filene tilfeldigvis blir ferdige. En galleri-plugin som kaller jQuery(...) før jQuery er lastet gir en TypeError i konsollen og et tomt galleri på siden. Feilen viser seg sjelden på utviklermaskinen, der alt ligger i cache og kommer ned i riktig rekkefølge uansett.
To detaljer fra MDN-referansen sparer deg for overraskelser. defer og async har ingen effekt på inline-skript uten src. Og skript med type="module" er utsatt som standard, så et ekstra defer endrer ingenting. Utsatte skript kjører før hendelsen DOMContentLoaded, så et inline-stykke som trenger utsatt jQuery kan vente på den hendelsen.
Defer i WordPress uten plugin
WordPress 6.3 innførte et strategy-argument i wp_enqueue_script(), og det er den riktige måten i dag, fordi WordPress selv holder styr på avhengighetskjeden:
wp_enqueue_script(
'tema-galleri',
get_template_directory_uri() . '/js/galleri.js',
array( 'jquery' ),
'1.2.0',
array(
'in_footer' => true,
'strategy' => 'defer',
)
);Poenget med å oppgi array( 'jquery' ) er at WordPress sjekker avhengighetskjeden før attributtet skrives ut. Utviklernotatet for WordPress 6.3 fastsetter reglene: for at et skript skal utsettes, kan avhengighetene være utsatt eller blokkerende, men alle skript som er avhengige av det, må være utsatt. Er ett av dem blokkerende, lastes skriptet og avhengighetene blokkerende igjen. Et async-skript kan nedgraderes til defer eller blokkerende, aldri motsatt. Legger du til inline-kode i posisjon after med wp_add_inline_script(), fjernes strategien. Et utsatt galleriskript med blokkerende jQuery er altså tillatt, fordi jQuery uansett kjører først.
For skript fra en plugin peker samme notat på wp_script_add_data( $handle, 'strategy', 'defer' ), kalt etter at pluginen har registrert handle-en. Versjoner før 6.3 ignorerer nøkkelen. Fra WordPress 6.9 tar samme array ifølge funksjonsreferansen også imot nøkkelen fetchpriority.
For eldre installasjoner, eller for en plugin du ikke kan endre, går veien om filteret:
add_filter( 'script_loader_tag', 'nb_defer_valgte_skript', 10, 2 );
function nb_defer_valgte_skript( string $tag, string $handle ): string {
$utsatt = array( 'slider', 'lightbox', 'kart' );
return in_array( $handle, $utsatt, true )
? str_replace( ' src', ' defer src', $tag )
: $tag;
}Legg merke til at listen er en ja-liste, ikke en nei-liste. En nei-liste (“alt utenom disse”) ser mer effektiv ut, men den utsetter også skript som legges til av neste plugin du installerer. Da har du en feil du ikke har skrevet.
Fjerne ubrukt CSS fra plugins
I tillegg til Critical CSS lønner det seg å fjerne CSS som ikke brukes på den aktuelle siden. Stilarkene til WooCommerce og Contact Form 7 trengs bare der butikken eller skjemaet faktisk finnes:
add_action( 'wp_enqueue_scripts', 'nb_fjern_ubrukt_css', 100 );
function nb_fjern_ubrukt_css(): void {
if ( function_exists( 'is_woocommerce' ) && ! is_woocommerce() && ! is_cart() && ! is_checkout() ) {
wp_dequeue_style( 'woocommerce-general' );
wp_dequeue_style( 'woocommerce-layout' );
wp_dequeue_style( 'woocommerce-smallscreen' );
}
if ( ! is_page( 'kontakt' ) ) {
wp_dequeue_style( 'contact-form-7' );
}
}Verktøy som PurgeCSS og UnCSS går et steg videre og fjerner selektorene som ikke forekommer på siden, inne i hver fil. Det reduserer det nettleseren må laste ned og parse, men har risikoen som er beskrevet under vanlige feil lenger ned.
Hvordan laste CSS asynkront uten FOUC
Mønsteret er alltid det samme: kritisk CSS inline i <head>, resten hentet uten å blokkere.
<style>/* bare regler for det som er synlig uten scrolling */</style>
<link rel="preload" href="/style.css" as="style"
onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/style.css"></noscript>noscript-linjen er ikke pynt. Uten den mister besøkende med JavaScript avslått hele stilarket, og det gjelder også en del bedriftsnettverk med streng innholdsfiltrering.
Mønsteret med preload og onload er det web.dev anbefaler for CSS som ikke er kritisk.
Tre ting avgjør om dette går bra:
- Størrelsen. web.dev-guiden om Critical CSS anbefaler å holde innholdet over folden under 14 KB komprimert, for å holde antall rundturer før første rendering nede. Blir den større, betaler du med lengre HTML-svar på hver eneste sidevisning, og da har du flyttet problemet i stedet for å fjerne det.
- Viewport. Critical CSS generert på 1300 piksler bredde mangler reglene som bare gjelder mobil. Generer for begge bredder og slå sammen resultatet.
- Test på treg linje. Sett DevTools til “Slow 3G” og last på nytt. Ser du ustylet tekst i et halvt sekund før layouten smekker på plass, har du tatt med for lite i den kritiske blokken.
Generere Critical CSS: verktøy og plugins
Den samme web.dev-guiden nevner to verktøy. Critical trekker ut, minifiserer og legger inn CSS over folden inline, og fungerer med Gulp, Grunt eller webpack. Penthouse passer for nettsteder med mange stiler eller dynamisk innsatte stiler, men finner ikke stilarkene selv, så du oppgir HTML- og CSS-filene.
I WordPress gjør plugins som regel jobben:
WP Rocket: Under “Optimaliser CSS-levering” genererer pluginen Critical CSS for hver side og legger det inn inline.
Autoptimize med CriticalCSS.com: Autoptimize kan kobles til tjenesten CriticalCSS.com. Du trenger en API-nøkkel, og deretter går genereringen automatisk.
LiteSpeed Cache: Genererer Critical CSS via tjenesten QUIC.cloud, og sidecachen kjører på LiteSpeed-servere.
Perfmatters: En lett plugin der Script Manager slår av skript og stiler per side, nyttig for plugins som laster filene sine på hele nettstedet.
Font-display swap og preload av fonter
En egen skrifttype uten font-display gir FOIT: nettleseren skjuler teksten til fontfilen er nede. På en dårlig mobilforbindelse betyr det flere sekunder med tomme tekstflater der innholdet skulle stått.
@font-face {
font-family: 'Inter';
src: url('/fonts/inter.woff2') format('woff2');
font-display: swap;
}swap viser systemfonten umiddelbart og bytter når filen kommer. Kombiner med preload, og husk crossorigin, som kreves for fonter selv når filen ligger på ditt eget domene:
<link rel="preload" href="/fonts/inter.woff2" as="font" type="font/woff2" crossorigin>Hoster du fonten selv, sparer du i tillegg et DNS-oppslag og et TLS-håndtrykk mot et fremmed domene før nedlastingen i det hele tatt begynner.
Personvernet teller også. Dynamisk lasting av Google Fonts sender den besøkendes IP-adresse til Googles servere. I januar 2022 kom Landgericht München I, en tysk domstol, til at denne overføringen uten samtykke var ulovlig, og dommen utløste en bølge av krav i Tyskland.
Slik hoster du Google Fonts lokalt:
- Last ned fontfilene fra Google Fonts-repositoriet eller med verktøyet google-webfonts-helper.
- Last opp WOFF2-filene til serveren din, WOFF2 gir best komprimering.
- Oppdater
@font-face-reglene i CSS-en slik at de peker på de lokale filene. - Fjern alle referanser til fonts.googleapis.com og fonts.gstatic.com fra HTML-en.
I WordPress automatiserer pluginen OMGF (Optimize My Google Fonts) hele prosessen.
Minifisere og slå sammen CSS og JS med HTTP/2
Hva minifisering gir
Minifisering fjerner mellomrom, kommentarer og unødvendige tegn fra CSS- og JavaScript-filer uten å endre hva de gjør. Hvor mye du sparer, avhenger av hvor mange kommentarer og mellomrom originalfilen har, og med gzip eller Brotli aktivert på serveren er forskjellen i overført størrelse mindre enn for den ukomprimerte filen.
I WordPress tar cache-plugins seg vanligvis av dette: WP Rocket minifiserer CSS og JS med en avkrysningsboks, Autoptimize er spesialisert på minifisering og sammenslåing, og LiteSpeed Cache har innebygd minifisering.
Slå sammen CSS- og JS-filer med HTTP/2
Å slå sammen flere CSS-filer til én (og flere JS-filer til én) reduserer antall HTTP-forespørsler. Med HTTP/2 og HTTP/3 betyr dette mindre enn før, fordi protokollene tillater mange nedlastinger samtidig over én tilkobling.
Sammenslåing kan til og med slå feil ut hvis den ugyldiggjør cachen for ofte. Slår du sammen 15 CSS-filer til én og en plugin endrer én linje, må hele den sammenslåtte filen lastes ned på nytt. Med separate filer trenger bare den endrede filen å oppdateres.
Anbefalingen i dag er å alltid minifisere, men bare slå sammen når nettstedet fortsatt bruker HTTP/1.1, eller når fossefallet viser dusinvis av små filer som venter på tur.
Preload, prefetch og fetchpriority i WordPress
I tillegg til async, defer og Critical CSS forstår moderne nettlesere prioriteringshint som forteller hvilke ressurser som er kritiske og hvilke som kan vente.
Når du bør bruke preload
<link rel="preload" href="/critical-script.js" as="script">
<link rel="preload" href="/hero-bilde.webp" as="image">Preload ber nettleseren laste ned en ressurs så tidlig som mulig, før den oppdager den selv under parsingen av HTML-en. Bruk det for kritiske ressurser som LCP-bildet, hovedfonten eller et uunnværlig skript.
Når du bør bruke prefetch
<link rel="prefetch" href="/neste-side/">
<link rel="prefetch" href="/stiler-side2.css">Prefetch laster ned en ressurs med lav prioritet når nettleseren har ledig tid, i påvente av at brukeren snart trenger den. Det passer for ressurser til den mest sannsynlige neste siden.
Når du bør bruke fetchpriority
<img src="/hero.webp" fetchpriority="high">
<img src="/dekor.webp" fetchpriority="low">Attributtet fetchpriority justerer nedlastingsprioriteten for enkeltressurser: høyere for LCP-bildet, lavere for dekorative bilder eller bilder utenfor skjermen. Ifølge web.dev virker det på link, img og script med verdiene high, low og auto. Preload og fetchpriority gjør ulike jobber: preload hjelper nettleseren å oppdage ressursen tidlig, fetchpriority endrer prioriteten men hjelper ikke med å oppdage den. Et LCP-bilde med preload kan fortsatt få lav prioritet, og et CSS-bakgrunnsbilde som er LCP-elementet trenger fortsatt preload.
Hvordan utsette tredjeparts skript og chat-widgets
Du kan optimalisere temaet ditt perfekt og likevel bli stående på samme LCP, fordi en chat-widget og en kartinnbygging drar inn noen hundre kilobyte hver. To grep hjelper mer enn all minifisering til sammen.
Last chat-widgeten først når brukeren viser tegn til å være til stede:
addEventListener('scroll', function last() {
const s = document.createElement('script');
s.src = 'https://widget.example.com/chat.js';
s.defer = true;
document.body.appendChild(s);
}, { once: true });Ingen besøkende åpner en chat i løpet av de første 300 millisekundene, så det er ingenting å tape på å vente.
Videoinnbygginger bytter du ut med en fasade: et stillbilde som ser ut som spilleren, og selve iframen først ved klikk. Pakken lite-youtube-embed gjør nettopp dette og tar en YouTube-innbygging fra flere hundre kilobyte ned til noen få.
Hvorfor viser Search Console andre tall enn Lighthouse
Lighthouse er labdata og gir rask tilbakemelding på hver enkelt endring. Feltdataene i Chrome User Experience Report er de som avgjør hva Search Console viser. De to er ikke uenige, de måler forskjellige ting: labdata er én måling på én maskin, feltdata er et rullerende vindu på 28 dager fra ekte enheter og ekte forbindelser.
Konsekvensen er praktisk. Ikke konkluder med at endringen var uten effekt fordi Search Console står stille dagen etter. Vinduet må rulle gjennom først. Noter datoen for utrullingen, så du vet hvilken del av kurven som hører til hvilken endring.
Vanlige feil med defer og critical CSS
asyncpå noe som bruker jQuery. Gir tomme gallerier og skjemaer som ikke sender, og bare på trege forbindelser.- For mye CSS inline. Hold det under 14 KB komprimert, ellers betaler hver sidevisning for det.
- Purge uten visuell sjekk. Automatiske verktøy kan fjerne stiler som bare slår inn ved interaksjon (hover, aktive tilstander, modaler) eller gjelder innhold som lastes dynamisk. Kontroller alltid resultatet, særlig på mobil.
- Teste bare på desktop. Et nettsted kan laste raskt på fiber og feile på mobil med 4G. Test i mobilvisningen i PageSpeed Insights og på ekte enheter.
- Jakte på 100 poeng. PageSpeed Insights er et diagnoseverktøy, ikke et mål. Optimaliser for opplevelsen til ekte besøkende, ikke for et tall.
- Glemt mobilviewport i Critical CSS. Mobilen er der målingen som teller blir gjort.
- Nei-liste i stedet for ja-liste når du utsetter skript. Neste plugin blir ditt problem.
- Ingen ny sjekk etter plugin-oppdateringer. Plugins endrer hva de køer opp, og et oppsett som virket i fjor kan være stille brutt i dag.
I hvilken rekkefølge bør du fjerne render-blocking ressurser
Gjør det i denne rekkefølgen, så vet du alltid hvilken endring som forårsaket hva. Fjern først skript og stilark som ikke skal lastes på den aktuelle siden i det hele tatt, for en fil som ikke sendes kan heller ikke blokkere noe. Utsett deretter resten med defer, og sjekk konsollen for feil før du går videre. Legg Critical CSS til sist, fordi det er steget som lettest gir synlige feil og dermed det du vil kunne rulle tilbake alene. Mellom hvert steg tar du en Lighthouse-kjøring på samme URL og samme innstillinger, ellers sammenligner du to ulike målinger og ikke to versjoner av siden.







