🖼️ Picture Element = Responsive Images
Images need to adapt to all screens. Picture element serves the right image at the right size.
📝 Picture Element Syntax
<picture>
<source
media="(min-width: 1024px)"
srcset="large.jpg"
/>
<source
media="(min-width: 768px)"
srcset="medium.jpg"
/>
<source
media="(min-width: 480px)"
srcset="small.jpg"
/>
<img
src="fallback.jpg"
alt="Description of image"
loading="lazy"
/>
</picture>
# Art Direction Example
<picture>
<source
media="(orientation: landscape)"
srcset="landscape.jpg"
/>
<source
media="(orientation: portrait)"
srcset="portrait.jpg"
/>
<img src="default.jpg" alt="Art direction example" />
</picture>
# WebP with Fallback
<picture>
<source
type="image/webp"
srcset="image.webp"
/>
<source
type="image/avif"
srcset="image.avif"
/>
<img
src="image.jpg"
alt="Modern format with fallback"
/>
</picture>
🎯 Advanced Responsive Images
# Multiple Resolutions (1x, 2x)
<img
src="image-1x.jpg"
srcset="image-1x.jpg 1x, image-2x.jpg 2x"
alt="High resolution support"
/>
# Width Descriptors with Sizes
<img
src="small.jpg"
srcset="small.jpg 480w,
medium.jpg 768w,
large.jpg 1024w"
sizes="(max-width: 480px) 100vw,
(max-width: 768px) 80vw,
50vw"
alt="Responsive with sizes"
/>
# Lazy Loading with Intersection Observer
<img
src="placeholder.jpg"
data-src="real-image.jpg"
class="lazy"
alt="Lazy loading example"
/>
<script>
const lazyImages = document.querySelectorAll('.lazy');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
lazyImages.forEach(img => observer.observe(img));
</script>
💡 Responsive Image Best Practices
- Always provide alt text for accessibility
- Use WebP/AVIF with fallbacks
- Implement lazy loading
- Optimize image sizes
- Use srcset for resolution switching
The picture element gives you complete control over responsive images. Your users will thank you for the faster loading times.
