Responsive image delivery

반응형 이미지 전송

The browser selects an image candidate suited to its display size and density.

···
html
<div class="atlas"><div class="head"><b>RESPONSIVE IMAGES · source choice</b><span class="pulse"></span></div><div class="stage"><div class="ri-view box"><div class="ri-photo" id="ri-photo"><b>image</b></div><div class="ri-width" id="ri-width">viewport 360px</div></div><div class="ri-choices mono"><span id="ri-small">400w<br>42 KB</span><span id="ri-medium">800w<br>110 KB</span><span id="ri-large">1200w<br>240 KB</span></div><input id="ri-slider" type="range" min="0" max="2" step="1" value="0" aria-label="Viewport size"></div></div>
css
.atlas{width:min(94vw,720px);height:min(88vh,320px);border:1px solid var(--line);border-radius:14px;background:var(--surface);padding:clamp(10px,2.5vmin,18px);display:flex;flex-direction:column;gap:clamp(7px,2vmin,12px);font:500 clamp(12px,3.2vmin,16px)/1.25 var(--font-sans),sans-serif;color:var(--fg);box-shadow:0 8px 28px rgba(0,0,0,.06)}.head{display:flex;align-items:center;justify-content:space-between;color:var(--accent);letter-spacing:.03em}.pulse{width:8px;height:8px;border-radius:50%;background:var(--accent);animation:blink 1.3s infinite}@keyframes blink{50%{opacity:.2}}.stage{flex:1;min-height:0;position:relative;overflow:hidden}.mono{font-family:ui-monospace,SFMono-Regular,Consolas,monospace}.muted{color:var(--muted)}.accent{color:var(--accent)}.box{border:1px solid var(--line);border-radius:8px;background:var(--bg)}.ri-view{height:47%;display:flex;align-items:center;justify-content:space-between;padding:9px;gap:9px}.ri-photo{width:35%;height:100%;border-radius:6px;background:linear-gradient(145deg,var(--accent-3),var(--accent));display:grid;place-items:center;color:white;transition:width .5s}.ri-width{font-size:12px;color:var(--accent)}.ri-choices{display:flex;gap:3px;margin-top:6px}.ri-choices span{flex:1;border:1px solid var(--line);border-radius:4px;padding:2px;text-align:center;font-size:12px;line-height:1.1}.ri-choices span.on{border-color:var(--accent);color:var(--accent)}#ri-slider{width:100%;margin-top:5px;accent-color:var(--accent)}
js
let choice=0;const widths=[360,720,1080];function show(n){choice=n;document.getElementById('ri-photo').style.width=[35,58,75][n]+'%';document.getElementById('ri-width').textContent='viewport '+widths[n]+'px';['small','medium','large'].forEach((id,i)=>document.getElementById('ri-'+id).classList.toggle('on',i===n));document.getElementById('ri-slider').value=String(n)}show(0);setInterval(()=>show((choice+1)%3),1300);document.getElementById('ri-slider').oninput=e=>show(Number(e.target.value))

srcset lists candidate image widths, while sizes describes the expected display width. The browser uses those hints plus viewport and display density to choose a request, avoiding a large asset on a small display.

The demo changes viewport width and shows a matching candidate and byte count. Real selection also depends on density and cache state, so the example is illustrative.

When to use

Use it when the same image appears at different sizes or mobile image transfer is high.

Open as page ↗