How to Approach Responsive Web Development in the Modern Era (2025+)

Apple released the first smart phone in 2007 and its widespread adoption over the next two years indirectly kickstarted the first era of responsive web development.

In 2009, media queries were introduced to the CSS spec in response to the demand for better mobile browsing experiences. They served as the primary workflow from 2009 to 2025.

Container Queries, a feature designed for more logical responsive development, were introduced in 2023, but were not immediately adopted. If I had to guess, it’s due to the two big gotchas of container queries that I wrote about in Container Queries vs Media Queries: A New Era of Responsive Web Design.

The primary gotcha of container queries — children relying on parents to be manually declared as measurable containers — was indirectly and accidentally solved by the introduction of native CSS nesting. Specifically, it was solved by a nesting technique that I identified as a working possibility and then proceeded to coin the Has Me Selector.

This development led me to introducing a “Container-Query-First” workflow in our visual development environment, Etch, and gave me the confidence to record It’s Time to Move On From Media Queries in August 2025.

That’s the briefest possible history of responsive development that I can give you, so you’re on the same page with where we’ve been and where we’re at now.

But, responsive development isn’t just about media queries versus container queries, and there’s still a lot of questions as to which responsive techniques should be used and when.

That’s what this article is going to answer for you. I’m going to give you a methodology for thinking about responsive development that you can easily apply to every single project you work on.

An Escalation-Based Workflow: How to Think About & Prioritize Responsive Techniques

The goal is to minimize directives and code complexity. We want to achieve mobile responsiveness with the simplest techniques first, then the most logical techniques, and finally the generic workflows.

Here’s the methodology:

  • Intrinsic Responsiveness: Elements and Blocks adapt naturally without any queries.
  • Available Space Responsiveness: If behavior depends on parent size or layout context, use container queries to create adjustments.
  • Device Responsiveness: If responsiveness can’t be achieved intrinsically and the device is the only influence on available space, fallback to media queries.

The approach is pretty simple: if a problem can be solved earlier in the chain, stop there. Escalation adds complexity. And with media queries, a reduction in responsive accuracy will occur when used inappropriately.

Let’s cover each step of the process:

Escalation Level 0: No Escalation (Static Content)

Not everything needs to be “handled” in terms of responsiveness.

Some elements are genuinely static and will never need to adapt: images, a small icon, a fixed badge, a tight label. If it doesn’t need to change across contexts or viewports, keep it simple and move on.

Additionally, don’t force things that are automatically responsive (like 100% width elements, text, etc.) to break responsiveness by incorrectly giving them dimensions.

For example, lets say you have a block with multiple paragraphs of content and you want it to only be 60 characters wide. Setting inline-size to 60ch breaks responsiveness where setting max-inline-size to 60ch preserves responsiveness.

I’ve seen this mistake made relentlessly in web design where a developer starts using media queries to solve a problem that should have never been introduced in the first place.

Escalation Level 1: Intrinsic Responsiveness

Modern CSS offers many techniques for making things intrinsically responsive. These should be employed first and many of these techniques can be deployed by default across all projects as a starting point. This is a major aspect of the philosophy behind Automatic CSS.

Web developers need to have a solid grasp of all the various responsive development techniques and work to employ them whenever possible. This cuts down on code, complexity, and general development headaches.

  • Clamp Functions: All spacing and typography can be handled automatically by clamp functions. This makes all headings, text, and spacing intrinsically responsive.
  • Calculated Line Height: Line height using em or percentages creates annoying inconsistencies across a wide range of sizes, like h1 to h6. This is why we introduced intelligent line height into Automatic CSS a year or two ago, which uses a calculation based on the X height of the font. An example is calc(8px + 2ex).
  • Min and Max Functions: There are many areas where responsiveness can be handled by a min() or max() function. These work by scaling something to a minimum or maximum size.
  • Flex Wrap: Many flex layouts don’t require media or container queries because they allow line wrapping. The default mode of flex is to not wrap, but if it makes sense for items to wrap when they run out of available space, setting flex-wrap to wrap is a one-line solution.
  • Auto-Fill, Auto-Fit, MinMax Grid Layouts: Grids have the ability to auto-fill and auto-fit their items in combination with the minmax() function, all of which can help you achieve intrinsic responsiveness. The caveat is that the layout shouldn’t need to care about having specific quantities of items in each row as the grid stacks. Automatic CSS offers two features — Variable Grids and Auto Grids — based on these techniques.
  • Columns: CSS has an intrinsically responsive, multi-column approach to columnized content called columns. They’re extremely helpful for flowing text across multiple columns as well as achieving masonry layouts.

These techniques should make up your first layer of responsive development.

If for some reason one of these techniques can’t get the job done, it’s time to escalate to Level 2.

Escalation Level 2: Container Queries

Container Queries offer the most logical approach to responsiveness, so they should be considered as the best option before media queries.

Remember, all responsive techniques are based on available space. Here’s how each layer works:

  • Intrinsic responsive techniques respond to available space automatically via mathematical calculation.
  • Container queries respond to available space by dynamically measuring the dimensions of a blocks’ parent.
  • Media queries respond to available space by measuring the size of the device accessing the page.

The reason container queries are more accurately responsive is because they measure their direct parent instead of the viewport. This allows for responsive changes without regard for the device and makes blocks/components far more dynamic and flexible.

The principle is simple: Could this component appear in a different context—like a sidebar, modal, or grid cell—where the available space might be different but viewport size is irrelevant? If so, use container queries.

A cuter way to say it is, “style for placement, not for platform.”

Container queries also replace the need for many BEM modifier classes. In the old days, you might design a tall card and then design a variation like “wide.” You’d use .card--wide to change the layout when the wide variant was needed.

With container queries, though, all you have to do is drop your card into a wider space and it’ll automatically become the wide variant. Much better!

Container queries also unlock the ability to use container query units: cqw, cqh, cqi, cqb, cqmin, and cqmax. These behave exactly like viewport units, but measure the container size instead of the viewport.

Escalation Level 3: Media Queries

Just because container queries are technically more accurate than media queries doesn’t mean that media queries are fully replaced by them.

There are still valid uses of media queries, but I’m also going to challenge you to use them differently than you’ve been using them.

Imagine for a moment that you’re building a hero section. It spans edge-to-edge across the viewport and contains a heading, subheading, and call-to-action button arranged in a two-column layout on larger screens that needs to stack vertically on mobile.

Are you ever going to take that hero section and place it inside a narrow sidebar? No. It’s always going to be full-width, always anchored to the viewport edges. The device viewport is the only container that matters.

This is exactly when media queries make sense.

Media queries should be used in two situations: when the device viewport is the only measurable container or when the block in question will never be used in any other context.

Other examples include modals, drawers, and fixed position elements. These are literally attached to the viewport—there’s no other containment context to measure. The viewport is the container, so we use the technique that measures the viewport: media queries.

But I don’t recommend using media queries the way you’ve used them in the past. It’s time for a new approach to media queries as well. Specifically, I want to challenge the concept of fixed “breakpoints” that you map all your media queries to.

Why? Because, gone are the days of creating breakpoints based on hand-picked device sizes. There are over 2,200 calculated device sizes in the wild. Picking four or five of them to make all your responsive decisions is wildly impractical. That’s why we completely removed breakpoint presets from Etch.

Instead, use block-based development principles. Define your media query based on what needs to happen to the specific block you’re working on.

If that hero section’s two-column layout needs to stack at 55.3rem (a size that never appears in any “breakpoint” preset), then make it stack at 55.3rem. Why force a generic breakpoint when it doesn’t perfectly correspond to the block you’re currently building?

This is more precise, more maintainable, and eliminates the cognitive overhead of trying to force every component into the same arbitrary breakpoint system.

What About Mobile-First vs Desktop-First?

Multiple computers and mobile devices on a desk

Major debates have been happening since the early days of responsive development with regard to mobile-first vs desktop-first workflows.

I haven’t weighed in on this debate much other than to point out the fact that there’s no universally better approach. In reality, mobile-first is more efficient for some layouts and components while desktop-first is better for others.

Instead of fighting over mobile and desktop workflows, we should be fighting for better interfaces and workarounds for query limitations.

For example, we’re adding tons of helper features to Etch to make responsive development faster, more accurate, and far more efficient and maintainable:

  • Fluid-responsive canvas
  • Right-click to dynamically insert a media query for the current canvas size.
  • Right click to dynamically insert the Has Me selector.
  • Right click to dynamically insert a container query for the current element size.
  • The ability to tokenize media and container queries.
  • Recipes for instantly inserting tokenized queries.
  • to-rem() function to convert px values in queries to rem automatically.

Beyond that, you should be heavily leveraging the new range syntax for queries (which Etch uses by default on auto-insertion).

Other environments will be adopting these features soon, no doubt, because what we’re innovating in terms of responsive workflows is light years better than anything that currently exists.

And as this happens, you’ll hear less and less about mobile-first vs desktop-first because that debate is largely irrelevant. You can easily apply mobile-first or desktop-first in a context-dependent workflow without committing universally to one or the other.

Conclusion

Modern responsiveness demands logic and precision. The escalation workflow detailed in this article keeps your CSS lean, your components portable, and your layouts resilient.

  1. Intrinsic first for natural adaptation.
  2. Container next for context-aware behavior.
  3. Media last for global, viewport-wide shifts.
  4. Use a modern development environment that isn’t based on the responsive stone age.

Build like this and you’ll ship faster, maintain less, and deliver interfaces that feel coherent in every environment.