CSS Responsive Images

Master the art of delivering optimal images across all devices and screen sizes

Why Responsive Images Matter

Responsive images are crucial for modern web development. They ensure that your images look great on any device, load quickly, and don't waste bandwidth. With the variety of screen sizes, resolutions, and network conditions, delivering the right image to the right device has never been more important.

Key Benefits of Responsive Images:

  • Faster loading times and better performance
  • Reduced bandwidth usage for mobile users
  • Improved visual quality on high-resolution displays
  • Better user experience across all devices
  • Improved SEO through better page speed metrics
  • Future-proofing for new devices and screen technologies

Common Challenges:

  • Art direction - different crops for different screen sizes
  • Resolution switching - appropriate sizes for different devices
  • File format optimization - modern formats vs browser support
  • Performance optimization - balancing quality and file size
  • Lazy loading - deferring offscreen image loading
  • Aspect ratio control - preventing layout shifts

Basic Responsive Image Techniques

The foundation of responsive images is simple: ensure images never exceed their container width and maintain their aspect ratio. This can be achieved with just a few lines of CSS.

Basic Responsive Image

img {
  max-width: 100%;
  height: auto;
  display: block;
}

This simple CSS ensures images scale down to fit their containers while maintaining their aspect ratio.

Responsive Background

.responsive-bg {
  background-image: url('image.jpg');
  background-size: cover;
  background-position: center;
}

Background images can be made responsive using background-size: cover or contain.

Interactive Demo:

The example in the full code demo allows you to drag to resize the container and see how the image adapts in real-time. This helps visualize how max-width: 100% and height: auto work together to create responsive images.

Advanced Responsive Image Techniques

For more complex scenarios, HTML and CSS provide advanced features like the picture element, srcset attribute, and modern image formats that give you precise control over which images are delivered to which devices.

Art Direction with <picture>

<picture>
  <source media="(min-width: 1200px)" srcset="large.jpg">
  <source media="(min-width: 768px)" srcset="medium.jpg">
  <img src="small.jpg" alt="Description">
</picture>

The picture element allows different images to be loaded based on media conditions, enabling art direction.

Resolution Switching with srcset

<img src="image-800w.jpg"
  srcset="image-400w.jpg 400w, image-800w.jpg 800w"
  sizes="(max-width: 600px) 100vw, 50vw"
  alt="Description">

The srcset attribute allows browsers to choose the most appropriate image based on device resolution.

Modern Image Formats

<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img src="image.jpg" alt="Description">
</picture>

Modern formats like AVIF and WebP offer superior compression but need fallbacks for browser support.

Lazy Loading

<img src="image.jpg" loading="lazy" alt="Description">
/* or */
<img data-src="image.jpg" class="lazy" alt="Description">

Lazy loading defers image loading until they're needed, significantly improving performance.

Performance Optimization

Image performance is critical for user experience and SEO. Optimizing your images can dramatically improve page load times, especially on mobile devices and slower connections.

Before Optimization

  • Large file sizes that slow down page loading
  • No responsive techniques leading to bandwidth waste
  • Legacy formats without modern compression
  • No lazy loading causing unnecessary initial loads
  • No CDN usage increasing latency
Slow Loading Times

After Optimization

  • Properly sized images for each device and resolution
  • Responsive image techniques to serve optimal sizes
  • Modern formats (WebP, AVIF) for better compression
  • Lazy loading to defer offscreen image loading
  • CDN with image optimization capabilities
Fast Loading Times

Performance Tips:

  • Always compress images without noticeable quality loss
  • Use responsive images to avoid serving large images to small screens
  • Implement lazy loading for images below the fold
  • Consider using modern formats like WebP and AVIF with fallbacks
  • Utilize CDNs with image optimization features
  • Set appropriate cache headers for images

Complete Responsive Images Example

Interactive Responsive Images Demo

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>CSS Responsive Images Masterclass</title>
  <style>
    * {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    
    :root {
      --primary-color: #4f46e5;
      --secondary-color: #7c3aed;
      --accent-color: #ec4899;
      --success-color: #10b981;
      --warning-color: #f59e0b;
      --danger-color: #ef4444;
      --info-color: #06b6d4;
      --dark-color: #1f2937;
      --light-color: #f9fafb;
      --text-color: #374151;
      --text-light: #ffffff;
      --border-color: #e5e7eb;
      --spacing-xs: 0.25rem;
      --spacing-sm: 0.5rem;
      --spacing-md: 1rem;
      --spacing-lg: 1.5rem;
      --spacing-xl: 2rem;
      --spacing-xxl: 3rem;
      --border-radius: 0.5rem;
      --shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
      --shadow-lg: 0 10px 25px rgba(0, 0, 0, 0.15);
      --transition: all 0.3s ease;
      --font-main: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
      --font-mono: 'SF Mono', Monaco, 'Cascadia Code', 'Roboto Mono', Consolas, monospace;
    }
    
    body {
      font-family: var(--font-main);
      line-height: 1.6;
      color: var(--text-color);
      background: linear-gradient(135deg, var(--light-color) 0%, #ffffff 100%);
      min-height: 100vh;
    }
    
    .container {
      max-width: 1200px;
      margin: 0 auto;
      padding: 0 var(--spacing-md);
    }
    
    /* Header Styles */
    .header {
      background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
      color: var(--text-light);
      padding: var(--spacing-xl) 0;
      text-align: center;
      margin-bottom: var(--spacing-xxl);
    }
    
    .header h1 {
      font-size: clamp(2rem, 5vw, 3.5rem);
      margin-bottom: var(--spacing-md);
      font-weight: bold;
    }
    
    .header p {
      font-size: clamp(1rem, 2.5vw, 1.25rem);
      opacity: 0.9;
      max-width: 600px;
      margin: 0 auto;
    }
    
    /* Section Styles */
    .section {
      background: white;
      border-radius: var(--border-radius);
      padding: var(--spacing-xl);
      margin-bottom: var(--spacing-xl);
      box-shadow: var(--shadow);
    }
    
    h2 {
      font-size: 2rem;
      color: var(--dark-color);
      margin-bottom: var(--spacing-lg);
      padding-bottom: var(--spacing-sm);
      border-bottom: 3px solid var(--primary-color);
    }
    
    h3 {
      font-size: 1.5rem;
      color: var(--dark-color);
      margin: var(--spacing-lg) 0 var(--spacing-md);
    }
    
    p {
      margin-bottom: var(--spacing-md);
      line-height: 1.7;
    }
    
    /* Demo Container */
    .demo-container {
      background: var(--light-color);
      border-radius: var(--border-radius);
      padding: var(--spacing-lg);
      margin: var(--spacing-lg) 0;
      border: 2px solid var(--border-color);
      position: relative;
    }
    
    .demo-label {
      position: absolute;
      top: -10px;
      left: var(--spacing-md);
      background: var(--primary-color);
      color: var(--text-light);
      padding: var(--spacing-xs) var(--spacing-sm);
      border-radius: var(--border-radius);
      font-size: 0.875rem;
      font-weight: bold;
    }
    
    /* Image Styles */
    .image-demo {
      width: 100%;
      margin: var(--spacing-md) 0;
      border-radius: var(--border-radius);
      overflow: hidden;
      box-shadow: var(--shadow);
    }
    
    .image-comparison {
      display: flex;
      flex-wrap: wrap;
      gap: var(--spacing-md);
      margin: var(--spacing-lg) 0;
    }
    
    .image-comparison-item {
      flex: 1;
      min-width: 300px;
      border: 2px solid var(--border-color);
      border-radius: var(--border-radius);
      overflow: hidden;
    }
    
    .image-comparison-title {
      background: var(--dark-color);
      color: var(--text-light);
      padding: var(--spacing-sm);
      text-align: center;
      font-weight: bold;
    }
    
    .image-comparison-content {
      padding: var(--spacing-md);
    }
    
    /* Responsive Grid */
    .responsive-grid {
      display: grid;
      gap: var(--spacing-md);
      margin: var(--spacing-lg) 0;
    }
    
    .grid-item {
      background: linear-gradient(45deg, var(--primary-color), var(--secondary-color));
      color: var(--text-light);
      padding: var(--spacing-lg);
      border-radius: var(--border-radius);
      text-align: center;
      font-weight: bold;
      transition: var(--transition);
    }
    
    /* Art Direction Demo */
    .art-direction-demo {
      margin: var(--spacing-lg) 0;
    }
    
    .art-direction-image {
      width: 100%;
      height: auto;
      border-radius: var(--border-radius);
      box-shadow: var(--shadow);
    }
    
    /* Resolution Switching Demo */
    .resolution-demo {
      display: flex;
      flex-wrap: wrap;
      gap: var(--spacing-md);
      margin: var(--spacing-lg) 0;
    }
    
    .resolution-item {
      flex: 1;
      min-width: 250px;
      text-align: center;
    }
    
    .resolution-image {
      width: 100%;
      height: auto;
      border-radius: var(--border-radius);
      box-shadow: var(--shadow);
    }
    
    /* Code Block */
    .code-block {
      background: #1a202c;
      color: #e2e8f0;
      padding: var(--spacing-lg);
      border-radius: var(--border-radius);
      overflow-x: auto;
      margin: var(--spacing-lg) 0;
      font-family: var(--font-mono);
      font-size: 0.875rem;
      line-height: 1.5;
      position: relative;
    }
    
    .code-comment {
      color: #68d391;
      font-style: italic;
    }
    
    .code-selector {
      color: #63b3ed;
    }
    
    .code-property {
      color: #fbb6ce;
    }
    
    .code-value {
      color: #f6ad55;
    }
    
    /* Performance Indicator */
    .performance-indicator {
      position: fixed;
      top: var(--spacing-md);
      right: var(--spacing-md);
      background: var(--dark-color);
      color: var(--text-light);
      padding: var(--spacing-sm) var(--spacing-md);
      border-radius: var(--border-radius);
      font-family: var(--font-mono);
      font-size: 0.75rem;
      z-index: 1000;
      box-shadow: var(--shadow);
    }
    
    /* Responsive Image Grid */
    .image-grid {
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
      gap: var(--spacing-md);
      margin: var(--spacing-lg) 0;
    }
    
    .image-grid-item {
      border-radius: var(--border-radius);
      overflow: hidden;
      box-shadow: var(--shadow);
      transition: var(--transition);
    }
    
    .image-grid-item:hover {
      transform: translateY(-5px);
      box-shadow: var(--shadow-lg);
    }
    
    .image-grid-img {
      width: 100%;
      height: auto;
      display: block;
    }
    
    /* Lazy Loading Demo */
    .lazy-loading-demo {
      height: 150vh;
      display: flex;
      flex-direction: column;
      justify-content: center;
      align-items: center;
      margin: var(--spacing-lg) 0;
      padding: var(--spacing-xl);
      background: linear-gradient(135deg, rgba(79, 70, 229, 0.1), rgba(124, 58, 237, 0.1));
      border-radius: var(--border-radius);
    }
    
    .lazy-image {
      width: 100%;
      max-width: 600px;
      height: auto;
      border-radius: var(--border-radius);
      box-shadow: var(--shadow);
      opacity: 0;
      transition: opacity 0.5s ease;
    }
    
    .lazy-image.loaded {
      opacity: 1;
    }
    
    /* Aspect Ratio Demo */
    .aspect-ratio-demo {
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
      gap: var(--spacing-md);
      margin: var(--spacing-lg) 0;
    }
    
    .aspect-ratio-item {
      border: 2px solid var(--border-color);
      border-radius: var(--border-radius);
      overflow: hidden;
    }
    
    .aspect-ratio-title {
      background: var(--dark-color);
      color: var(--text-light);
      padding: var(--spacing-sm);
      text-align: center;
      font-weight: bold;
    }
    
    .aspect-ratio-content {
      padding: var(--spacing-md);
    }
    
    /* Media Queries for the demo page */
    @media (max-width: 768px) {
      .image-comparison-item {
        min-width: 100%;
      }
      
      .resolution-item {
        min-width: 100%;
      }
    }
    
    /* Animation for demo purposes */
    @keyframes fadeIn {
      from { opacity: 0; }
      to { opacity: 1; }
    }
    
    .fade-in {
      animation: fadeIn 1s ease-in-out;
    }
  </style>
</head>
<body>
  <!-- Performance Indicator -->
  <div class="performance-indicator">
    Viewport: <span id="viewport-size"></span>
  </div>
  
  <header class="header">
    <div class="container">
      <h1>CSS Responsive Images</h1>
      <p>Master the art of delivering optimal images across all devices and screen sizes</p>
    </div>
  </header>
  
  <div class="container">
    <!-- Introduction -->
    <section class="section">
      <h2>Why Responsive Images Matter</h2>
      <p>
        Responsive images are crucial for modern web development. They ensure that your images look great on any device,
        load quickly, and don't waste bandwidth. With the variety of screen sizes, resolutions, and network conditions,
        delivering the right image to the right device has never been more important.
      </p>
      
      <div class="demo-container">
        <div class="demo-label">Live Demo</div>
        <div class="image-comparison">
          <div class="image-comparison-item">
            <div class="image-comparison-title">Non-Responsive Image</div>
            <div class="image-comparison-content">
              <img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80" 
                   alt="Non-responsive image example" 
                   style="width: 100%; height: auto;">
              <p>Fixed size image that doesn't adapt to container</p>
            </div>
          </div>
          
          <div class="image-comparison-item">
            <div class="image-comparison-title">Responsive Image</div>
            <div class="image-comparison-content">
              <img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80" 
                   alt="Responsive image example" 
                   style="max-width: 100%; height: auto;">
              <p>Responsive image that adapts to container width</p>
            </div>
          </div>
        </div>
        <p><strong>Resize your browser to see the difference!</strong></p>
      </div>
    </section>
    
    <!-- Basic Responsive Images -->
    <section class="section">
      <h2>Basic Responsive Images</h2>
      <p>
        The foundation of responsive images is simple: ensure images never exceed their container width and maintain their aspect ratio.
      </p>
      
      <div class="code-block">
        <span class="code-comment">/* Basic responsive image technique */</span><br>
        <span class="code-selector">img</span> {<br>
        &nbsp;&nbsp;<span class="code-property">max-width</span>: <span class="code-value">100%</span>;<br>
        &nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">auto</span>;<br>
        &nbsp;&nbsp;<span class="code-property">display</span>: <span class="code-value">block</span>; <span class="code-comment">/* Removes extra space below image */</span><br>
        }<br><br>
        
        <span class="code-comment">/* For background images */</span><br>
        <span class="code-selector">.responsive-bg</span> {<br>
        &nbsp;&nbsp;<span class="code-property">background-image</span>: <span class="code-value">url('image.jpg')</span>;<br>
        &nbsp;&nbsp;<span class="code-property">background-size</span>: <span class="code-value">cover</span>; <span class="code-comment">/* or contain */</span><br>
        &nbsp;&nbsp;<span class="code-property">background-position</span>: <span class="code-value">center center</span>;<br>
        }
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Demo</div>
        <div style="width: 100%; max-width: 800px; margin: 0 auto; border: 2px dashed var(--border-color); padding: var(--spacing-md); resize: horizontal; overflow: auto;">
          <img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80" 
               alt="Responsive image demo" 
               style="max-width: 100%; height: auto; display: block;">
        </div>
        <p><strong>Drag the right edge to resize the container and see how the image adapts!</strong></p>
      </div>
    </section>
    
    <!-- Art Direction with picture element -->
    <section class="section">
      <h2>Art Direction with &lt;picture&gt; Element</h2>
      <p>
        The &lt;picture&gt; element allows you to define different images for different viewport sizes, 
        enabling art direction for optimal cropping and composition.
      </p>
      
      <div class="code-block">
        <span class="code-comment">&lt;!-- Art direction with picture element --&gt;</span><br>
        &lt;<span class="code-selector">picture</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">source</span> <span class="code-property">media</span>=<span class="code-value">"(min-width: 1200px)"</span> <span class="code-property">srcset</span>=<span class="code-value">"large.jpg"</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">source</span> <span class="code-property">media</span>=<span class="code-value">"(min-width: 768px)"</span> <span class="code-property">srcset</span>=<span class="code-value">"medium.jpg"</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">source</span> <span class="code-property">media</span>=<span class="code-value">"(min-width: 480px)"</span> <span class="code-property">srcset</span>=<span class="code-value">"small.jpg"</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">img</span> <span class="code-property">src</span>=<span class="code-value">"fallback.jpg"</span> <span class="code-property">alt</span>=<span class="code-value">"Description"</span>&gt;<br>
        &lt;/<span class="code-selector">picture</span>&gt;
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Art Direction Demo</div>
        <div class="art-direction-demo">
          <picture>
            <source media="(min-width: 1200px)" srcset="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80">
            <source media="(min-width: 768px)" srcset="https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80">
            <source media="(min-width: 480px)" srcset="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=600&q=80">
            <img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Mountain landscape with art direction" 
                 style="max-width: 100%; height: auto; display: block;">
          </picture>
        </div>
        <p><strong>Resize your browser to see different images load based on viewport size!</strong></p>
      </div>
    </section>
    
    <!-- Resolution Switching with srcset -->
    <section class="section">
      <h2>Resolution Switching with srcset</h2>
      <p>
        The srcset attribute allows browsers to choose the most appropriate image based on device resolution and other factors,
        helping to save bandwidth on smaller devices.
      </p>
      
      <div class="code-block">
        <span class="code-comment">&lt;!-- Resolution switching with srcset --&gt;</span><br>
        &lt;<span class="code-selector">img</span><br>
        &nbsp;&nbsp;<span class="code-property">src</span>=<span class="code-value">"image-800w.jpg"</span><br>
        &nbsp;&nbsp;<span class="code-property">srcset</span>=<span class="code-value">"image-400w.jpg 400w, image-800w.jpg 800w, image-1200w.jpg 1200w"</span><br>
        &nbsp;&nbsp;<span class="code-property">sizes</span>=<span class="code-value">"(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 33vw"</span><br>
        &nbsp;&nbsp;<span class="code-property">alt</span>=<span class="code-value">"Responsive image with srcset"</span><br>
        &gt;
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Resolution Switching Demo</div>
        <div class="resolution-demo">
          <div class="resolution-item">
            <h3>1x Display</h3>
            <img src="https://images.unsplash.com/photo-1418065460487-3e41a6c84dc5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Forest image for 1x displays" 
                 class="resolution-image">
            <p>Standard resolution (1x)</p>
          </div>
          
          <div class="resolution-item">
            <h3>2x Display (Retina)</h3>
            <img src="https://images.unsplash.com/photo-1418065460487-3e41a6c84dc5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80" 
                 alt="Forest image for 2x displays" 
                 class="resolution-image">
            <p>High resolution (2x)</p>
          </div>
        </div>
        <p><strong>On retina displays, the browser will automatically choose higher resolution images when available.</strong></p>
      </div>
    </section>
    
    <!-- Responsive Background Images -->
    <section class="section">
      <h2>Responsive Background Images</h2>
      <p>
        CSS background images can be made responsive using various techniques, including media queries and the image-set() function.
      </p>
      
      <div class="code-block">
        <span class="code-comment">/* Responsive background with media queries */</span><br>
        <span class="code-selector">.hero</span> {<br>
        &nbsp;&nbsp;<span class="code-property">background-image</span>: <span class="code-value">url('hero-small.jpg')</span>;<br>
        &nbsp;&nbsp;<span class="code-property">background-size</span>: <span class="code-value">cover</span>;<br>
        &nbsp;&nbsp;<span class="code-property">background-position</span>: <span class="code-value">center center</span>;<br>
        &nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">50vh</span>;<br>
        }<br><br>
        
        <span class="code-selector">@media</span> <span class="code-value">(min-width: 768px)</span> {<br>
        &nbsp;&nbsp;<span class="code-selector">.hero</span> {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-property">background-image</span>: <span class="code-value">url('hero-medium.jpg')</span>;<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">60vh</span>;<br>
        &nbsp;&nbsp;}<br>
        }<br><br>
        
        <span class="code-selector">@media</span> <span class="code-value">(min-width: 1200px)</span> {<br>
        &nbsp;&nbsp;<span class="code-selector">.hero</span> {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-property">background-image</span>: <span class="code-value">url('hero-large.jpg')</span>;<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">70vh</span>;<br>
        &nbsp;&nbsp;}<br>
        }<br><br>
        
        <span class="code-comment">/* Using image-set() for resolution switching */</span><br>
        <span class="code-selector">.hero</span> {<br>
        &nbsp;&nbsp;<span class="code-property">background-image</span>: <span class="code-value">image-set(</span><br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-value">url('hero-1x.jpg') 1x</span>,<br>
        &nbsp;&nbsp;&nbsp;&nbsp;<span class="code-value">url('hero-2x.jpg') 2x</span><br>
        &nbsp;&nbsp;);<br>
        }
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Background Image Demo</div>
        <div style="
          background-image: url('https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=800&q=80');
          background-size: cover;
          background-position: center center;
          height: 300px;
          border-radius: var(--border-radius);
          display: flex;
          align-items: center;
          justify-content: center;
          color: white;
          text-shadow: 2px 2px 4px rgba(0,0,0,0.5);
          font-size: 1.5rem;
          font-weight: bold;
        ">
          Responsive Background Image
        </div>
        <p><strong>This background image will scale to cover its container while maintaining aspect ratio.</strong></p>
      </div>
    </section>
    
    <!-- Lazy Loading Images -->
    <section class="section">
      <h2>Lazy Loading Images</h2>
      <p>
        Lazy loading defers the loading of images until they are needed, significantly improving page load performance,
        especially for image-heavy websites.
      </p>
      
      <div class="code-block">
        <span class="code-comment">&lt;!-- Native lazy loading --&gt;</span><br>
        &lt;<span class="code-selector">img</span> <span class="code-property">src</span>=<span class="code-value">"image.jpg"</span> <span class="code-property">loading</span>=<span class="code-value">"lazy"</span> <span class="code-property">alt</span>=<span class="code-value">"Lazy loaded image"</span>&gt;<br><br>
        
        <span class="code-comment">/* JavaScript-based lazy loading */</span><br>
        <span class="code-selector">document.addEventListener</span>(<span class="code-value">'DOMContentLoaded'</span>, <span class="code-value">function</span>() {<br>
        &nbsp;&nbsp;<span class="code-value">const</span> lazyImages = <span class="code-selector">document.querySelectorAll</span>(<span class="code-value">'img.lazy'</span>);<br><br>
        
        &nbsp;&nbsp;<span class="code-value">const</span> lazyLoad = <span class="code-value">function</span>() {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;lazyImages.<span class="code-selector">forEach</span>(<span class="code-value">function</span>(img) {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="code-value">if</span> (img.<span class="code-property">getBoundingClientRect</span>().<span class="code-property">top</span> &lt;= <span class="code-selector">window.innerHeight</span> && img.<span class="code-property">getBoundingClientRect</span>().<span class="code-property">bottom</span> >= 0 && <span class="code-selector">getComputedStyle</span>(img).<span class="code-property">display</span> !== <span class="code-value">'none'</span>) {<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img.<span class="code-property">src</span> = img.<span class="code-property">dataset</span>.<span class="code-property">src</span>;<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;img.<span class="code-property">classList</span>.<span class="code-property">remove</span>(<span class="code-value">'lazy'</span>);<br>
        &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br>
        &nbsp;&nbsp;&nbsp;&nbsp;});<br>
        &nbsp;&nbsp;};<br><br>
        
        &nbsp;&nbsp;<span class="code-comment">// Initial check</span><br>
        &nbsp;&nbsp;lazyLoad();<br><br>
        
        &nbsp;&nbsp;<span class="code-comment">// Listen to scroll events</span><br>
        &nbsp;&nbsp;<span class="code-selector">window.addEventListener</span>(<span class="code-value">'scroll'</span>, lazyLoad);<br>
        &nbsp;&nbsp;<span class="code-selector">window.addEventListener</span>(<span class="code-value">'resize'</span>, lazyLoad);<br>
        });
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Lazy Loading Demo</div>
        <div class="lazy-loading-demo">
          <p>Scroll down to see the image load...</p>
          <img data-src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1200&q=80" 
               class="lazy-image" 
               alt="Lazy loaded mountain image">
        </div>
        <p><strong>Scroll down to trigger the lazy loading of the image!</strong></p>
      </div>
    </section>
    
    <!-- Aspect Ratio Control -->
    <section class="section">
      <h2>Aspect Ratio Control</h2>
      <p>
        Maintaining consistent aspect ratios for images is crucial for responsive design to prevent layout shifts and ensure visual consistency.
      </p>
      
      <div class="code-block">
        <span class="code-comment">/* Traditional aspect ratio padding technique */</span><br>
        <span class="code-selector">.aspect-ratio-box</span> {<br>
        &nbsp;&nbsp;<span class="code-property">position</span>: <span class="code-value">relative</span>;<br>
        &nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">0</span>;<br>
        &nbsp;&nbsp;<span class="code-property">padding-top</span>: <span class="code-value">56.25%</span>; <span class="code-comment">/* 16:9 Aspect Ratio */</span><br>
        }<br><br>
        
        <span class="code-selector">.aspect-ratio-box img</span> {<br>
        &nbsp;&nbsp;<span class="code-property">position</span>: <span class="code-value">absolute</span>;<br>
        &nbsp;&nbsp;<span class="code-property">top</span>: <span class="code-value">0</span>;<br>
        &nbsp;&nbsp;<span class="code-property">left</span>: <span class="code-value">0</span>;<br>
        &nbsp;&nbsp;<span class="code-property">width</span>: <span class="code-value">100%</span>;<br>
        &nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">100%</span>;<br>
        &nbsp;&nbsp;<span class="code-property">object-fit</span>: <span class="code-value">cover</span>;<br>
        }<br><br>
        
        <span class="code-comment">/* Modern aspect-ratio property */</span><br>
        <span class="code-selector">.modern-aspect-ratio</span> {<br>
        &nbsp;&nbsp;<span class="code-property">aspect-ratio</span>: <span class="code-value">16 / 9</span>;<br>
        }
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Aspect Ratio Demo</div>
        <div class="aspect-ratio-demo">
          <div class="aspect-ratio-item">
            <div class="aspect-ratio-title">16:9 Aspect Ratio</div>
            <div class="aspect-ratio-content">
              <div style="position: relative; height: 0; padding-top: 56.25%; background: #f3f4f6; border-radius: 4px; overflow: hidden;">
                <img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                     alt="16:9 aspect ratio example" 
                     style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
              </div>
            </div>
          </div>
          
          <div class="aspect-ratio-item">
            <div class="aspect-ratio-title">1:1 Aspect Ratio</div>
            <div class="aspect-ratio-content">
              <div style="position: relative; height: 0; padding-top: 100%; background: #f3f4f6; border-radius: 4px; overflow: hidden;">
                <img src="https://images.unsplash.com/photo-1418065460487-3e41a6c84dc5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                     alt="1:1 aspect ratio example" 
                     style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
              </div>
            </div>
          </div>
          
          <div class="aspect-ratio-item">
            <div class="aspect-ratio-title">4:3 Aspect Ratio</div>
            <div class="aspect-ratio-content">
              <div style="position: relative; height: 0; padding-top: 75%; background: #f3f4f6; border-radius: 4px; overflow: hidden;">
                <img src="https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                     alt="4:3 aspect ratio example" 
                     style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; object-fit: cover;">
              </div>
            </div>
          </div>
        </div>
        <p><strong>These images maintain their aspect ratios regardless of container width.</strong></p>
      </div>
    </section>
    
    <!-- Responsive Image Gallery -->
    <section class="section">
      <h2>Responsive Image Gallery</h2>
      <p>
        Creating a responsive image gallery involves combining multiple techniques like CSS Grid, Flexbox, and responsive image practices.
      </p>
      
      <div class="code-block">
        <span class="code-comment">/* Responsive image gallery with CSS Grid */</span><br>
        <span class="code-selector">.gallery</span> {<br>
        &nbsp;&nbsp;<span class="code-property">display</span>: <span class="code-value">grid</span>;<br>
        &nbsp;&nbsp;<span class="code-property">grid-template-columns</span>: <span class="code-value">repeat(auto-fill, minmax(250px, 1fr))</span>;<br>
        &nbsp;&nbsp;<span class="code-property">gap</span>: <span class="code-value">1rem</span>;<br>
        }<br><br>
        
        <span class="code-selector">.gallery-item</span> {<br>
        &nbsp;&nbsp;<span class="code-property">position</span>: <span class="code-value">relative</span>;<br>
        &nbsp;&nbsp;<span class="code-property">overflow</span>: <span class="code-value">hidden</span>;<br>
        &nbsp;&nbsp;<span class="code-property">border-radius</span>: <span class="code-value">var(--border-radius)</span>;<br>
        }<br><br>
        
        <span class="code-selector">.gallery-item img</span> {<br>
        &nbsp;&nbsp;<span class="code-property">width</span>: <span class="code-value">100%</span>;<br>
        &nbsp;&nbsp;<span class="code-property">height</span>: <span class="code-value">auto</span>;<br>
        &nbsp;&nbsp;<span class="code-property">display</span>: <span class="code-value">block</span>;<br>
        &nbsp;&nbsp;<span class="code-property">transition</span>: <span class="code-value">transform 0.3s ease</span>;<br>
        }<br><br>
        
        <span class="code-selector">.gallery-item:hover img</span> {<br>
        &nbsp;&nbsp;<span class="code-property">transform</span>: <span class="code-value">scale(1.05)</span>;<br>
        }
      </div>
      
      <div class="demo-container">
        <div class="demo-label">Gallery Demo</div>
        <div class="image-grid">
          <div class="image-grid-item">
            <img src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Mountain landscape" 
                 class="image-grid-img">
          </div>
          <div class="image-grid-item">
            <img src="https://images.unsplash.com/photo-1418065460487-3e41a6c84dc5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Forest landscape" 
                 class="image-grid-img">
          </div>
          <div class="image-grid-item">
            <img src="https://images.unsplash.com/photo-1464822759023-fed622ff2c3b?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Snowy mountain" 
                 class="image-grid-img">
          </div>
          <div class="image-grid-item">
            <img src="https://images.unsplash.com/photo-1501785888041-af3ef285b470?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Lakeside view" 
                 class="image-grid-img">
          </div>
          <div class="image-grid-item">
            <img src="https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Mountain range" 
                 class="image-grid-img">
          </div>
          <div class="image-grid-item">
            <img src="https://images.unsplash.com/photo-1433086966358-54859d0ed716?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=400&q=80" 
                 alt="Waterfall" 
                 class="image-grid-img">
          </div>
        </div>
        <p><strong>Resize your browser to see the gallery adjust the number of columns!</strong></p>
      </div>
    </section>
    
    <!-- Performance Best Practices -->
    <section class="section">
      <h2>Performance Best Practices</h2>
      <p>
        Optimizing images for performance is crucial for fast-loading websites and good user experience.
      </p>
      
      <div class="image-comparison">
        <div class="image-comparison-item">
          <div class="image-comparison-title">Before Optimization</div>
          <div class="image-comparison-content">
            <ul>
              <li>Large file sizes</li>
              <li>No responsive techniques</li>
              <li>No modern formats (WebP, AVIF)</li>
              <li>No lazy loading</li>
              <li>No CDN usage</li>
            </ul>
            <p style="color: var(--danger-color); font-weight: bold;">Slow loading times</p>
          </div>
        </div>
        
        <div class="image-comparison-item">
          <div class="image-comparison-title">After Optimization</div>
          <div class="image-comparison-content">
            <ul>
              <li>Properly sized images</li>
              <li>Responsive image techniques</li>
              <li>Modern formats (WebP, AVIF)</li>
              <li>Lazy loading implemented</li>
              <li>CDN with image optimization</li>
            </ul>
            <p style="color: var(--success-color); font-weight: bold;">Fast loading times</p>
          </div>
        </div>
      </div>
      
      <div class="code-block">
        <span class="code-comment">&lt;!-- Optimized responsive image with modern formats --&gt;</span><br>
        &lt;<span class="code-selector">picture</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">source</span> <span class="code-property">type</span>=<span class="code-value">"image/avif"</span> <span class="code-property">srcset</span>=<span class="code-value">"image.avif"</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">source</span> <span class="code-property">type</span>=<span class="code-value">"image/webp"</span> <span class="code-property">srcset</span>=<span class="code-value">"image.webp"</span>&gt;<br>
        &nbsp;&nbsp;&lt;<span class="code-selector">img</span> <span class="code-property">src</span>=<span class="code-value">"image.jpg"</span> <span class="code-property">alt</span>=<span class="code-value">"Optimized image"</span> <span class="code-property">loading</span>=<span class="code-value">"lazy"</span>&gt;<br>
        &lt;/<span class="code-selector">picture</span>&gt;
      </div>
    </section>
    
    <!-- Summary -->
    <section class="section">
      <h2>Summary</h2>
      <p>
        Responsive images are essential for modern web development. By implementing the techniques covered in this guide,
        you can ensure your images look great on any device while maintaining optimal performance.
      </p>
      
      <div class="image-comparison">
        <div class="image-comparison-item">
          <div class="image-comparison-title">Key Techniques</div>
          <div class="image-comparison-content">
            <ul>
              <li>max-width: 100% for basic responsiveness</li>
              <li>srcset for resolution switching</li>
              <li>picture element for art direction</li>
              <li>Lazy loading for performance</li>
              <li>Aspect ratio control for stability</li>
              <li>Modern formats for compression</li>
            </ul>
          </div>
        </div>
        
        <div class="image-comparison-item">
          <div class="image-comparison-title">Benefits</div>
          <div class="image-comparison-content">
            <ul>
              <li>Faster loading times</li>
              <li>Better user experience</li>
              <li>Reduced bandwidth usage</li>
              <li>Improved SEO</li>
              <li>Consistent visual quality</li>
              <li>Future-proof websites</li>
            </ul>
          </div>
        </div>
      </div>
    </section>
  </div>
  
  <script>
    // Update viewport size indicator
    function updateViewportSize() {
      const width = window.innerWidth;
      const height = window.innerHeight;
      const indicator = document.getElementById('viewport-size');
      if (indicator) {
        indicator.textContent = `${width} × ${height}px`;
      }
    }
    
    // Lazy loading implementation for demo
    document.addEventListener('DOMContentLoaded', function() {
      const lazyImage = document.querySelector('.lazy-image');
      
      const lazyLoad = function() {
        if (lazyImage && !lazyImage.classList.contains('loaded')) {
          const rect = lazyImage.getBoundingClientRect();
          if (rect.top <= window.innerHeight && rect.bottom >= 0 && getComputedStyle(lazyImage).display !== 'none') {
            lazyImage.src = lazyImage.dataset.src;
            lazyImage.classList.add('loaded');
          }
        }
      };
      
      // Initial check
      lazyLoad();
      
      // Listen to scroll events
      window.addEventListener('scroll', lazyLoad);
      window.addEventListener('resize', lazyLoad);
    });
    
    // Update on load and resize
    updateViewportSize();
    window.addEventListener('resize', updateViewportSize);
  </script>
</body>
</html>

Ready to Master Responsive Images?

Experiment with our interactive example that demonstrates all responsive image techniques in action. Resize your browser window, test on different devices, and see how the images adapt in real-time!

< PreviousNext >