🌐

Mobile-First Responsive Design: A Practical CSS Playbook

HTML/CSS4 min readUpdated October 2026

Build pages that work on phones, tablets, and desktops. Covers the viewport tag, clamp(), mobile-first media queries, flexible images, and testing.

More than half of web visits happen on phones. If your page only looks right on a wide monitor, it's broken for most people.

Responsive design means one page that adapts to any screen. It doesn't require a framework. It takes a handful of habits, and this guide covers them in the order you'd use them.

Step 1: The viewport tag

Without this line in your <head>, phones pretend to be a wide desktop screen and shrink your page down to fit.

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

Add it to every page. Nothing else on this list works properly without it.

Step 2: Design for the small screen first

"Mobile-first" means writing your base CSS for phones, then adding rules for bigger screens. It forces you to decide what matters most, and it keeps your CSS simpler, since small screens get the plain single-column layout without extra overrides.

The tool for adding rules is min-width media queries:

<style>
  body { font-family: sans-serif; margin: 0; padding: 16px; }

  .cards { display: grid; gap: 12px; }          /* phone: one column */
  .card  { padding: 20px; background: #f0fdf4; border: 1px solid #86efac; border-radius: 8px; }

  @media (min-width: 600px) {
    .cards { grid-template-columns: repeat(2, 1fr); }   /* tablet */
  }
  @media (min-width: 960px) {
    .cards { grid-template-columns: repeat(4, 1fr); }   /* desktop */
  }
</style>

<div class="cards">
  <div class="card">One</div>
  <div class="card">Two</div>
  <div class="card">Three</div>
  <div class="card">Four</div>
</div>

Drag the editor's preview wider and narrower and watch the columns change. Notice that you didn't write any rules for phones. That's the whole idea.

Choosing breakpoints

Don't pick breakpoints by device names, since new devices keep appearing. Instead, start narrow, stretch the window, and add a breakpoint at the point where your layout starts to look bad. Common starting points are around 600px, 900px, and 1200px, but your content decides.

Step 3: Let sizes flow with clamp()

Fixed pixel sizes either look huge on a phone or tiny on a monitor. clamp(min, preferred, max) gives you a size that grows with the screen but stops at sensible limits.

<style>
  body { font-family: sans-serif; margin: 0; padding: 16px; }
  h1 {
    font-size: clamp(1.6rem, 4vw + 1rem, 3rem);
    margin: 0 0 8px;
  }
  .wrap {
    width: min(100% - 32px, 720px);
    margin-inline: auto;
  }
</style>

<div class="wrap">
  <h1>This heading scales smoothly</h1>
  <p>The container is as wide as the screen, up to 720px, and stays centered.</p>
</div>

min(100% - 32px, 720px) is a one-line replacement for the old "max-width plus padding" pattern. No media query is needed for either of these.

Step 4: Make images and media flexible

Images have a fixed size by default and will overflow small screens. This small reset fixes it:

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

For large photos, use srcset so phones download a smaller file:

<img src="photo-800.jpg"
     srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
     sizes="(min-width: 960px) 50vw, 100vw"
     alt="A mountain lake at sunrise"
     width="800" height="533" loading="lazy">

Always include width and height so the browser reserves the space before the image loads. That stops the page from jumping around. loading="lazy" delays offscreen images until the user scrolls near them.

Step 5: Use layouts that adapt on their own

Often, you can skip media queries completely. A Grid with auto-fit or auto-fill rearranges itself:

<style>
  .grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
    font-family: sans-serif;
  }
  .grid div { background: #dcfce7; padding: 24px; border-radius: 8px; text-align: center; }
</style>

<div class="grid">
  <div>A</div><div>B</div><div>C</div><div>D</div><div>E</div>
</div>

Flexbox with flex-wrap: wrap does something similar for rows of items. Reach for media queries when the layout changes in structure, such as moving a sidebar below the content.

Step 6: Think about touch

Fingers are bigger than mouse pointers. Make buttons and links at least about 44 by 44 pixels, with some space between them. Don't rely on hover for anything essential, since touch screens don't have it. Text should be at least 16px, or iOS zooms in when someone taps a form field.

Container queries: components that adapt to their space

Media queries look at the screen. Container queries look at the box a component sits in, so one card can adapt whether it's in a wide main area or a narrow sidebar. All current major browsers support them.

<style>
  .slot { container-type: inline-size; border: 1px dashed #999; padding: 8px; resize: horizontal; overflow: auto; width: 420px; }
  .product { display: grid; gap: 8px; font-family: sans-serif; }
  .thumb { background: #bbf7d0; height: 60px; border-radius: 6px; }

  @container (min-width: 360px) {
    .product { grid-template-columns: 100px 1fr; }
  }
</style>

<div class="slot">
  <div class="product">
    <div class="thumb"></div>
    <div><strong>Trail shoes</strong><br>Light and grippy.</div>
  </div>
</div>

Drag the bottom-right corner of the dashed box to resize it. The layout switches based on the box's width, not the browser window.

How to test

  • Use your browser's device toolbar (right-click, Inspect, then toggle the device view) and try several widths.
  • Test on a real phone when you can. Emulators can't show you everything.
  • Drag the window slowly between breakpoints. Many bugs live in the in-between sizes.
  • Zoom the text to 200%. Does the layout still hold up?

Key takeaways

  • Always include the viewport meta tag.
  • Write base styles for phones, then add min-width media queries.
  • Use clamp(), min(), and auto-fit grids so layouts flex without extra rules.
  • Make images flexible, and give them width and height.
  • Keep touch targets big and don't hide important things behind hover.

Try it yourself

Reading helps, but typing the code is what makes it stick. Open the editor, paste any example from this article, and change it until it breaks.

Open the HTML/CSS editor

Related Articles