Optimasi gambar artinya dua hal: bikin file gambar sekecil mungkin tanpa kelihatan jelek, dan memberi tahu browser ukuran gambarnya sebelum filenya datang. Gambar sering jadi bagian terbesar dari berat sebuah halaman, jadi di sinilah penghematan paling gampang. Mirip kirim foto lewat WhatsApp: foto 3,6 MB dari kamera dikecilkan dan dikompres jadi ratusan KB, dan di HP temanmu tetap kelihatan bagus.
🧪 Tebakan cepat: foto kamera 4000 × 3000 piksel (sekitar 3,6 MB) ditampilkan di kotak 800 × 600. Kalau filenya di-resize ke 800 × 600 dengan kualitas yang sama, ukurannya kira-kira jadi 1,8 MB, 720 KB, atau 144 KB? Tebak dulu, jawabannya ada di bagian "Ukuran file yang pas".
Ukuran file yang pas
CSS cuma mengubah ukuran tampil. Kalau filenya 4000 × 3000, browser tetap mengunduh semua pikselnya, lalu mengecilkannya di layar. Sisanya dibuang percuma.
Hitung pikselnya: 4000 × 3000 = 12 juta piksel, sedangkan 800 × 600 = 480 ribu piksel. Lebarnya 5 kali, tingginya 5 kali, jadi pikselnya 5 × 5 = 25 kali lebih banyak. Di kualitas yang sama, ukuran file ikut kira-kira 25 kali lebih kecil: 3,6 MB jadi sekitar 144 KB. Itu jawaban tebakannya.
Ini foto yang sama di Lab, langkah demi langkah:
| Langkah | Ukuran file | Unduh di 4G lambat (1,6 Mbps) |
|---|---|---|
| Asli dari kamera, 4000 × 3000, JPEG kualitas 95 | sekitar 3,6 MB | 18 detik |
| Resize ke 800 × 600 | sekitar 144 KB | 0,7 detik |
| Kompres ke kualitas 80 | sekitar 80 KB | 0,4 detik |
| Simpan sebagai WebP | sekitar 53 KB | 0,3 detik |
Layar HP yang tajam kadang butuh 2 kali lipat piksel supaya gambar gak buram. Cara menyediakan beberapa ukuran sekaligus ada di pelajaran Responsive Images.
Kompres: lossy dan lossless
- Lossy membuang detail yang hampir gak kelihatan mata. JPEG di kualitas 75 sampai 85 biasanya sudah cukup untuk foto, dan jauh lebih kecil dari kualitas 95 atau 100.
- Lossless gak mengubah satu piksel pun. Yang dirapikan cara menyimpannya, plus metadata dibuang: info kamera, tanggal, bahkan lokasi GPS (EXIF) yang ikut tersimpan di foto.
- Format modern seperti WebP dan AVIF menyimpan gambar yang sama dengan lebih sedikit byte. Detailnya di pelajaran Format Gambar Modern.
Jadi cara paling ampuh mengecilkan file tanpa kualitas kelihatan turun: kompres lossless (buang metadata), lalu konversi ke format modern seperti WebP. Alatnya: squoosh.app di browser, atau library sharp di Node.js:
import sharp from 'sharp';
await sharp('foto-asli.jpg') // 4000 × 3000, sekitar 3,6 MB
.resize({ width: 800 }) // 800 × 600, rasionya tetap
.webp({ quality: 80 }) // kompres ke WebP
.toFile('photo.webp'); // sekitar 53 KB, metadata ikut dibuang
Kasih tahu ukurannya: width dan height
Tanpa width dan height, browser gak tahu tinggi gambar sampai filenya selesai diunduh. Jadi dia menyisakan tinggi 0, menyusun teks di bawahnya, lalu waktu foto datang semua teks didorong ke bawah. Pergeseran mendadak ini disebut layout shift, dan totalnya diukur dengan CLS (Cumulative Layout Shift): bagus kalau sampai 0,1, buruk kalau di atas 0,25.
Di Lab, artikelnya dibuka di HP selebar 360 px. Fotonya tampil 328 × 246 px. Tanpa ukuran, paragraf di bawahnya loncat 246 px: CLS 0,27, merah. Dengan width="800" height="600", browser langsung tahu rasionya 4:3 dan menyisakan kotak 328 × 246 dari awal: CLS 0.
<style>
img { max-width: 100%; height: auto; }
</style>
<img
src="photo.jpg"
width="800"
height="600"
loading="lazy"
alt="Pemandangan gunung saat matahari terbit"
/>
width="800"danheight="600": ukuran asli file dalam piksel, angka saja tanpapx. Browser memakainya untuk menghitung rasio dan menyisakan tempat.max-width: 100%; height: auto;di CSS: gambar boleh mengecil mengikuti layar, dan tingginya dihitung dari rasio tadi.loading="lazy": foto ini ada di bawah layar pertama, jadi unduhannya ditunda sampai kamu scroll mendekatinya. Detailnya di pelajaran Lazy Loading. Jangan pasang di gambar paling atas yang langsung terlihat.alt: teks pengganti untuk pembaca layar dan saat gambar gagal dimuat. Tulis apa isi gambarnya, bukan dikosongkan.
⚠️ Jebakan yang sering ketemu
- Mengecilkan pakai CSS saja.
width: 400pxdi CSS gak mengurangi satu byte pun. Resize filenya. - width dan height salah tulis. Pakai angka tanpa
px, dan rasionya harus sama dengan file aslinya. Kalau di CSS kamu set tinggi tetap tanpaheight: auto, gambarnya gepeng. loading="lazy"di gambar paling atas. Gambar utama yang langsung terlihat jadi telat diunduh, dan LCP memburuk.altkosong atau asal.alt=""cuma untuk gambar hiasan. Foto yang punya isi butuh deskripsi, bukan"gambar"atau nama filenya.
TL;DR: Browser mengunduh semua piksel file, berapa pun ukuran tampilnya: foto 4000 × 3000 di kotak 800 × 600 berarti 25 kali piksel terbuang, jadi resize filenya. Lalu kompres (lossy di kualitas sekitar 80, lossless untuk membuang metadata) dan pakai format modern seperti WebP: 3,6 MB bisa jadi sekitar 53 KB. Selalu tulis width dan height (angka tanpa px) supaya browser menyisakan tempat dan CLS-nya 0, dengan CSS max-width: 100%; height: auto;. Gambar di bawah layar pertama diberi loading="lazy", dan setiap foto diberi alt yang menjelaskan isinya.