A breakpoint is a width at which your layout changes. Many projects pick them from a list of popular devices. That approach ages badly and misses the real problem. This guide shows how to find breakpoints from your content instead.
Why device widths are the wrong starting point
It is tempting to write breakpoints like "iPhone", "iPad" and "desktop", using the screen widths of particular models. The trouble is:
- New devices arrive every year with new sizes. Your list is out of date the moment you write it.
- Browser windows on laptops and desktops can be any width, and many people do not maximise them.
- Split-screen modes, foldable phones and desktop zoom create widths that match no device.
- A layout can break at a width between two of your "device" breakpoints, and nobody notices until a user does.
The viewport width is a continuous range, not a handful of fixed values. Your layout must work at every point in that range.
Device widths are still useful for testing. Checking popular sizes in DevTools catches real problems. Just do not let them decide where your CSS changes.
Find breakpoints from the content
The method is simple and works for any design:
- Build the mobile-first base styles and open the page in a narrow window, around 320 pixels.
- Slowly widen the window, or drag the DevTools responsive viewport.
- Watch for the moment the design starts to look wrong. Lines of text get too long. Cards stretch until they look empty. Images become huge. White space becomes awkward.
- Note the width where it happens. That is a breakpoint.
- Add a media query at that width, adjust the layout, and keep widening.
- Repeat until the widest size you care about.
Here is a concrete example. A single-column article looks fine until about 42rem, when lines become too long to read comfortably. Rather than switching layout at a device width, you respond to that:
.article {
padding-inline: 1rem;
}
@media (width >= 42rem) {
.article {
max-width: 38rem;
margin-inline: auto;
padding-inline: 0;
}
}
The breakpoint is where the content needs it, so the change looks deliberate at every width.
Use your text to measure
Lines of roughly 45 to 75 characters are commonly recommended for comfortable reading. If you size breakpoints in rem or em, they relate directly to your text. A breakpoint at 40rem means "about forty times the default font size", which stays meaningful if a user changes their default font size.
How many breakpoints do you need?
Fewer than you think. Every breakpoint is another layout to design, build and test.
With intrinsic layouts from lesson 7 and fluid sizing from lesson 6, many components need no breakpoints at all. A typical site ends up with two or three major breakpoints for page-level layout changes, such as:
| Name | Example value | Typical change |
|---|---|---|
md | 40rem | Two-column card grids, larger spacing |
lg | 64rem | Sidebar beside content, full navigation bar |
xl | 80rem | Wider containers, extra columns |
These values are examples, not a standard. Yours come from your content.
Major breakpoints and minor tweaks
It helps to separate two kinds of change:
- Major breakpoints change the page layout. They should be shared across the site.
- Minor tweaks adjust one component at its own awkward width, for example tightening a heading that wraps badly. Keep these next to the component and use them sparingly.
If you find yourself adding many component tweaks, it often means the component should be intrinsic, or should use a container query instead.
Keep breakpoints consistent with tokens
When breakpoints are typed by hand in dozens of files, they drift. Someone writes 47.5rem here and 768px there, and the layout breaks between them.
Treat breakpoints as design tokens: a single, named list that everyone uses.
The custom property problem
You might expect this to work:
:root {
--bp-lg: 64rem;
}
/* Does not work */
@media (width >= var(--bp-lg)) {
.layout { display: grid; }
}
It does not. Custom properties belong to elements, and a media query is evaluated outside any element, so var() is not allowed in media query conditions.
Option 1: a documented list
In plain CSS, keep one comment at the top of your main stylesheet as the source of truth, and only use those values:
/*
Breakpoints (use only these):
md: 40rem
lg: 64rem
xl: 80rem
*/
@media (width >= 40rem) {
.cards { grid-template-columns: repeat(2, 1fr); }
}
@media (width >= 64rem) {
.layout { grid-template-columns: 16rem minmax(0, 1fr); }
}
A quick search for @media during code review catches any value not on the list.
Option 2: a preprocessor or build step
Sass variables are replaced before the browser sees the CSS, so they work in media queries:
$bp-md: 40rem;
$bp-lg: 64rem;
@media (width >= $bp-lg) {
.layout { grid-template-columns: 16rem minmax(0, 1fr); }
}
There is also a CSS specification for custom media queries using @custom-media, which would let you name a query once and reuse it. Browser support is very limited, so in practice it is used through build tools such as PostCSS, which convert it to ordinary media queries. Check Baseline on web.dev before relying on it natively.
Share tokens with JavaScript
If JavaScript needs the same breakpoints, for example with matchMedia(), define them once in a shared configuration file and import that file in both your build and your scripts. That avoids two copies drifting apart.
Content-based breakpoints and container queries
Content-based thinking leads naturally to container queries. If a card component breaks when it is narrower than 22rem, that is true wherever the card appears, in a sidebar or the main column. A container query lets the card respond to its own width, so you set that breakpoint once inside the component instead of guessing viewport widths for every page that uses it. You will build this in lesson 11.
A breakpoint checklist
- Start from the mobile-first base and widen slowly.
- Add a breakpoint only where the content looks wrong.
- Use
remoremvalues. - Keep major breakpoints to a short, shared, named list.
- Prefer intrinsic layouts and container queries for component-level changes.
- Test between your breakpoints, not only at them.
The width just below a breakpoint is where bugs hide. If your breakpoint is at 64rem, test at about 63rem as well. That is the widest the smaller layout ever has to stretch.
Summary
- Device widths change constantly; your layout must work across the whole range of widths.
- Find breakpoints by widening the window and noting where the content starts to look wrong.
- Most sites need only two or three major breakpoints, plus the occasional component tweak.
- Custom properties cannot be used inside media queries; use a documented list, a preprocessor or a build step.
- Component-level breakpoints often belong in container queries.
In the next lesson you will handle tables, code blocks and embeds that are wider than the screen.