🌞

Responsive Design

Build websites that look amazing on every device. Master media queries, fluid layouts, responsive images, and mobile-first development strategies.

Responsive Design Fundamentals

Responsive design ensures your website adapts seamlessly to any screen size - from phones to tablets to desktops. It's not just about making things smaller; it's about creating optimal experiences for each device.

The Viewport Meta Tag

This small tag is essential for responsive design. Without it, mobile browsers render your site at desktop width and scale it down, breaking your responsive styles.

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

Relative Units

100px
50%
5rem
25vw
CSS
/* Fixed units - don't scale */
.fixed { width: 300px; }

/* Relative to parent */
.relative { width: 50%; }

/* Relative to root font-size (usually 16px) */
.rem { font-size: 1.5rem; /* 24px */ }

/* Relative to viewport width */
.viewport { width: 50vw; /* 50% of viewport width */ }

/* Relative to current font-size */
.em { padding: 2em; /* 2x current font size */ }
  • %: Relative to parent element - great for fluid layouts
  • rem: Relative to root font-size - consistent scaling
  • em: Relative to current font-size - component-level scaling
  • vw/vh: Viewport-relative - full-width/height sections
  • vmin/vmax: Smaller/larger viewport dimension

Media Queries

Media queries let you apply different styles based on device characteristics like screen width, height, orientation, or resolution. They're the foundation of responsive design.

Basic Syntax

CSS
/* Mobile-first approach (recommended) */
.container {
    padding: 16px;
}

/* Tablet and up */
@media (min-width: 768px) {
    .container {
        padding: 32px;
    }
}

/* Desktop and up */
@media (min-width: 1024px) {
    .container {
        padding: 48px;
    }
}

Common Breakpoints

📱 Mobile < 768px
📱 Tablet 768px - 1023px
💻 Desktop 1024px - 1439px
🖥️ Large > 1440px
CSS
/* Mobile: 0-767px (default, no media query needed) */

/* Tablet: 768px and up */
@media (min-width: 768px) { }

/* Desktop: 1024px and up */
@media (min-width: 1024px) { }

/* Large Desktop: 1440px and up */
@media (min-width: 1440px) { }

/* Between specific widths */
@media (min-width: 768px) and (max-width: 1023px) { }

/* Portrait/Landscape orientation */
@media (orientation: portrait) { }
@media (orientation: landscape) { }

Mobile-First vs Desktop-First

Mobile-first (recommended): Start with mobile styles, then add complexity for larger screens using min-width. Easier to maintain and better performance on mobile devices.

Desktop-first: Start with desktop styles, then override for smaller screens using max-width. Can lead to bloated mobile CSS as you're removing desktop complexity.

Fluid Typography

Fluid typography scales smoothly between minimum and maximum sizes based on viewport width. No more jarring jumps between breakpoints!

The clamp() Function

Resize your browser to see me scale smoothly!

CSS
/* clamp(minimum, preferred, maximum) */
h1 {
    font-size: clamp(2rem, 5vw + 1rem, 4rem);
    /* Minimum 2rem (32px), scales with viewport, max 4rem (64px) */
}

h2 {
    font-size: clamp(1.5rem, 3vw + 1rem, 3rem);
}

p {
    font-size: clamp(1rem, 2vw + 0.5rem, 1.25rem);
}

/* Line height scales too */
.text {
    line-height: clamp(1.5, 1vw + 1.2, 1.8);
}

How it works: clamp() accepts three values - minimum, preferred (typically viewport-based), and maximum. The browser calculates the preferred value, but constrains it between min and max.

This creates smooth scaling across all viewport sizes without media queries!

Responsive Images

Images need special attention in responsive design. Serve appropriately sized images to save bandwidth and improve performance.

Basic Responsive Images

CSS
/* Make images fluid by default */
img {
    max-width: 100%;
    height: auto;
    display: block;
}

/* Maintain aspect ratio while filling container */
.image-container {
    width: 100%;
    aspect-ratio: 16 / 9;
    overflow: hidden;
}

.image-container img {
    width: 100%;
    height: 100%;
    object-fit: cover; /* or contain, fill, scale-down */
    object-position: center; /* or top, bottom, left, right */
}

Object-fit Examples

📷
cover
📷
contain
📷
fill
HTML
<!-- srcset: serve different images for different screen sizes -->
<img
    src="image-800w.jpg"
    srcset="image-400w.jpg 400w,
            image-800w.jpg 800w,
            image-1200w.jpg 1200w"
    sizes="(max-width: 600px) 400px,
           (max-width: 1000px) 800px,
           1200px"
    alt="Responsive image"
>

<!-- picture element: art direction (different crops for different sizes) -->
<picture>
    <source media="(min-width: 1024px)" srcset="wide-image.jpg">
    <source media="(min-width: 768px)" srcset="medium-image.jpg">
    <img src="mobile-image.jpg" alt="Adaptive image">
</picture>

Responsive Layout Patterns

Common patterns for adapting layouts across screen sizes.

Responsive Grid

1
2
3
4
5
6
CSS
/* Auto-responsive grid - no media queries! */
.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    gap: 24px;
}

/* Or with media queries for more control */
.grid {
    display: grid;
    grid-template-columns: 1fr; /* Mobile: 1 column */
    gap: 16px;
}

@media (min-width: 768px) {
    .grid {
        grid-template-columns: repeat(2, 1fr); /* Tablet: 2 columns */
        gap: 24px;
    }
}

@media (min-width: 1024px) {
    .grid {
        grid-template-columns: repeat(3, 1fr); /* Desktop: 3 columns */
        gap: 32px;
    }
}

Responsive Navigation

📱 Mobile: Hamburger Menu
💻 Desktop: Horizontal Nav
CSS
/* Mobile: Hidden navigation, show hamburger */
.nav-links {
    display: none;
}

.hamburger {
    display: block;
}

/* Desktop: Show navigation, hide hamburger */
@media (min-width: 768px) {
    .nav-links {
        display: flex;
        gap: 24px;
    }

    .hamburger {
        display: none;
    }
}

Container Queries (Modern)

Container queries let components respond to their container's size instead of the viewport. This enables truly reusable, context-aware components.

CSS
/* Define a container */
.sidebar {
    container-type: inline-size;
    container-name: sidebar;
}

/* Query the container, not the viewport */
@container sidebar (min-width: 400px) {
    .card {
        display: grid;
        grid-template-columns: 1fr 2fr;
    }
}

For a deep dive into container queries, check out the dedicated Container Queries page.

Best Practices

Touch Targets

Minimum 44×44px: This is the WCAG guideline for touch targets. Smaller targets are hard to tap accurately, especially for users with motor impairments.

CSS
/* Ensure buttons and links are tappable */
button, a {
    min-height: 44px;
    min-width: 44px;
    padding: 12px 24px;
}

/* Or use padding to reach the minimum */
.link {
    padding: 12px 16px;
}

Performance on Mobile

  • Optimize images: Use modern formats (WebP, AVIF) and appropriate sizes
  • Minimize JavaScript: Mobile CPUs are slower - keep JS lightweight
  • Use system fonts: Save bandwidth by using fonts already on the device
  • Lazy load: Load images and content as users scroll to them
  • Test on real devices: Simulators don't capture real-world performance

Testing Checklist

  • ✓ Test on actual mobile devices (iOS and Android)
  • ✓ Verify touch targets are large enough (44×44px minimum)
  • ✓ Check text readability without zooming
  • ✓ Test forms on mobile keyboards
  • ✓ Verify images load quickly on 3G
  • ✓ Check horizontal scrolling (should be none!)
  • ✓ Test both portrait and landscape orientations