Breakpoints were always a hack. You’d pick 768px and 1024px because some phone was that wide in 2014, then patch the gaps forever. Modern CSS lets the browser do the math instead. Three tools replace most of your media queries.
Fluid type with clamp
Stop shipping three font sizes for one heading. clamp() interpolates smoothly between a minimum and a maximum, driven by the viewport:
h1 {
font-size: clamp(1.75rem, 1rem + 3vw, 3rem);
}The middle value scales with the viewport; the outer two clamp it so it never gets tiny on phones or absurd on monitors. One line, every screen size, no breakpoints. Use it for spacing too — padding: clamp(1rem, 5vw, 4rem) gives you gutters that breathe.
Container queries, not viewport
A card doesn’t care how wide the window is. It cares how much room it has. Container queries let a component respond to its own container, so the same card lays out wide in the main column and stacked in a sidebar — no viewport math. Set container-type: inline-size on the parent, then style children with @container (min-width: 400px). This is the one that actually changes how you build components.
Let layouts lay out
Some layouts need no queries at all. A row of items that wraps when it runs out of room is just flex-wrap: wrap with a min-width on each item. A grid that adds columns as space allows is repeat(auto-fit, minmax(...)). These are intrinsic layouts: they respond to content and available space, not to arbitrary widths. Fewer rules, fewer edge cases.
Fewer breakpoints, better UI
You’ll still write the occasional media query — a full sidebar collapsing into a drawer earns one. But start with fluid values and container queries, and reach for a breakpoint only when the layout genuinely needs to change, not just resize. Delete the ones you’re only using to nudge a font size. Let the browser interpolate, and your UI stops breaking at 900px.