Chapter 1 of ?
css 8 min read

CSS3 Mastery — Chapter 17: CSS Media Queries, Responsive Web Design & Viewport

Chapter 17: CSS Media Queries, Responsive Web Design & Viewport

Responsive Web Design (RWD) ensures web applications adapt seamlessly across smartphones, tablets, laptops, dynamic notch displays, and ultra-wide desktop monitors. Mastering viewport management, mobile-first CSS architecture, modern Media Query Range syntax (width >= 768px), mobile safe area insets (env()), fluid typography (clamp()), and next-generation Container Queries (@container) creates truly device-agnostic user experiences.

17.1 Viewport Meta Tag & Mobile Safe Area Insets (env())

The HTML viewport meta tag tells mobile browser engines to render the layout at the device's actual physical screen width rather than simulating a 980px desktop view. Setting viewport-fit=cover extends full-bleed backgrounds into device camera notches and home indicator curves, managed using env() variables:

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">

padding-top: max(16px, env(safe-area-inset-top));
padding-bottom: max(16px, env(safe-area-inset-bottom));
Environmental Variable Description Typical Use Case
env(safe-area-inset-top) Top inset distance from edge to clear camera notch or Dynamic Island. Fixed headers, top app bars, sticky banners.
env(safe-area-inset-bottom) Bottom inset distance from edge to clear home gesture indicator bar. Fixed bottom navigation bars, floating action buttons (FAB).
env(safe-area-inset-left) / right Left and right side insets for landscape orientation on curved screens. Full-width hero section padding in landscape mode.
<!DOCTYPE html>
<html>
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; margin: 0; }

    /* Fixed Bottom Nav using env() Safe Area Inset */
    .mobile-nav {
      position: fixed; bottom: 0; left: 0; right: 0;
      background: #1e293b; border-top: 1px solid #334155;
      padding-top: 12px;
      /* Protects against overlapping Home Indicator bar on mobile devices */
      padding-bottom: max(12px, env(safe-area-inset-bottom));
      display: flex; justify-content: space-around;
      font-size: 12px; font-weight: bold; color: #38bdf8;
    }
  </style>
</head>
<body>
  <div style="padding:24px;">
    <h3 style="color:#38bdf8;margin-top:0;">Mobile Safe Area Insets Demo</h3>
    <p style="font-size:12px;color:#94a3b8;">The bottom bar below automatically uses env(safe-area-inset-bottom) to prevent home bar collisions!</p>
  </div>

  <div class="mobile-nav">
    <span>🏠 Home</span>
    <span>🔍 Search</span>
    <span>⚙️ Settings</span>
  </div>
</body>
</html>

17.2 Modern Media Query Range Syntax (width >= 768px)

CSS Media Queries Level 4 introduced Range Media Query Syntax using mathematical comparison operators (>=, <=, >, <). This eliminates verbose, confusing min-width / max-width syntax and avoids off-by-one pixel overlap bugs:

Target Viewport Condition Legacy Syntax (Media Queries Level 3) Modern Range Syntax (Media Queries Level 4)
Minimum width 768px (Tablets+) @media (min-width: 768px) @media (width >= 768px)
Maximum width 640px (Mobile only) @media (max-width: 640px) @media (width <= 640px)
Exact range between 768px and 1024px @media (min-width: 768px) and (max-width: 1024px) @media (768px <= width <= 1024px)
<!DOCTYPE html>
<html>
<head>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }
    h3 { margin-top: 0; color: #818cf8; }

    /* Mobile Base (< 768px) */
    .range-card {
      background: rgba(239, 68, 68, 0.2); border: 2px solid #ef4444; color: #f87171;
      padding: 16px; border-radius: 10px; font-size: 14px; font-weight: bold; text-align: center;
      transition: all 0.3s ease;
    }
    .range-card::after { content: " (Mobile Viewport < 768px)"; }

    /* Modern Range Query: 768px <= width <= 1024px */
    @media (768px <= width <= 1024px) {
      .range-card {
        background: rgba(245, 158, 11, 0.2); border-color: #f59e0b; color: #fbbf24;
      }
      .range-card::after { content: " (Tablet Range: 768px <= width <= 1024px)"; }
    }

    /* Modern Range Query: width >= 1025px */
    @media (width >= 1025px) {
      .range-card {
        background: rgba(16, 185, 129, 0.2); border-color: #10b981; color: #34d399;
      }
      .range-card::after { content: " (Desktop Viewport: width >= 1025px)"; }
    }
  </style>
</head>
<body>
  <h3>Modern Range Media Query Detector</h3>
  <p style="font-size:12px;color:#64748b;">Resize viewport window to trigger Range Query intervals:</p>

  <div class="range-card">
    Active State:
  </div>
</body>
</html>

17.3 Fluid Typography & Dynamic Layout Spacing (clamp())

Instead of creating harsh step-based typography jumps across media query breakpoints, clamp(MIN, VAL, MAX) dynamically interpolates font sizes and spacing continuously based on viewport width:

font-size: clamp(1.25rem, 0.8rem + 1.5vw, 2.75rem);
Floor = 1.25rem (20px mobile min)  |  Ideal Slope = 0.8rem + 1.5vw  |  Ceiling = 2.75rem (44px desktop max)
<!DOCTYPE html>
<html>
<head>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; }

    /* Fluid Heading using clamp() */
    .fluid-title {
      font-size: clamp(1.25rem, 0.8rem + 2vw, 2.5rem);
      color: #38bdf8; font-weight: 800; margin: 0 0 8px;
    }

    /* Fluid Container Padding */
    .fluid-box {
      background: #1e293b; border: 2px solid #38bdf8; border-radius: 12px;
      padding: clamp(12px, 3vw, 32px);
    }
  </style>
</head>
<body>
  <div class="fluid-box">
    <h1 class="fluid-title">Truly Fluid Heading Scaling</h1>
    <p style="font-size:13px;color:#94a3b8;margin:0;">Both title font-size and card padding smoothly scale with viewport size without any discrete media query jumps!</p>
  </div>
</body>
</html>

17.4 Container Queries (@container, cqw, cqh & Container Units)

While Media Queries test the outer screen viewport width, Container Queries (@container) enable component-driven design by querying the size of an element's direct parent container. Container Query length units (cqw, cqh, cqi, cqb) provide relative sizing based on container dimensions:

Container Unit Definition & Basis Viewport Equivalent
cqw 1% of query container's width vw (Viewport Width)
cqh 1% of query container's height vh (Viewport Height)
cqi 1% of query container's inline size (width in horizontal writing mode) vi (Viewport Inline)
cqb 1% of query container's block size (height in horizontal writing mode) vb (Viewport Block)
cqmin / cqmax Smaller / larger value of cqi or cqb vmin / vmax
<!DOCTYPE html>
<html>
<head>
  <style>
    *, *::before, *::after { box-sizing: border-box; }
    body { font-family: system-ui, sans-serif; background: #0f172a; color: #f8fafc; padding: 24px; margin: 0; display: flex; flex-direction: column; gap: 20px; }
    h3 { margin-top: 0; color: #10b981; }

    /* Establish Container Context */
    .widget-container {
      container-type: inline-size;
      container-name: product-widget;
      background: #1e293b; border: 2px dashed #10b981; border-radius: 12px;
      padding: 16px; resize: horizontal; overflow: auto;
      width: 100%; max-width: 480px;
    }

    /* Base Component Layout */
    .widget-body { display: flex; flex-direction: column; gap: 10px; }
    .widget-title { font-size: clamp(14px, 4cqw, 22px); color: #34d399; font-weight: bold; }

    /* Container Query: Reflow when container width >= 380px */
    @container product-widget (min-width: 380px) {
      .widget-body {
        flex-direction: row;
        align-items: center;
        justify-content: space-between;
      }
    }
  </style>
</head>
<body>
  <h3>@container Query &amp; cqw Unit Demo</h3>
  <p style="font-size:12px;color:#64748b;">Drag bottom-right handle to resize container. Component reflows and scales text via cqw units:</p>

  <div class="widget-container">
    <div class="widget-body">
      <div class="widget-title">Container-Aware Product Card</div>
      <button style="background:#10b981;color:#fff;border:none;padding:8px 16px;border-radius:6px;font-weight:bold;cursor:pointer;">Buy Now</button>
    </div>
  </div>
</body>
</html>

17.5 Interactive Sandbox — Range Queries, clamp() & Container Queries

Test Range Media Queries, fluid clamp() typography, and @container queries live in the interactive playground below:

Live Playground — Chapter 17 Sandbox
Done with this chapter?
Mark it complete to track your progress and unlock your certificate.
Next Up

Learner Reviews

Write a Review
Share your experience to help other learners.
Your Rating *