반응형 이미지 전송

Responsive image delivery

표시 크기에 맞는 이미지 후보를 골라 불필요한 전송량을 줄입니다.

···
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은 파일 후보의 픽셀 너비를, sizes는 이미지가 화면에서 차지할 예상 너비를 알려줍니다. 브라우저는 뷰포트와 화면 밀도를 고려해 적절한 파일을 요청합니다. 모든 화면에 가장 큰 이미지를 보내는 것보다 전송량을 줄일 수 있습니다.

데모의 뷰포트 너비를 바꾸면 선택된 후보와 전송량이 함께 바뀝니다. 실제 브라우저는 캐시와 밀도도 고려하므로 후보 선택이 예시와 꼭 같지는 않습니다.

언제 쓰나

같은 이미지를 작은 카드와 큰 화면에서 보여주거나 모바일 전송량이 클 때 씁니다.

페이지로 열기 ↗