Responsiiviset kuvat 2026: srcset, sizes, AVIF ja fetchpriority käytännössä

Käytännön opas responsiivisiin kuviin vuonna 2026: srcset ja sizes oikein, AVIF/WebP-fallback picture-elementillä, lazy loading ja fetchpriority LCP:n parantamiseksi. Sisältää valmiit koodiesimerkit, kuvaputken ohjeet ja Lighthouse-tarkistuslistan.

Päivitetty: 16.8.2026

Responsiiviset kuvat ovat vuonna 2026 selaimen valittavissa oleva joukko kuvavariantteja, joista se lataa laitteelle ja verkolle parhaiten sopivan version srcset-, sizes- ja <picture>-elementtien avulla. Tuloksena on pienempi tavumäärä, nopeampi LCP ja vähemmän datansiirtoa mobiiliverkoissa. Kun yhdistät modernit formaatit (AVIF, WebP) fallbackeineen, oikein mitoitetut width/height-attribuutit ja fetchpriority="high" LCP-kuvalle, saat käytännössä ilmaista suorituskykyä ilman rakennemuutoksia.

  • srcset + sizes antaa selaimen valita oikean resoluution: säästö 30–70 % tavuista Retina-näytöillä ja mobiililaitteilla.
  • <picture>-elementti hoitaa formaattineuvottelun (AVIF, WebP, JPEG) ja art directionin ilman JavaScriptiä.
  • AVIF tuo 2026 keskimäärin 20–30 % pienemmän tavumäärän WebP:hen verrattuna samalla laadulla, ja se tuetaan nyt kaikissa vihreissä selaimissa.
  • fetchpriority="high" LCP-kuvalle nostaa Largest Contentful Paintin priorisointia selainten resurssijonossa, usein 100–400 ms parannus.
  • loading="lazy" kuuluu vain fold-linjan alle jääville kuville. LCP-kuvalle se on antipattern.
  • width ja height -attribuutit varaavat tilan ja estävät CLS:n, vaikka CSS venyttäisi kuvan responsiiviseksi.

Miksi responsiiviset kuvat vaikuttavat suorituskykyyn

Yhden asiakasprojektin RUM-datassa vuonna 2025 näin, että kuvat vastasivat mediaanikäyttäjän tuotesivulla 68 % latauksen kokonaisbyteistä. Rehellisesti sanottuna luku yllätti myös meidät. Kun replikoin saman sivun responsiivisilla kuvilla ja AVIF-formaatilla, sama sivu latautui 4G-yhteydellä 2,1 sekuntia nopeammin ja LCP putosi 3,3 s → 1,7 s. Ei minkäänlaista koodimuutosta muualla, pelkästään <img>-tagien uudelleenkirjoitus.

Ongelma on yksinkertainen: kun palvelet 2560 px levyistä JPEG-kuvaa 375 px levyiseen puhelinnäyttöön, siirrät noin 6–8-kertaisen määrän pikseleitä käyttämättä niitä. Selain skaalaa ne CSS:llä pienemmäksi ilmaiseksi, mutta verkko on jo ehtinyt kärsiä. Responsiiviset kuvat siirtävät päätöksenteon selaimelle, joka tietää tarkalleen näytön leveyden, laitteen pikselitiheyden (DPR), verkkoyhteyden nopeuden (Save-Data-vihjeen kautta) ja viewportin todellisen koon.

Käytännössä tämä tarkoittaa kolmea rinnakkaista optimointia: oikeat mittasuhteet (srcset/sizes), oikea formaatti (AVIF/WebP/JPEG-neuvottelu picture-elementillä) ja oikea latausprioriteetti (fetchpriority + preload). Kaikki nämä ovat vakioselain-APIa vuonna 2026, etkä tarvitse yhtäkään JavaScript-kirjastoa. Google mittaa tuloksen Largest Contentful Paint -metriikalla, joka on suoraan sidoksissa hakukoneen ranking-signaaleihin.

srcset ja sizes: miten selain valitsee kuvan

srcset luettelee saatavilla olevat kuvavariantit ja niiden pikselileveydet. sizes taas kertoo selaimelle, kuinka leveänä kuva näkyy eri viewport-leveyksillä. Selain yhdistää nämä kaksi tietoa laitteen DPR:ään ja valitsee pienimmän kuvan, joka vielä näyttää terävältä. Näin se toimii käytännössä:

<img
  src="/img/hero-800.jpg"
  srcset="
    /img/hero-400.avif 400w,
    /img/hero-800.avif 800w,
    /img/hero-1200.avif 1200w,
    /img/hero-1600.avif 1600w,
    /img/hero-2400.avif 2400w"
  sizes="(min-width: 1200px) 1140px,
         (min-width: 768px) calc(100vw - 32px),
         100vw"
  alt="Tuotekuva keltaisesta juoksukengästä"
  width="1200"
  height="800"
  fetchpriority="high"
>

Huomaa neljä asiaa: (1) src-attribuutti on fallback vanhoille selaimille, eikä se laukea, jos srcset ymmärretään; (2) w-yksikkö srcset:issä on todellinen pikselileveys, ei viewport-leveys; (3) sizes-media-queryt luetaan järjestyksessä ylhäältä alas ja ensimmäinen sopiva voittaa; (4) width- ja height-attribuutit varaavat aspektisuhteen ja estävät layoutin hyppimisen, kuten CLS-optimoinnin oppaassa käsitellään tarkemmin.

Yleisin virhe on jättää sizes pois. Silloin selain olettaa sizes="100vw", ja lataa isolla näytöllä usein liian ison kuvan pieneen container-elementtiin. Törmäsin tähän itse viime kuussa, kun tuotelistaus latasi tuplat kuvatavuja pelkän puuttuvan atribuutin takia. Testaa aina Chrome DevToolsin Network-välilehden Resource Size -sarakkeella, että selain valitsee odotetun variantin eri laitteilla.

picture-elementti ja AVIF/WebP-fallback

<picture>-elementti on formaattineuvottelun kotipaikka. Selain käy <source>-elementit läpi järjestyksessä ja käyttää ensimmäistä, jonka MIME-tyyppi se ymmärtää. Sisällä oleva <img> on aina pakollinen. Se on sekä fallback että kaikki DOM-attribuutit (alt, width, height, fetchpriority) periytyvät siitä.

<picture>
  <source
    type="image/avif"
    srcset="/img/hero-400.avif 400w,
            /img/hero-800.avif 800w,
            /img/hero-1200.avif 1200w,
            /img/hero-1600.avif 1600w"
    sizes="(min-width: 1200px) 1140px, 100vw">
  <source
    type="image/webp"
    srcset="/img/hero-400.webp 400w,
            /img/hero-800.webp 800w,
            /img/hero-1200.webp 1200w,
            /img/hero-1600.webp 1600w"
    sizes="(min-width: 1200px) 1140px, 100vw">
  <img
    src="/img/hero-1200.jpg"
    srcset="/img/hero-400.jpg 400w,
            /img/hero-800.jpg 800w,
            /img/hero-1200.jpg 1200w,
            /img/hero-1600.jpg 1600w"
    sizes="(min-width: 1200px) 1140px, 100vw"
    alt="Hero-kuva sivun otsakkeessa"
    width="1200" height="675"
    fetchpriority="high">
</picture>

AVIF on vuonna 2026 tuettu kaikissa vihreissä selaimissa: Chrome 85+ (2020), Firefox 93+ (2021), Safari 16.4+ (2023) ja Edge 121+ (2024). Käytännössä yli 96 % globaalista liikenteestä osaa dekoodata sen. AVIF-tiedostot ovat keskimäärin 20–30 % pienempiä kuin WebP samalla PSNR-laadulla ja 50 % pienempiä kuin JPEG. WebP-fallback kannattaa silti pitää siihen asti, että vanhat Safarit (iOS 14, 15) tippuvat käytöstä, ja aina JPEG viimeisenä varmuuden vuoksi.

Art direction: eri rajaus mobiilissa ja desktopissa

<picture> mahdollistaa myös eri kuvasommittelun eri viewporteissa media-attribuutin kautta. Tämä on hyödyllistä esimerkiksi silloin, kun hero-kuvassa halutaan mobiilissa lähikuva ja desktopilla panoraama:

<picture>
  <source media="(min-width: 768px)"
          srcset="/img/hero-wide-1600.avif 1600w, /img/hero-wide-2400.avif 2400w"
          type="image/avif">
  <source media="(max-width: 767px)"
          srcset="/img/hero-portrait-600.avif 600w, /img/hero-portrait-900.avif 900w"
          type="image/avif">
  <img src="/img/hero-wide-1200.jpg" alt="Kevätkokoelma" width="1200" height="800">
</picture>

fetchpriority ja LCP-kuvan priorisointi

fetchpriority-attribuutti (Chromium 101+, Safari 17.2+, Firefox 132+) kertoo selaimelle, että tietty resurssi pitää siirtää muiden edelle selaimen sisäisessä latausjonossa. LCP-kuvalle asetettu fetchpriority="high" tuottaa Chromen omissa mittauksissa mediaanissa 200–400 ms parannuksen Largest Contentful Paintiin, koska selain ei odota CSS:n tai muiden kuvien lataamista ennen kuin aloittaa LCP-kuvan haun.

<!-- Yläreunan hero-kuva, joka on todennäköisesti LCP-elementti -->
<img src="/img/hero-1200.avif"
     srcset="..."
     sizes="100vw"
     alt="..."
     width="1200" height="600"
     fetchpriority="high">

<!-- Kuva, jonka selain saa deprioritisoida (esim. skrollattava karuselli) -->
<img src="/img/gallery-2.avif"
     alt="..."
     width="600" height="400"
     loading="lazy"
     fetchpriority="low">

Vaihtoehto fetchpriority:lle on <link rel="preload" as="image"> dokumentin <head>ssä, mutta vuonna 2026 fetchpriority on parempi ratkaisu, koska se ei duplikoi kuvan URL:ia ja se toimii responsiivisten kuvien kanssa mutkattomasti. Jos silti käytät preloadia, muista imagesrcset- ja imagesizes-attribuutit:

<link rel="preload"
      as="image"
      href="/img/hero-1200.avif"
      imagesrcset="/img/hero-800.avif 800w, /img/hero-1200.avif 1200w, /img/hero-1600.avif 1600w"
      imagesizes="100vw"
      fetchpriority="high"
      type="image/avif">

Katso lisätaustaa LCP-optimoinnin käytännön oppaasta, jossa käsittelen kuvaresurssien priorisointia laajemmin osana kriittistä renderöintipolkua.

Lazy loading oikein: milloin ja miten

loading="lazy" on natiivi selain-attribuutti, joka lykkää kuvan latausta kunnes se on lähellä viewportia. Se toimii kaikissa vihreissä selaimissa ilman IntersectionObserver-koodia. Yleisin virhe on lisätä se kaikkiin sivun kuviin, mukaan lukien LCP-kuva. Silloin selain viivyttää LCP-latausta ja Lighthouse rankaisee sivua "Largest Contentful Paint image was lazily loaded" -varoituksella.

Sääntö on yksinkertainen: fold-linjan yläpuolella olevat kuvat eivät ole koskaan lazy. Fold-linjan alla olevat ovat aina lazy. Käytännössä tämä tarkoittaa yleensä:

  • Hero-kuva ja above-the-fold -tuotekuvat: fetchpriority="high", EI loading="lazy".
  • Karusellin ensimmäinen slide: fetchpriority="high", muut loading="lazy".
  • Tuotelistauksen ensimmäiset 4–6 riviä: eager (default). Loput: loading="lazy".
  • Footerin logot ja alaviitteen kuvat: aina loading="lazy".

Iframejen kohdalla sama pätee: <iframe loading="lazy"> on erinomainen YouTube-embedien ja Google Maps -upotusten kohdalla, jotka usein tuovat sivuun 500 kt+ ylimääräistä JavaScriptiä. Tämä liittyy laajempaan aiheeseen, jota käsittelin kolmannen osapuolen skriptien optimointi -artikkelissa.

Kuvaputken rakentaminen: sharp, squoosh ja CDN

Responsiiviset kuvat vaativat useita variantteja per kuva. Käsin generointi ei skaalaudu (kokeilin sitä kerran, kesti kaksi iltaa liian kauan). Vuonna 2026 näen kolme yleistä ratkaisua:

1. Build-aikainen prosessointi (sharp / squoosh)

Node-pohjaiset työkalut kuten sharp (libvips-käärö) generoivat variantit rakennusvaiheessa. Tämä sopii projekteihin, joissa kuvia ei lisätä usein ja jotka ovat versionhallinnassa. Esimerkki Node-skripti, joka luo AVIF- ja WebP-variantit 400/800/1200/1600 px leveyksinä:

import sharp from 'sharp';
import { readdir } from 'node:fs/promises';
import path from 'node:path';

const SRC = './src/images';
const OUT = './public/img';
const WIDTHS = [400, 800, 1200, 1600, 2400];
const FORMATS = [
  { ext: 'avif', options: { quality: 55, effort: 6 } },
  { ext: 'webp', options: { quality: 78 } },
  { ext: 'jpg',  options: { quality: 82, mozjpeg: true } },
];

for (const file of await readdir(SRC)) {
  const base = path.parse(file).name;
  const input = sharp(path.join(SRC, file));
  const meta = await input.metadata();

  for (const w of WIDTHS) {
    if (meta.width < w) continue;
    for (const { ext, options } of FORMATS) {
      await input
        .clone()
        .resize({ width: w, withoutEnlargement: true })
        .toFormat(ext, options)
        .toFile(`${OUT}/${base}-${w}.${ext}`);
    }
  }
}

AVIF-enkoodaus on hidasta (effort: 6 voi kestää useita sekunteja per kuva), joten aja se CI:ssä välimuistilla, älä paikallisesti jokaisella save-hetkellä. GitHub Actionsissa cache voi olla ./public/img-hakemiston hash.

2. Runtime-CDN (Cloudinary, Imgix, Cloudflare Images)

Kuva-CDN palvelee variantteja query-parametrien perusteella: ?w=800&fm=avif&q=55. Sopii, kun kuvien määrä on suuri tai käyttäjät lataavat niitä (esim. UGC). Kalliimpi mutta joustava. Cloudflare Imagesin hinnoittelu vuonna 2026 alkaa noin 5 dollarista/kk 100 000 kuvasta ja skaalautuu lineaarisesti.

3. Framework-integraatiot

Next.js, Astro ja Nuxt tarjoavat sisäänrakennetut <Image>-komponentit, jotka hoitavat prosessoinnin, srcset-generoinnin ja formaattineuvottelun puolestasi. Käytä näitä, jos frameworkkisi tarjoaa ne. DIY-toteutus on harvoin sen arvoinen.

Next.js, Astro ja Nuxt: valmiit ratkaisut

Kolme yleisintä frameworkkia hoitavat responsiiviset kuvat lähes automaattisesti. Näin ne käytännössä toimivat vuonna 2026:

OminaisuusNext.js 15 next/imageAstro 5 <Image>Nuxt 3 <NuxtImg>
Automaattinen srcsetKylläKylläKyllä
AVIF-tuki oletuksenaKonfiguroitavaKylläKyllä
Runtime vs. buildRuntime (Vercel) tai buildBuildMolemmat
Lazy loadingOletuksena päälläOletuksena päälläOletuksena päällä
fetchprioritypriority-proploading="eager"preload-prop
Placeholder (blur)Kyllä, LQIP tai base64KylläKyllä

Next.js 15 -esimerkki

import Image from 'next/image';
import hero from '@/public/hero.jpg';

export default function Home() {
  return (
    <Image
      src={hero}
      alt="Tuotekuva keltaisesta juoksukengästä"
      priority           // asettaa fetchpriority="high" ja preloadin
      sizes="(min-width: 1200px) 1140px, 100vw"
      placeholder="blur"
    />
  );
}

Next.jsin next.config.js:ssä muista määrittää images.formats: ['image/avif', 'image/webp'], jotta AVIF-neuvottelu on päällä. Katso Next.js Image-komponentin virallinen dokumentaatio täydellisen parametrilistan osalta.

Astro 5 -esimerkki

---
import { Image } from 'astro:assets';
import hero from '../assets/hero.jpg';
---
<Image
  src={hero}
  alt="Hero-kuva"
  widths={[400, 800, 1200, 1600]}
  sizes="(min-width: 1200px) 1140px, 100vw"
  formats={['avif', 'webp']}
  loading="eager"
/>

Lighthouse-tarkistuslista ja mittaus

Kun olet toteuttanut yllä olevat, aja Lighthouse tai PageSpeed Insights ja tarkista nämä auditit vihreiksi:

  • Properly size images: kuvat eivät ole enempää kuin 1 × näytöllä näkyvä koko.
  • Serve images in next-gen formats: AVIF/WebP käytössä JPEG:n sijaan.
  • Efficiently encode images: laatuparametrit tarpeeksi matalalla (AVIF 45–60, WebP 75–80).
  • Defer offscreen images: fold-linjan alla olevat käyttävät loading="lazy".
  • Preload Largest Contentful Paint image: LCP-kuvalla on fetchpriority="high" tai preload.
  • Image elements do not have explicit width and height: jokaisella kuvalla on width- ja height-attribuutit.

Käytännön RUM-mittausta varten seuraa Largest Contentful Paint -metriikkaa web-vitals-kirjaston avulla ja segmentoi laitetyypin sekä yhteyden nopeuden mukaan. Näet suoraan, kuinka paljon responsiivisten kuvien käyttöönotto on vaikuttanut oikeilla käyttäjillä, ei vain lab-mittauksissa.

Usein kysytyt kysymykset

Mitä eroa on srcset- ja sizes-attribuuteilla?

srcset luettelee saatavilla olevat kuvavariantit ja niiden todelliset pikselileveydet. sizes kertoo selaimelle, miten leveänä kuva näkyy eri viewport-leveyksillä. Selain käyttää molempia yhdessä valitakseen pienimmän kuvan, joka vielä näyttää terävältä laitteen DPR:llä.

Onko AVIF parempi kuin WebP vuonna 2026?

Kyllä useimmissa tapauksissa: AVIF-tiedostot ovat 20–30 % pienempiä kuin WebP samalla PSNR-laadulla. Enkoodaus on hitaampaa, joten se sopii parhaiten build-aikaiseen prosessointiin tai CDN-välimuistiin. Pidä WebP fallbackina vanhoille Safari-versioille (iOS 14, 15).

Milloin fetchpriority-attribuuttia kannattaa käyttää?

Aseta fetchpriority="high" vain LCP-kuvalle, yleensä yksi hero- tai above-the-fold -kuva per sivu. Käytä fetchpriority="low" lazy-ladatuille kuville, jotka voidaan viivyttää. Useampi high-prioriteettinen resurssi nollaa hyödyn.

Miksi Lighthouse varoittaa LCP-kuvan lazy loadingista?

Koska loading="lazy" viivyttää LCP-kuvan latausta, kunnes selain päättää sen olevan lähellä viewportia. Se lisää LCP-aikaa satoja millisekunteja. Jätä lazy loading pois kaikilta fold-linjan yläpuolelta löytyviltä kuvilta.

Tarvitseeko width- ja height-attribuutit vaikka CSS venyttää kuvaa?

Kyllä, ehdottomasti. Attribuutit määrittävät kuvan aspektisuhteen, jotta selain voi varata tilaa ennen kuvan latautumista. Ilman niitä sivu hyppii kuvan latautuessa ja Cumulative Layout Shift -pisteesi kärsivät. CSS voi silti asettaa width: 100%; height: auto.

Tietoa Kirjoittajasta Priya Ravindran

Priya is a frontend performance engineer with 11 years of experience untangling slow React and Next.js apps. She spent four years at Shopify on the Storefront Performance team, where she drove a project that cut median LCP across the Online Store theme platform from 3.4s to 1.8s by rewriting the critical render path and killing third-party tag bloat. Before that she shipped checkout perf work at Klarna. These days she runs an independent practice helping Series B/C ecommerce companies hit a 75th-percentile INP under 200ms before they bother with redesigns. She has a soft spot for Lighthouse CI in pull-request gates and writes most of her perf budgets in YAML. Outside work she's slowly restoring a 1998 Honda CB400 and arguing with her partner about whether RUM beats lab data (it does).