The layout that was "right" and still wrong
This started with a category hero for a client project: a heading, a short description, and a grid of four product cards. On my first responsive pass, I added a breakpoint at 768px because that is the tablet standard.
Technically, the layout behaved. The grid collapsed when it was supposed to. The text resized. Nothing overlapped. On paper, it matched the usual "desktop, tablet, phone" model.
At exactly 768px, it also looked terrible.
The heading wrapped in a way that made the title feel like an afterthought. The cards were just wide enough that your eyes had to travel too far to scan them, and just narrow enough that they did not feel spacious. The layout was technically correct at 768px but experientially broken. The breakpoint was serving the device, not the content.
Finding the real breakpoint: 644px
The real breakpoint for this hero was not a round number. It was 644px, and it came from a single product card.
Each card had three pieces of content: a product code, a short description, and a "View" link. As the viewport shrank, there was a specific moment where that content stopped working.
Below 644px wide:
- The product code wrapped onto two lines.
- The "View" link's touch target started crowding the text.
That was the exact point where the content demanded a different layout. It had nothing to do with iPad dimensions or Bootstrap conventions. It had everything to do with the minimum readable width of a single card.
I wrote about this earlier in AI-Powered CSS Grid Layouts: My Actual Workflow, Not Hype.
I set the breakpoint at 644px. At that width and below, the grid changed. The layout held its shape until the content broke, then it snapped to a new configuration.
The heading had its own opinion: 520px
The hero heading did not care about 644px at all. It had its own breaking point at 520px, and it came from language, not layout.
The client used a long German compound word in the title that never broke gracefully. It either sat on one line and looked great, or it hit the container edge and the line-height made the stacked title look like a paragraph.
Below 520px, that is exactly what happened: the word hit the container, wrapped, and the default line-height made the stacked title look like body copy. It stopped reading like a headline.
I added a smaller font size and tighter leading at 520px. The heading regained its shape and hierarchy. Above that width, it stayed large and generous. The breakpoint belonged to the typography, not to the grid and not to the device.
If I had forced everything through a single device breakpoint, the title would have been too small on some phones and still broken on others. Content-driven breakpoints meant the typography had its own responsive logic.
Three content breakpoints, zero device breakpoints
By the end of this hero, I had three different content breakpoints:
644pxfor the product grid.520pxfor the hero title typography.400pxfor the navigation toggle.
There was no single "tablet" or "phone" breakpoint for this component. Each piece of content declared its own breaking point, and the CSS followed.
More on this in my article Container Queries vs Media Queries: The Call I Make On Every Component.
The trade-off is obvious: the code is messier than a single md: prefix. You cannot memorize it as "desktop, tablet, phone". You have to read it and understand what each number is doing.
The upside is that the layout never looks "almost right" at any width. It either works or it changes. Those awkward middle zones where the grid is technically responsive but experientially off do not exist, because the breakpoints are tuned to the content's breaking points, not Apple's product line.
How this felt on an actual phone
The client did not notice the breakpoint values, but they noticed that the site felt right on their phone.
They tested it on an older Samsung model that is exactly 412px wide. At that width, the layout was not a compromised version of the desktop view. It was a fully considered stack. The content breakpoint had coincidentally aligned with their device, but only because it was derived from readability, not market share.
That is the difference between responsive design that looks like it was tested and responsive design that looks like it was guessed.
Let the component own its breakpoints
To make this maintainable, I stopped thinking of breakpoints as global constants and started treating them as component properties.
For this hero, the CSS defined its own custom properties in the component scope:
Read also Where Cursor Stops and My Judgment Begins.
.category-hero {
--hero-break: 644px;
--title-break: 520px;
}
@media (max-width: 644px) {
.category-hero { /* grid changes */ }
}
@media (max-width: 520px) {
.category-hero__title { /* type changes */ }
}
The global 768px breakpoint still exists in the framework for legacy reasons, but it is not used here. The component owns its own breaking points because the component owns its own content.
This is more code to maintain, but it is honest code. It admits that layout is a negotiation between content and container, not a schedule of device releases.
If a future change adds a longer product code or a different language in the title, I know exactly where to look. The numbers in the CSS are not arbitrary; they are the recorded moments where the content stopped working and asked for help.
Subscribe to my newsletter to get the latest updates and news
Member discussion