How to Choose CSS Breakpoints
Set breakpoints where your content starts to look wrong, not at specific device widths. Write mobile-first styles with min-width queries, start from common conventions like 640, 768, 1024 and 1280px if you need defaults, and use container queries for components.
A breakpoint is a width at which your layout changes, for example from one column to two. Early responsive design often tied breakpoints to popular devices: 320px for one phone, 768px for one tablet. That approach ages badly. There are now thousands of screen sizes, and the device list you design for today will be out of date in a year.
Start from content, not devices
A content-first breakpoint is placed where the design actually breaks. The process is simple:
- Build the layout for a narrow screen first.
- Slowly widen the browser window.
- Stop when something looks wrong: lines of text become too long, cards stretch awkwardly, or there is obviously room for a second column.
- Add a breakpoint at about that width and adjust the layout.
- Keep widening and repeat.
Because the breakpoints come from your design, they keep working on devices that don't exist yet. A useful signal is line length: body text is generally comfortable at roughly 45 to 75 characters per line. When a single column of text grows past that, it is time to add a sidebar, a second column, or a max-width.
Mobile-first with min-width queries
Mobile-first means your base CSS, outside any media query, is the small-screen layout. You then layer on changes with min-width queries as space increases. This tends to keep stylesheets smaller, because narrow layouts are usually simpler, and you add complexity rather than undoing it.
/* Base: one column, works at any width */
.cards { display: grid; gap: 1rem; }
/* Two columns once there is room for ~2 × 18rem cards */
@media (min-width: 40em) {
.cards { grid-template-columns: repeat(2, 1fr); }
}
/* Three columns on wide screens */
@media (min-width: 64em) {
.cards { grid-template-columns: repeat(3, 1fr); }
}Desktop-first, using max-width queries, works too, but often leads to more overrides as you strip features back for smaller screens. Whichever direction you pick, avoid mixing both on the same component, and watch for overlap: max-width: 768px and min-width: 768px both match at exactly 768px.
Modern browsers also support range syntax, such as @media (width >= 40em), which reads more naturally and avoids the off-by-one problem. It is supported in current major browsers, but check your support targets if you need very old ones.
Common breakpoint conventions
If you need starting values, popular frameworks have converged on similar numbers. These are conventions, not rules, and nothing about them is special to browsers.
| Typical range | Tailwind CSS default | Bootstrap 5 | Often used for |
|---|---|---|---|
| Small | 640px (sm) | 576px (sm) | Large phones, landscape phones |
| Medium | 768px (md) | 768px (md) | Tablets in portrait, small windows |
| Large | 1024px (lg) | 992px (lg) | Tablets in landscape, laptops |
| Extra large | 1280px (xl) | 1200px (xl) | Desktops |
| 2X large | 1536px (2xl) | 1400px (xxl) | Wide desktops |
Using a framework's values has real benefits: your team already knows them, and component libraries are built around them. Just be willing to add a custom breakpoint when your content needs one, or to skip one your design doesn't use.
em vs px in media queries
You can write breakpoints in px, em or rem. The difference shows up when a user changes the default font size in their browser settings:
- px breakpoints stay fixed. If text is enlarged, a two-column layout may keep two columns that are now too narrow for the bigger text.
- em breakpoints scale with that setting. A user with a 24px default would trigger a
40emquery at 960px instead of 640px, so they get the roomier layout sooner.
One detail trips people up: in media queries, em and rem are based on the browser's initial font size, usually 16px, not on any font-size you set on html. So 40em means 640px for a user with default settings, regardless of your root size. To convert your design widths, divide by 16, or use the px to em converter. Our guide to px, rem, em and vw covers the units in more depth.
Page zoom (Ctrl or Cmd plus) changes the effective viewport width in modern browsers, so it triggers px and em queries alike. The em advantage is specifically about the default font size preference.
Worked example: a card grid
You have a grid of article cards. Each card looks good between about 18rem (288px) and 26rem (416px) wide, with 1rem gaps and 1rem padding on the page.
- One column until two 18rem cards plus a gap and page padding fit: 18 + 1 + 18 + 2 = 39rem. Round up to a 40em breakpoint (640px at default settings).
- Two columns until a third card fits: 18 × 3 + 2 + 2 = 58rem. You may prefer a little breathing room, so 64em (1024px) is a sensible choice.
- Three columns from there. Cap the container with a
max-widthso cards never stretch past about 26rem each.
Those happen to land on common framework values, but they were derived from the card, so you know exactly why they are there. For this particular pattern, CSS Grid can even handle it with no media queries at all:
.cards {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fill, minmax(min(18rem, 100%), 1fr));
}Container queries: the modern complement
Media queries only know the viewport size. That is a problem for reusable components: a card in a narrow sidebar and the same card in a wide main column face very different space on the same screen. Container queries solve this by letting a component respond to the size of its parent.
.card-wrap { container-type: inline-size; }
.card { display: grid; gap: 0.75rem; }
/* When the card's container is at least 30rem wide,
put the image beside the text */
@container (min-width: 30rem) {
.card { grid-template-columns: 12rem 1fr; }
}Size container queries are supported in all current major browsers. A good division of labor is to use media queries for the overall page layout (navigation, columns, sidebars) and container queries for components that get placed in different contexts. Read more in MDN's container queries guide and the MDN media queries reference.
Fewer breakpoints with fluid sizing
Many breakpoints exist only to bump font sizes or spacing up a notch. Fluid values using viewport units and clamp() can replace those steps with smooth scaling. The px to vw converter helps translate fixed design widths into viewport units, and the fluid typography guide shows how to keep text accessible while it scales.
Breakpoint checklist
- Base styles are the narrow layout and work at 320px wide.
- Each breakpoint has a reason you can explain in terms of content.
- Units are consistent across the project (all em or all px).
- Components that live in multiple places use container queries.
- You have tested with a larger default font size and with zoom.
Frequently asked questions
What are the standard CSS breakpoints?
There is no official standard. Popular frameworks use similar conventions: Tailwind CSS defaults to 640, 768, 1024, 1280 and 1536px, and Bootstrap 5 uses 576, 768, 992, 1200 and 1400px. They are useful starting points, but your content should decide where layouts change.
Should I use min-width or max-width media queries?
Mobile-first min-width queries are the most common approach. You write the base styles for small screens and add rules as space increases, which tends to produce less CSS and fewer overrides than max-width queries.
Should media queries use px or em?
Both work. Em-based queries scale with the user browser font size setting, so layouts adapt when someone enlarges their default text. In media queries, 1em is based on the browser initial font size, usually 16px, not on your html font-size.
How many breakpoints do I need?
As few as your content requires. Many sites manage with two or three major breakpoints plus a few component-level tweaks. Container queries can remove the need for many page-level breakpoints.
What is the difference between media queries and container queries?
Media queries respond to the viewport size. Container queries respond to the size of a parent element, so a component can adapt to whatever space it is placed in, such as a narrow sidebar or a wide main column.