CSSResponsive Design Overview

Responsive design fundamentals

Responsive design creates websites that work well on any screen size — from small phones to large monitors. The foundation is the viewport meta tag (tells mobile browsers how to render), then CSS techniques like media queries, flexible layouts (flexbox/grid), and fluid typography. Modern responsive design prioritizes mobile-first development: start with mobile styles, then enhance for larger screens.

The mobile-first approach

Mobile-first means writing CSS for the smallest screens first, then adding media queries for larger screens. This approach encourages simpler, more performant code and ensures mobile users get a solid experience.

CSS
/* Mobile-first: styles for small screens first */
.container {
  display: flex;
  flex-direction: column;  /* stack vertically on mobile */
  padding: 15px;
  font-size: 16px;
}

.sidebar {
  order: 2;  /* sidebar below content on mobile */
  width: 100%;
  margin-top: 20px;
}

.content {
  order: 1;
  width: 100%;
}

/* Enhance for tablet and up */
@media (min-width: 768px) {
  .container {
    flex-direction: row;
    padding: 20px;
    gap: 20px;
  }

  .sidebar {
    order: 2;
    width: 300px;
    flex: 0 0 auto;
    margin-top: 0;
  }

  .content {
    flex: 1;
  }
}

/* Enhance for desktop and up */
@media (min-width: 1200px) {
  .container {
    max-width: 1400px;
    margin: 0 auto;
    padding: 40px;
  }
}
Viewport meta tag

The viewport meta tag tells mobile browsers how to render your page. Without it, mobile devices assume the page is desktop-sized and zoom out, making text tiny.

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

<!-- Breakdown -->
<!-- width=device-width: make page width match device width -->
<!-- initial-scale=1.0: start at 100% zoom, not zoomed out -->

<!-- Optional additions -->
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, user-scalable=yes">
<!-- maximum-scale: limit zoom to 5x -->
<!-- user-scalable: allow users to zoom (always include) -->
Media queries

Breakpoint

Device type

Common widths

320px - 480px

Mobile phones

iPhone SE, older phones

481px - 768px

Tablets

iPad, Android tablets

769px - 1024px

Tablets landscape

iPad landscape, small laptops

1025px+

Desktop/monitors

Large screens, TVs

CSS
/* Mobile-first: base styles for all devices */
.button {
  padding: 12px 20px;
  font-size: 16px;
  width: 100%;  /* full width on mobile */
}

/* Small tablet and up */
@media (min-width: 481px) {
  .button {
    width: auto;  /* auto width on larger screens */
    padding: 10px 20px;
    font-size: 15px;
  }
}

/* Tablet and up */
@media (min-width: 769px) {
  .button {
    padding: 12px 24px;
    font-size: 16px;
  }
}

/* Desktop and up */
@media (min-width: 1025px) {
  .button {
    padding: 14px 28px;
    font-size: 18px;
  }
}

/* Using max-width (desktop-first approach, less common) */
@media (max-width: 768px) {
  .button {
    width: 100%;
  }
}
Responsive patterns without media queries

Modern CSS offers ways to be responsive without explicit media queries using flexible units, min/max functions, and flexbox/grid.

CSS
/* Flexible layout with flexbox (no media query needed) */
.grid {
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
}

.item {
  flex: 1 1 250px;  /* min 250px, grows to fill space */
  min-width: 0;
}

<!-- On narrow screens: 1 item per row
     On medium: 2-3 items per row
     On wide: 4+ items per row
     All without media queries! -->

/* Responsive grid with auto-fit */
.responsive-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
}

<!-- Automatically adjusts columns based on space -->

/* Fluid typography */
.heading {
  font-size: clamp(20px, 5vw, 48px);
  /* min 20px, preferred 5% viewport width, max 48px -->
  /* Scales smoothly with viewport */
}

/* Responsive padding/margin */
.section {
  padding: clamp(20px, 5vw, 60px);
  /* min 20px, preferred 5vw, max 60px */
}
Container queries (modern alternative)

Container queries let elements respond to their container's size rather than viewport size. This is more powerful than media queries for components.

CSS
/* Define a container context */
.card-container {
  container-type: inline-size;  /* track container width */
}

/* Query the container size */
@container (min-width: 300px) {
  .card {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 20px;
  }
}

@container (max-width: 299px) {
  .card {
    display: flex;
    flex-direction: column;
  }
}

<!-- The card layout changes based on container width, not viewport -->
<!-- Works great for reusable components -->

/* Named containers */
.page {
  container-type: inline-size;
  container-name: page;
}

@container page (min-width: 800px) {
  .main {
    display: grid;
    grid-template-columns: 1fr 1fr 1fr;
  }
}
Responsive typography

CSS
/* Fluid font sizing with clamp() */
html {
  /* Scale font size between 14px and 20px based on viewport */
  font-size: clamp(14px, 2vw, 20px);
}

h1 {
  font-size: clamp(28px, 8vw, 64px);
  /* Small screens: 28px, scales up, max 64px */
}

h2 {
  font-size: clamp(24px, 6vw, 48px);
}

p {
  font-size: clamp(14px, 2vw, 18px);
  line-height: 1.6;
}

/* Media query approach (older) */
@media (max-width: 768px) {
  h1 { font-size: 28px; }
  h2 { font-size: 24px; }
}

@media (min-width: 769px) and (max-width: 1200px) {
  h1 { font-size: 40px; }
  h2 { font-size: 32px; }
}

@media (min-width: 1201px) {
  h1 { font-size: 64px; }
  h2 { font-size: 48px; }
}

<!-- clamp() approach scales smoothly -->
<!-- Media query approach jumps at breakpoints -->
Images in responsive design

CSS
/* Images scale with container */
img {
  max-width: 100%;
  height: auto;  /* maintain aspect ratio */
  display: block;  /* remove inline spacing -->
}

/* Responsive images with srcset (HTML) */
<img
  src="image-400w.jpg"
  srcset="image-800w.jpg 2x, image-1200w.jpg 3x"
  alt="Description"
>

<!-- Browser chooses image based on device pixel ratio -->

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

/* CSS for background images */
.hero {
  background-image: url('hero-400w.jpg');
}

@media (min-width: 768px) {
  .hero {
    background-image: url('hero-800w.jpg');
  }
}

@media (min-width: 1200px) {
  .hero {
    background-image: url('hero-1600w.jpg');
  }
}
Note
Modern responsive design uses a mix of approaches: mobile-first media queries for major layout changes, flexbox/grid for automatic responsiveness, clamp() for fluid sizing, and container queries for component-level responsiveness.
Next
Organizing media queries effectively: [media query patterns](/css/media-queries).