Skip to content

Hint sizes Next.js Jadi Bohong Begitu CSS Max-Width Nge-clamp

Adityo Guni Waluyo

CSS max-width bikin hint sizes next/image menjanjikan slot vw yang salah. Perbaiki pakai nilai piksel biar srcset memilih kandidat yang pas.

Ringkasan

Ganti ukuran gambar pakai CSS doang ternyata nggak cukup, browser masih ngunduh file gede gara-gara hint sizes masih janji 40vw. Solusinya jujur aja tulis nilai piksel langsung di sizes biar sinkron sama clamp-nya. Sekarang tiap utak-atik gambar, cek tab Network udah jadi langkah wajib.

Deploy pertama setelah visual hero diganti maskot elang, saya buka tab Network di DevTools dan langsung curiga. File gambar yang terunduh terasa kegedean untuk sesuatu yang tampil cuma selebar sepertiga kolom. Di layar, maskot itu juga kelihatan nggak seimbang sama hierarki teks di sekitarnya.

Tebakan pertama saya simpel: kecilin aja pakai CSS. Saya ganti className komponen <Image /> jadi rantai max-w-[220px] sm:max-w-[280px] lg:max-w-[330px]. Secara visual hasilnya pas dan proporsional. Saya kira beres dan hampir langsung commit.

Tapi tab Network bilang lain. Browser masih mengunduh kandidat resolusi tinggi, setara slot sekitar 576px, padahal render box-nya sekarang cuma 330px. Ternyata yang bohong bukan CSS-nya, melainkan sizes="(min-width: 1024px) 40vw, 70vw" yang saya warisin dari komponen lama. Clamp visual sudah jalan, tapi hint ukuran yang diberikan ke browser belum diikutsertakan dalam pembaruan.

Janji palsu dari hint sizes

Browser membaca sizes sebagai janji soal lebar slot render gambar, lalu memilih kandidat dari srcset yang paling cocok untuk slot itu. Kalau viewport-nya 1440px, 40vw artinya slot 576px — dan di situ pilihan kandidat dihitung, bukan dari kotak 330px hasil clamp CSS. Gambar yang diunduh pun lebih besar dari kebutuhan render [2].

Kejadian seperti ini sering lolos dari radar karena di layar semuanya terlihat normal; pemborosannya murni di sisi unduhan. Di Next.js, bentuk srcset-nya sendiri ikut ditentukan sizes: tanpa atribut itu, yang digenerate terbatas (1x, 2x) untuk gambar berukuran tetap; dengan atribut itu, muncul srcset penuh ber-descriptor lebar (640w, 750w, dan seterusnya) [2]. web.dev menjelaskan sisi browsernya: dengan descriptor lebar plus sizes, browser menghitung effective pixel density otomatis lalu memilih kandidat terbaik untuk slot yang dijanjikan [3]. Selama janjinya 40vw padahal realitanya 330px, semua kalkulasi rapi itu melayani angka yang salah.

Solusi: nilai piksel di dalam sizes

Solusinya bukan nebak-nebak vw lagi, tapi jujur soal kotak render. Nilai piksel di dalam sizes itu sepenuhnya legal [2] dan justru yang mendeskripsikan clamp saya secara eksak. Versi sebelumnya:

sizes="(min-width: 1024px) 40vw, 70vw"
className="h-auto w-auto max-w-full"

Versi sesudahnya memakai slot piksel yang sinkron dengan rantai clamp:

sizes="(min-width: 1024px) 330px, 60vw"
className="h-auto w-full max-w-[220px] sm:max-w-[280px] lg:max-w-[330px]"

Pasangan properti width dan height juga sering disalahpahami sebagai penentu ukuran di layar. Padahal keduanya cuma menyimpan ukuran intrinsik untuk rasio aspek dan reservasi ruang biar layout nggak lompat saat gambar loading [1]. Dokumen Next.js menyebutnya eksplisit: ukuran render tetap urusan CSS [2]. Kalau atribut sizes nggak diisi sama sekali, browser mengasumsikan gambar selebar viewport penuh dan mengunduh lebih besar dari perlu [2] — asumsi yang jelas salah untuk komponen hero yang ukurannya dikunci batas maksimal.

Kebiasaan baru yang worth it

Sekarang saya lebih milih nilai piksel absolut di sizes kapan pun komponennya punya batas ukuran tetap di breakpoint tertentu. Nggak ada lagi kalkulasi vw yang rapuh terhadap perubahan clamp; hint-nya prediktif dan gampang di-debug. Kalau nanti layoutnya memang proporsional terhadap viewport, baru vw masuk akal.

Kontrak sizes–srcset yang melenceng diam-diam itu mahal harganya, dan yang bayar pengguna dengan koneksi pas-pasan. Karena itu cek tab Network setelah utak-atik konfigurasi gambar sekarang jadi langkah wajib sebelum saya nyebut sebuah perubahan visual sudah beres.

Sumber

Artikel terkait