Skip to main content
ANVISoftware Solutions
Lesson 9 of 20Beginner16 min

Responsive Design

By the end of this lesson

Build layouts that work from small phones to wide desktops.

Responsive design means one page that adapts, rather than separate versions for separate devices. There are too many screen sizes to design for individually, and the reader can change theirs at any moment by rotating a phone or resizing a window.

The starting assumption that makes this manageable: design for the narrow case first. A single column of readable text works everywhere. Wider screens then get extra columns as an enhancement, rather than a wide layout being squeezed down and patched.

Mobile-first: the narrow layout is the default
CSS
/* Applies everywhere, including the smallest screens */
.employee-card {
  display: grid;
  gap: 0.5rem;
  padding: 1rem;
}

.directory-toolbar {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

/* Added only when there is room for it */
@media (min-width: 40rem) {
  .directory-toolbar {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}
  • Everything outside the media query is the base layout, and it is the narrow one. A phone applies it and stops.
  • min-width means "from this width upwards". Reading top to bottom, the stylesheet adds capability as space becomes available.
  • Written the other way round — a desktop base plus max-width queries — the small-screen styles become a list of corrections to something that does not fit. That is harder to read and easy to leave incomplete.
  • The breakpoint is in rem rather than pixels so it scales with the reader's font size. Someone using large text gets the single-column layout for longer, which is the right outcome.
  • One breakpoint, chosen because the toolbar stops fitting. That is the test: change the layout when the content needs it, not at a number from a device list.

Units, and what each one follows:

rem
A multiple of the page's root font size. That size is the reader's browser setting, so rem respects someone who has chosen larger text. Use it for type, spacing and breakpoints.
em
A multiple of the current element's font size. Useful for spacing that should scale with the text it sits next to, such as padding inside a button.
px
A fixed length. Right for things that genuinely should not scale, such as a 1px border. Fixing font sizes in px ignores the reader's own preference.
%
A share of the parent's size. Straightforward for widths, less so for heights, where the parent often has no set height.
ch
Roughly the width of one character. max-width: 70ch is a direct way to keep a line of text at a comfortable reading length.
vw and vh
A percentage of the viewport. Powerful and easy to misuse — font sizes in pure vw become unreadably small on a phone and absurd on a monitor. Pair them with limits.
Three tools that remove media queries
CSS
.page {
  width: 100%;
  max-width: 72rem;
  margin-inline: auto;
  padding-inline: 1rem;
}

h1 {
  font-size: clamp(1.75rem, 1.25rem + 2vw, 2.75rem);
  line-height: 1.2;
}

.employee-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
}
  • max-width with an auto inline margin gives a container that fills a phone and stops growing on a monitor. Without the limit, lines of text stretch to 200 characters and become hard to track.
  • clamp takes a minimum, a preferred value and a maximum. The heading never drops below 1.75rem, never passes 2.75rem, and moves smoothly between them as the viewport changes.
  • The middle value mixes a rem and a vw on purpose. Including a rem component means the text still responds to the reader's font-size setting and to browser zoom; a pure vw value does not.
  • The grid changes its column count from the space available. Three declarations, no breakpoints, and it keeps working in a narrow container as well as a narrow window.
  • Between them these three cover a surprising amount of what media queries used to do. Media queries remain the right answer for changes the container's width cannot imply — reordering regions, hiding a sidebar, switching a navigation pattern.

How to check your work, in rough order of value:

  • Drag the window edge slowly from narrow to wide, watching for the widths where something goes wrong rather than the widths in your CSS
  • Zoom the page to 200 percent. Content should reflow, not disappear or need sideways scrolling
  • Set the browser's default font size to large and reload — this is what a rem-based layout is protecting
  • Check landscape on a phone, where height is short and sticky headers eat the screen
  • Try the page on a real device once. Touch targets that felt fine with a mouse often do not

Summary

  • Start from the narrow layout and add capability as space allows, rather than correcting a wide one
  • Relative units let the reader's own font-size setting work; px font sizes override it
  • max-width keeps line lengths readable on wide screens
  • auto-fit grids and clamp remove many media queries, and respond to the container rather than the device
  • Choose breakpoints where your content breaks, and test between them as well as at them

Practice

Attempt each one before opening the solution. Getting it wrong first is how the idea sticks.

Try it yourself

Turn it around

Here is a desktop-first fragment. Rewrite it mobile-first, and remove any breakpoint you no longer need.

.employee-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 24px; } @media (max-width: 900px) { .employee-grid { grid-template-columns: repeat(2, 1fr); } } @media (max-width: 600px) { .employee-grid { grid-template-columns: 1fr; } }

Show solution

Both media queries disappear. The three of them were describing one idea — cards should be at least so wide — and auto-fit with minmax states that directly.

The declaration now works in any container rather than at any viewport width, so the same grid behaves correctly inside a narrow panel. The desktop-first version would show four columns there and overflow.

If a design genuinely requires exactly four columns above a certain width, keep a media query for that. It is a real requirement, and pretending otherwise produces a layout that nearly matches at every size.

CSS
.employee-grid {
  display: grid;
  gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
}

/* Only if the design really does require a hard cap on the widest screens */
@media (min-width: 90rem) {
  .employee-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

Think about it

Think about it

A designer asks for a heading at font-size: 5vw so it always fills the width. What will you tell them, and what will you build instead?

Show solution

At 320px that is 16px, which is body text rather than a heading. On a 2560px monitor it is 128px. The value is proportional to the window, which is not the same as being readable in it.

The larger problem is that viewport units do not respond to the reader increasing their text size, so the heading becomes one of the few things on the page they cannot make bigger.

Build it with clamp, with a rem component in the middle term: clamp(1.75rem, 1.25rem + 2vw, 3rem). It still grows with the window, it has sensible ends, and it still responds to zoom and font-size settings.

Saved in this browser only.