Dalam modul ini, Anda akan mempelajari cara memberi browser pilihan gambar sehingga browser dapat membuat keputusan terbaik tentang apa yang akan ditampilkan. srcset
bukanlah metode untuk menukar sumber gambar pada titik henti sementara tertentu, dan tidak dimaksudkan untuk menukar satu gambar dengan gambar lainnya. Sintaks ini memungkinkan
browser untuk memecahkan masalah yang sangat sulit, terlepas dari kami: meminta dan merender sumber gambar yang disesuaikan dengan konteks penjelajahan pengguna dengan lancar,
termasuk ukuran area pandang, kepadatan tampilan, preferensi pengguna, bandwidth, dan berbagai faktor lainnya.
Ini pertanyaan yang besar—tentunya lebih dari sekadar memikirkan hal ini saat kita hanya memberi markup suatu gambar untuk web, dan melakukannya dengan baik melibatkan lebih banyak hal
informasi daripada yang
dapat kita akses.
Menjelaskan kepadatan dengan x
<img>
dengan lebar tetap akan menempati area pandang yang sama dalam konteks penjelajahan apa pun, terlepas dari kepadatan pengguna
tampilan—jumlah {i>pixel<i} fisik yang membentuk layarnya. Misalnya, gambar dengan lebar inheren 400px
akan menempati hampir
seluruh area pandang browser di Google Pixel asli dan Pixel 6 Pro yang jauh lebih baru—kedua perangkat memiliki 412px
yang dinormalkan
area pandang lebar piksel logis.
Namun, Pixel 6 Pro memiliki layar yang jauh lebih tajam: 6 Pro memiliki resolusi fisik sebesar 1440 × 3120 piksel, sedangkan
Pixel berukuran 1080 × 1920 piksel—yaitu, jumlah piksel hardware yang membentuk layar itu sendiri.
Rasio antara piksel logis perangkat dan piksel fisik adalah rasio piksel perangkat untuk tampilan tersebut (DPR). DPR adalah
dihitung dengan membagi resolusi layar perangkat yang sebenarnya dengan piksel CSS area pandang.
Jadi, Pixel yang asli memiliki DPR 2,6, sedangkan Pixel 6 Pro memiliki DPR 3,5.
iPhone 4, perangkat pertama dengan DPR lebih besar dari 1, melaporkan rasio {i>pixel<i} perangkat sebesar 2—resolusi fisik layar adalah
menggandakan resolusi logis. Setiap perangkat sebelum iPhone 4 memiliki DPR 1: satu piksel logis hingga satu piksel fisik.
Jika Anda melihat gambar selebar 400px
tersebut di layar dengan DPR 2
, setiap piksel logis dirender di empat bagian
piksel fisik tampilan: dua horizontal dan dua vertikal. Gambar tidak mendapatkan manfaat dari layar berkepadatan tinggi—gambar akan terlihat
sama seperti yang akan ditampilkan pada layar dengan DPR 1
. Tentu saja, apa pun yang "digambar" oleh mesin rendering browser—teks, bentuk CSS, atau SVG,
misalnya—akan digambar agar sesuai dengan layar dengan kepadatan yang lebih tinggi. Namun, seperti yang Anda pelajari dari Format dan Kompresi Gambar, gambar raster bersifat tetap
{i>grid<i} piksel. Meskipun mungkin tidak selalu tampak jelas, gambar raster yang ditingkatkan kualitasnya agar sesuai dengan layar yang memiliki kepadatan lebih tinggi akan terlihat
resolusi rendah
dibandingkan dengan halaman sekitarnya.
Untuk mencegah peningkatan skala ini, gambar yang dirender harus memiliki lebar intrinsik minimal 800
piksel. Saat diperkecil
agar sesuai dengan ruang dalam tata letak dengan lebar 400 piksel logis, sumber gambar 800 piksel tersebut memiliki kepadatan piksel dua kali lipat—pada layar dengan DPR 2
,
itu akan terlihat
bagus dan tajam.
Karena layar dengan DPR 1
tidak dapat memanfaatkan kepadatan gambar yang ditingkatkan, skala gambar akan diperkecil agar sesuai dengan
— dan seperti yang Anda ketahui, gambar yang diperkecil akan terlihat baik-baik saja. Pada layar berkepadatan rendah, gambar cocok untuk kepadatan lebih tinggi
tampilan layar akan terlihat seperti gambar kepadatan rendah lainnya.
Seperti yang Anda pelajari pada Gambar dan Performa, pengguna dengan layar berkepadatan rendah yang melihat sumber gambar diperkecil menjadi 400px
hanya memerlukan sumber dengan lebar inheren 400px
. Meskipun gambar yang jauh lebih besar akan sesuai
untuk semua pengguna secara visual,
sumber gambar beresolusi tinggi yang dirender pada layar kecil dan kepadatan rendah akan terlihat seperti gambar kecil lainnya dengan kepadatan rendah, tetapi terasa jauh lebih lambat.
Seperti yang mungkin Anda duga, perangkat seluler dengan DPR 1 sangat jarang,
meskipun masih biasa di "desktop" konteks penjelajahan. Menurut data
dibagikan oleh Matt Hobbs, sekitar 18% sesi penjelajahan GOV.UK dari November 2022 melaporkan DPR 1. Meskipun gambar berkepadatan tinggi akan terlihat seperti yang diharapkan pengguna, gambar tersebut akan memerlukan bandwidth dan biaya pemrosesan yang jauh lebih tinggi—yaitu
kekhawatiran khusus untuk pengguna pada perangkat yang lebih lama dan kurang canggih masih cenderung memiliki layar kepadatan rendah.
Menggunakan srcset
memastikan bahwa hanya perangkat dengan tampilan resolusi tinggi yang menerima sumber gambar yang cukup besar untuk terlihat tajam, tanpa meneruskan sumber gambar yang sama
biaya {i>bandwidth<i} pada pengguna dengan
tampilan resolusi yang lebih rendah.
Atribut srcset
mengidentifikasi satu atau beberapa kandidat yang dipisahkan koma untuk merender gambar. Setiap kandidat terdiri dari
dua hal: URL, seperti yang akan Anda gunakan di src
, dan sintaksis yang mendeskripsikan sumber gambar tersebut. Setiap kandidat di srcset
dijelaskan oleh lebar bawaannya ("sintaksis w
") atau kepadatan yang diinginkan ("sintaksis x
").
Sintaksis x
adalah singkatan untuk "sumber ini sesuai untuk tampilan dengan kepadatan ini"—kandidat yang diikuti dengan 2x
adalah
sesuai untuk tampilan dengan DPR 2.
<img src="low-density.jpg" srcset="double-density.jpg 2x" alt="...">
Browser yang mendukung srcset
akan diberi dua kandidat: double-density.jpg
, yang dijelaskan 2x
sebagai yang sesuai
untuk tampilan dengan DPR 2, dan low-density.jpg
dalam atribut src
—kandidat yang dipilih jika tidak ada yang lebih sesuai
ditemukan di srcset
. Bagi browser yang tidak mendukung srcset
, atribut dan kontennya akan diabaikan—konten src
akan diminta, seperti biasa.
Nilai yang ditentukan dalam atribut srcset
mudah disalahartikan sebagai petunjuk. 2x
tersebut memberi tahu browser bahwa
akan sesuai untuk digunakan pada tampilan dengan DPR 2—informasi tentang sumber itu sendiri. Tidak memberi tahu
{i>browser<i} bagaimana menggunakan sumber tersebut, hanya
memberi tahu {i>browser<i} bagaimana sumber tersebut dapat digunakan. Ini adalah perbedaan yang kecil,
tapi penting: ini
adalah gambar kepadatan ganda, bukan gambar untuk digunakan pada tampilan kepadatan ganda.
Perbedaan antara sintaksis yang menyatakan "sumber ini sesuai untuk tampilan 2x
" dan yang bertuliskan "gunakan sumber ini di layar 2x
"
sedikit di cetak, tetapi kepadatan tampilan hanyalah salah satu dari sekian banyak faktor yang saling berkaitan yang digunakan browser untuk memutuskan kandidat
dirender, hanya beberapa yang
bisa Anda ketahui. Misalnya: satu per satu, Anda dapat menentukan apakah pengguna telah mengaktifkan
preferensi browser hemat bandwidth melalui kueri media prefers-reduced-data
, dan gunakan kueri tersebut untuk selalu mengikutsertakan pengguna ke gambar yang berkepadatan rendah
terlepas dari kepadatan tampilan mereka—tetapi jika tidak diterapkan secara konsisten, oleh setiap developer, di setiap situs, hal tersebut tidak akan banyak berguna bagi pengguna.
Mereka mungkin mendapatkan preferensi yang dihormati di satu situs, dan menemui dinding gambar yang merusak bandwidth di situs berikutnya.
Algoritma pemilihan resource yang sengaja tidak jelas yang digunakan oleh srcset
/sizes
memberi ruang bagi browser untuk memutuskan kepadatan yang lebih rendah
gambar dengan penurunan bandwidth, atau berdasarkan preferensi untuk meminimalkan penggunaan data, tanpa kami bertanggung jawab atas bagaimana, atau kapan, atau pada
ambang batas apa. Tidak ada gunanya mengambil tanggung jawab—dan menambah pekerjaan—sehingga browser lebih siap menanganinya untuk Anda.
Mendeskripsikan lebar dengan w
srcset
menerima jenis deskripsi kedua untuk kandidat sumber gambar. Alat ini jauh lebih ampuh—dan untuk tujuan kita,
akan jauh lebih
mudah dipahami. Daripada menandai kandidat sebagai memiliki dimensi yang sesuai untuk kepadatan tampilan tertentu,
sintaksis w
menjelaskan lebar yang melekat pada setiap sumber kandidat. Sekali lagi, setiap kandidat identik
konten, pemangkasan yang sama, dan rasio aspek yang sama. Namun dalam kasus ini, Anda ingin browser pengguna memilih di antara dua kandidat:
{i>small.jpg<i}, sumber dengan lebar inheren 600px, dan large.jpg, sumber dengan lebar inheren 1200px.
srcset="small.jpg 600w, large.jpg 1200w"
Ini tidak memberi tahu browser apa yang harus dilakukan dengan informasi ini—hanya memberinya daftar kandidat untuk menampilkan gambar.
Sebelum browser bisa membuat keputusan tentang sumber mana yang akan dirender, Anda perlu memberikannya sedikit informasi tambahan: a
deskripsi tentang cara merender gambar di halaman. Untuk melakukannya, gunakan atribut sizes
.
Mendeskripsikan penggunaan dengan sizes
Browser memiliki performa yang luar biasa dalam hal mentransfer gambar. Permintaan aset gambar akan dimulai dalam waktu lama
sebelum permintaan stylesheet atau JavaScript—sering kali bahkan sebelum markup telah diurai sepenuhnya. Saat browser
membuat permintaan ini, tidak memiliki informasi tentang halaman itu sendiri, terlepas dari markup—bahkan mungkin tidak memulai permintaan
untuk stylesheet eksternal, apalagi menerapkannya. Pada saat browser mengurai markup Anda dan mulai membuat
permintaan, hanya memiliki informasi tingkat browser: ukuran area pandang pengguna, kepadatan piksel layar pengguna,
preferensi pengguna, dan sebagainya.
Ini tidak memberi tahu kita apa pun tentang bagaimana gambar dimaksudkan untuk dirender dalam tata letak halaman—bahkan tidak dapat menggunakan area pandang
sebagai proxy untuk batas atas ukuran img
, karena dapat menempati penampung scroll horizontal. Kita perlu
memberikan informasi ini ke browser dan melakukannya dengan menggunakan markup. Hanya itu yang dapat kita gunakan untuk permintaan ini.
Seperti srcset
, sizes
dimaksudkan untuk membuat informasi tentang gambar tersedia segera setelah markup diuraikan. Sama seperti srcset
adalah singkatan dari "ini adalah file sumber dan ukurannya yang melekat," atribut sizes
adalah singkatan dari "di sini
adalah ukuran gambar yang dirender dalam tata letak". Cara Anda mendeskripsikan gambar relatif terhadap area pandang—sekali lagi, area pandang
adalah satu-satunya informasi tata letak yang
dimiliki browser saat permintaan gambar dibuat.
Hal ini mungkin terdengar sedikit bertele-tele, tetapi dalam praktiknya jauh lebih mudah untuk dipahami:
<img
sizes="80vw"
srcset="small.jpg 600w, medium.jpg 1200w, large.jpg 2000w"
src="fallback.jpg"
alt="...">
Di sini, nilai sizes
ini memberi tahu browser bahwa ruang dalam tata letak yang ditempati img
memiliki lebar 80vw
—80%
area pandang. Ingat, ini bukan petunjuk, tetapi deskripsi ukuran gambar dalam tata letak halaman. Tidak ada keterangan
"buat ini
gambar menempati 80% dari area pandang," tetapi "gambar ini akan menempati 80% dari area pandang setelah halaman dirender."
Sebagai pengembang, pekerjaan Anda sudah selesai. Anda telah menjelaskan daftar sumber kandidat dalam srcset
dan lebar gambar Anda secara akurat
di sizes
, dan, seperti halnya sintaksis x
di srcset
, sisanya bergantung pada browser.
Tetapi untuk memahami sepenuhnya bagaimana informasi ini digunakan, mari kita luangkan waktu sejenak untuk mengambil keputusan yang
yang dilakukan browser pengguna saat menemukan markup ini:
Anda telah memberi tahu browser bahwa gambar ini akan menempati 80% dari area pandang yang tersedia—jadi, jika kita merender img
ini pada
perangkat dengan area pandang selebar 1000 piksel, gambar ini akan menempati 800 piksel. {i>Browser<i} kemudian akan mengambil
nilai itu dan membagi terhadap
lebar setiap kandidat sumber gambar yang telah kita tentukan di srcset
. Sumber terkecil memiliki
ukuran inheren 600 {i>pixel<i},
jadi: 600÷800=0,75. Gambar medium kami adalah lebar 1200 piksel: 1200÷800=1,5. Gambar terbesar kami adalah lebar 2000 piksel: 2000÷800=2,5.
Hasil penghitungan tersebut (.75
, 1.5
, dan 2.5
) adalah opsi DPR yang khusus disesuaikan dengan
ukuran area tampilan. Karena browser juga memiliki informasi tentang kepadatan tampilan pengguna, browser membuat serangkaian keputusan:
Pada ukuran area pandang ini, kandidat small.jpg
akan dihapus terlepas dari kepadatan tampilan pengguna—dengan DPR yang dihitung lebih rendah
dari 1
, sumber ini akan memerlukan peningkatan skala untuk semua pengguna, sehingga tidak sesuai. Pada perangkat dengan DPR 1
, medium.jpg
menyediakan
kecocokan terdekat—sumber tersebut sesuai untuk ditampilkan pada DPR 1.5
, sehingga sedikit lebih besar dari yang diperlukan, tetapi perlu diingat bahwa downscaling
proses yang mulus secara visual. Pada perangkat dengan DPR 2, large.jpg
adalah kecocokan terdekat sehingga akan dipilih.
Jika gambar yang sama dirender pada area pandang lebar 600 piksel, hasil dari semua perhitungan tersebut akan menjadi sangat berbeda: 80vw sekarang menjadi 480px.
Ketika kita membagi sumber lebarnya, kita akan mendapatkan 1.25
, 2.5
, dan 4.1666666667
. Pada ukuran area pandang ini, small.jpg
akan dipilih
pada 1x perangkat, dan medium.jpg
akan cocok di 2x perangkat.
Gambar ini akan terlihat sama di semua konteks penjelajahan ini: semua file sumber kita sama persis terlepas dari dimensinya,
dan setiap gambar dirender dengan tajam sesuai kepadatan tampilan pengguna. Namun, bukannya menampilkan large.jpg
kepada setiap pengguna
untuk mengakomodasi area pandang terbesar dan tampilan dengan kepadatan tertinggi, pengguna akan selalu melihat kandidat terkecil yang sesuai.
Dengan menggunakan sintaksis deskriptif, bukan preskriptif, Anda tidak perlu menetapkan titik henti sementara secara manual dan mempertimbangkan area pandang mendatang dan
DPR—Anda cukup memberikan informasi ke browser dan mengizinkannya menentukan jawaban untuk Anda.
Karena nilai sizes
relatif terhadap area pandang dan sepenuhnya tidak bergantung pada tata letak halaman, nilai ini menambahkan lapisan detail.
Jarang ada gambar yang hanya menempati sebagian area tampilan, tanpa margin lebar tetap, padding, atau pengaruh
dari elemen lain pada laman. Anda harus sering menyatakan lebar gambar menggunakan kombinasi satuan; persentase, em
, px
, dan seterusnya.
Untungnya, Anda dapat menggunakan calc()
di sini—browser apa pun dengan dukungan native untuk gambar responsif juga akan mendukung calc()
, sehingga kita dapat
padu padankan unit CSS—misalnya, gambar yang memenuhi lebar penuh area tampilan pengguna, dikurangi margin 1em
di kedua sisi:
<img
sizes="calc(100vw-2em)"
srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1600w, x-large.jpg 2400w"
src="fallback.jpg"
alt="...">
Mendeskripsikan titik henti sementara
Jika Anda telah menghabiskan banyak waktu bekerja dengan tata letak responsif, Anda mungkin melihat sesuatu yang hilang dari contoh-contoh ini:
ruang yang ditempati gambar dalam tata letak sangat mungkin berubah di seluruh titik henti sementara tata letak. Dalam hal ini, Anda perlu
untuk meneruskan detail lebih lanjut ke browser: sizes
menerima kumpulan kandidat yang dipisahkan koma untuk ukuran objek yang dirender
seperti srcset
yang menerima kandidat yang dipisahkan koma untuk sumber gambar. Kondisi tersebut menggunakan sintaksis kueri media yang sudah dikenal.
Sintaksis ini adalah kecocokan pertama: segera setelah kondisi media cocok, browser berhenti menguraikan atribut sizes
, dan nilainya
yang ditentukan akan diterapkan.
Misalnya, Anda memiliki gambar yang dimaksudkan untuk menempati 80% area tampilan, dikurangi satu em
padding di kedua sisi, pada area pandang di atas 1.200 piksel—aktif
area pandang yang lebih kecil, namun akan menempati lebar penuh area pandang.
<img
sizes="(min-width: 1200px) calc(80vw - 2em), 100vw"
srcset="small.jpg 600w, medium.jpg 1200w, large.jpg 2000w"
src="fallback.jpg"
alt="...">
Jika area pandang pengguna lebih besar dari 1.200 piksel, calc(80vw - 2em)
akan menjelaskan lebar gambar dalam tata letak. Jika
Kondisi (min-width: 1200px)
tidak cocok, browser akan berpindah ke nilai berikutnya. Karena tidak ada
kondisi media yang terkait dengan nilai ini, 100vw
digunakan sebagai default. Jika Anda menulis atribut sizes
ini menggunakan
Kueri media max-width
:
<img
sizes="(max-width: 1200px) 100vw, calc(80vw - 2em)"
srcset="small.jpg 600w, medium.jpg 1200w, large.jpg 2000w"
src="fallback.jpg"
alt="...">
Dalam bahasa sederhana: "apakah (max-width: 1200px)
cocok? Jika belum, lanjutkan. Nilai berikutnya—calc(80vw - 2em)
—tidak memiliki kondisi yang memenuhi syarat,
jadi ini adalah yang dipilih.
Setelah memberikan semua informasi tentang elemen img
ini ke browser—sumber potensial, lebar yang melekat,
dan bagaimana Anda ingin menampilkan gambar kepada pengguna—browser menggunakan seperangkat aturan kabur untuk menentukan apa yang harus dilakukan dengan
informasi tersebut. Jika kedengarannya tidak jelas, mungkin karena memang demikian. Algoritma pemilihan sumber yang dienkode dalam
Spesifikasi HTML secara eksplisit samar-samar tentang cara memilih sumber. Setelah sumber, deskripsi mereka, dan bagaimana
gambar akan dirender dan semuanya telah diuraikan, browser bebas melakukan apa pun yang diinginkan—Anda tidak dapat mengetahui dengan pasti
{i>source<i} yang akan
dipilih oleh {i>browser<i}.
Sintaksis yang menyatakan "gunakan sumber ini pada layar resolusi tinggi" dapat diprediksi, tetapi tidak akan membahas masalah intinya
dengan gambar dalam tata letak responsif: menghemat bandwidth pengguna. Kepadatan piksel layar hanya terkait secara langsung dengan internet
kecepatan koneksi, jika ada. Jika Anda menggunakan laptop berkualitas tinggi, tetapi menjelajahi web melalui koneksi berkuota, di-tethering
ke ponsel, atau menggunakan koneksi Wi-Fi pesawat yang goyang—Anda sebaiknya menonaktifkan sumber gambar beresolusi tinggi,
kualitas tampilan Anda.
Memberikan keputusan akhir kepada browser memungkinkan peningkatan kinerja yang jauh lebih banyak daripada yang dapat kami kelola dengan preskriptif yang ketat
sintaksis. Misalnya: di sebagian besar browser, img
yang menggunakan sintaksis srcset
atau sizes
tidak akan pernah merepotkan saat meminta sumber dengan
dimensi dibandingkan dengan yang telah dimiliki pengguna dalam {i>cache<i} browser mereka. Apa gunanya membuat permintaan baru untuk sumber
yang akan terlihat identik, ketika {i>browser<i} dapat dengan mulus memperkecil skala sumber gambar yang sudah dimilikinya? Tetapi jika pengguna meningkatkan
area tampilan hingga titik di mana gambar baru diperlukan untuk menghindari peningkatan skala, tersebut akan tetap dibuat, sehingga semua
terlihat seperti yang Anda harapkan.
Kurangnya kontrol eksplisit itu bisa terasa sedikit menakutkan pada nilai aslinya, tetapi karena Anda menggunakan file sumber dengan
besar, kita tidak lagi menimbulkan
kerusakan pada pengguna dibandingkan dengan yang kami lakukan pada src
sumber tunggal, terlepas dari
keputusan yang dibuat oleh browser.
Menggunakan sizes
dan srcset
Ada banyak informasi—baik untuk Anda, pembaca, maupun browser. srcset
dan sizes
adalah sintaksis padat,
yang menggambarkan sejumlah informasi yang mengejutkan,
dalam jumlah karakter yang relatif sedikit. Yaitu, baik atau buruk, sesuai desain: membuat
sintaksis ini lebih ringkas—dan lebih mudah diurai oleh manusia—dapat membuatnya lebih sulit diurai oleh browser. Tujuan
semakin banyak kompleksitas yang ditambahkan ke string, semakin besar potensi error parser atau perbedaan perilaku yang tidak disengaja
dari satu browser ke browser lain. Namun, ada sisi positifnya: {i>syntax<i} yang lebih mudah dibaca oleh komputer adalah {i>syntax<i} yang lebih mudah ditulis
oleh mereka.
srcset
adalah contoh yang jelas untuk otomatisasi. Jarang sekali Anda membuat beberapa versi gambar dengan tangan untuk
lingkungan production, alih-alih mengotomatiskan proses menggunakan {i>task runner<i} seperti Gulp, pemaket seperti Webpack,
CDN seperti Cloudinary, atau fungsi yang sudah tersedia di CMS pilihan Anda. Memberikan informasi yang cukup untuk membuat sumber
pertama-tama, sistem akan memiliki cukup informasi untuk menulisnya ke dalam atribut srcset
yang valid.
sizes
sedikit lebih sulit untuk diotomatiskan. Seperti yang Anda ketahui, satu-satunya cara sistem
dapat menghitung ukuran gambar dalam
tata letak yang dirender adalah telah merender tata letak. Untungnya, sejumlah alat pengembang
telah bermunculan untuk menyederhanakan
proses penulisan atribut sizes
—dengan efisiensi yang tidak dapat Anda sesuaikan secara manual.
respImageLint, misalnya, adalah cuplikan kode yang dimaksudkan untuk memeriksa atribut sizes
Anda
akurasi dan memberikan saran untuk perbaikan. Project Lazysizes disusupi
beberapa kecepatan demi efisiensi dengan menunda permintaan gambar hingga tata letak dibuat, sehingga JavaScript
menghasilkan nilai sizes
untuk Anda. Jika Anda menggunakan framework rendering sisi klien yang sepenuhnya seperti React atau Vue, ada
sejumlah solusi untuk pembuatan dan/atau pembuatan atribut srcset
dan sizes
, yang akan kita bahas lebih lanjut di CMS dan Framework.