frontend-101
GitHub
The DOM
Responsiveness
Components
State
API Calls
Frameworks
Accessibility
The DOMComponents

frontend-101 — a learning resource for new frontend devs.

© 2026 · MIT LicenseFound an issue?

Responsiveness

Making layouts adapt to any screen size.

What is responsive design?

You built a three-column dashboard that looks sharp on a 27-inch monitor. A teammate opens it on their phone: the third column runs off the right edge, the headings wrap to one word per line, and they close the tab. Responsive design is what keeps that from happening.

It is a single codebase whose layout reshapes itself to the width it is given. Instead of building a phone version and a desktop version, you write one set of HTML and CSS that reorganizes itself based on the space available. The core tool is the breakpoint: a CSS rule that says “once the screen is wider than X pixels, apply these styles.” Below that width a different set takes over. That is how a three-column grid collapses into a single-column stack without touching the HTML.

The word “responsive” misleads a lot of beginners into thinking something detects the phone and loads a separate mobile site. Nothing detects anything. There is no second site and no JavaScript checking the screen; the same CSS simply reacts to how much width it currently has to work with.

Why it matters

More than half of all web traffic is on phones. A layout that only holds together on a desktop monitor doesn’t just look off on a phone; it quietly locks out most of the people trying to use what you built.

A responsive codebase isn’t a bonus feature, it’s the expected baseline, and it is far cheaper to live with than two sites that drift apart every time someone ships a change to one and forgets the other.

Off the edge

Your signup form is perfect on a laptop. On a phone the submit button sits past the right edge, and no amount of scrolling down brings it into reach.

Fat-finger taps

Links spaced for a mouse cursor land a thumb-width too close, so every tap catches the wrong one.

Fixed twice, or not at all

A separate mobile site means every fix happens twice. You patch the broken nav link on desktop, ship it, and a week later a phone user hits the same dead link, because the mobile copy never got the change.

Interactive demo

Before you drag: at what width do you think the three columns give up and drop to two? Grab the handle on the right edge, resize the preview, and find the pixel where it happens.

Viewport width

1200px

Try breaking it:

  • Drag from wide to narrow and watch the nav links vanish into a hamburger and the columns fold from three to two to one. Which breakpoint also switches the footer from a row to a stack?
  • Cross 512px slowly. The jump from one column to two happens in a single pixel step, not a smooth slide. That step is the breakpoint.
  • Park the width at 900px, then nudge below 896. The third column disappears. That 896 line is a choice, not a law: you decide where the layout should change.

How it works

Use the device buttons to snap to common sizes, or drag the handle on the right edge to resize freely and watch the layout reflow. The width readout tracks the preview’s current size as you go. The layout lands in one of three arrangements:

  • mobile: single column, hamburger menu, stacked footer
  • tablet (512px+): two-column grid, nav links visible, inline footer
  • desktop (896px+): three-column grid, full width

Here is the part worth noticing: a real @media breakpoint only ever sees the browser’s actual viewport (the visible area of the window), never an arbitrary box like the preview above. Since the whole point of this demo is a box you resize independently of your real window, it uses container queries instead: the preview is marked as a container, and its layout responds to its own width. No JavaScript decides the columns; the CSS does. The breakpoints (512px and 896px) are Tailwind’s named container sizes. Written out as plain CSS, the card grid looks like this:

How the demo's card grid responds to its container
1
2
3
4
5
6
7
8
9
10
11
.preview {
  container-type: inline-size;
}

@container (min-width: 512px) {
  .cards { grid-template-columns: repeat(2, 1fr); }
}

@container (min-width: 896px) {
  .cards { grid-template-columns: repeat(3, 1fr); }
}

On a real page you react to the whole window instead of a box, so you swap @container for @media (min-width: 896px), keyed to the viewport rather than the preview. That @media form is the one you’ll type most.

If you remember one thing

Build one layout that adapts to the space it’s given, and it works on every screen, without detecting the device or keeping a separate mobile site.