CSS wish: inner breakpoints

[2025-09-26] dev, css
(Ad, please don’t block)

In this blog post, I’d like to talk about CSS: I wish it supported inner breakpoints – breakpoints not for viewports or containers but for HTML elements inside viewports or containers.

The past: media queries and container queries  

Media queries  

Media queries were an important initial foundation for making web page layouts responsive: They could adapt dynamically to different viewport sizes (viewport means “part of the web page that is visible on screen”).

article {
  /* Desktop mode */
  flex-direction: row;
}
@media (width < 40rem) {
  article {
    /* Mobile mode */
    flex-direction: column;
  }
}

In desktop mode, we have more horizontal space and use “row” as a flex direction. In mobile mode, we go with “column”.

Container queries  

One important recent next step were container queries:

.parent {
  container-name: parent;
  container-type: inline-size;
}

article {
  /* Desktop mode */
  flex-direction: row;
}
@container parent (width < 40rem) {
  article {
    /* Mobile mode */
    flex-direction: column;
  }
}

Instead of reacting to viewport size changes, we can react to size changes of HTML elements. With media queries, the whole page was responsive. With container queries, individual user interface elements can be responsive, too.

Queries plus nesting  

CSS now lets us nest rules. That makes container queries (and media queries) even more convenient:

.parent {
  container-name: parent;
  container-type: inline-size;
}
article {
  /* Desktop mode */
  flex-direction: row;

  @container parent (width < 40rem) {
    /* Mobile mode */
    flex-direction: column;
  }
}

The challenge: sidebar layout that wraps  

Approach: container query with breakpoints + grid layout  

I love using grids for responsive layouts because they give you a lot of freedom when it comes to rearranging things. Consider the following example: A layout with content in .main-col and a fixed .sidebar.

Layout on wide screens:

+------------------------+-------+
| .main-col              | .side |
|                        | bar   |
+------------------------+-------+

Layout on narrow screens:

+-------------+
| .main-col   |
|             |
+-------------+
| .side       |
| bar         |
+-------------+

We can implement it as follows, via a container query with a breakpoint and a grid layout (see GitHub repository rauschma/sidebar-via-grid):

HTML:

<body>
  <div class="sidebar-layout">
    <div class="main-col">
      main-col
      <ul>
        <li>First</li>
        <li>Second</li>
        <li>Third</li>
      </ul>
    </div>
    <div class="sidebar">
      sidebar
    </div>
  </div>
</body>

CSS:

body {
  container-name: sidebar-layout-container;
  container-type: inline-size;
}
.sidebar-layout {
  display: grid;
  grid-template-columns: 1fr 15rem;
  grid-template-rows: 1fr;
  grid-template-areas: /*A*/
    "main-col sidebar"
  ;
  @container sidebar-layout-container (width < 40rem) {
    grid-template-columns: 1fr;
    grid-template-rows: auto;
    grid-template-areas: /*B*/
      "main-col"
      "sidebar"
    ;
  }
}
.main-col {
  grid-area: main-col;
  background: red;
}
.sidebar {
  grid-area: sidebar;
  background: green;
}

I love how easy it is two switch between a horizontal layout (line A) and a vertical layout (line B) – thanks to grid-template-areas.

This approach has one significant downside: We are actually not interested in the whole width of the container, only in the width of .main.col. Since, in this case, the sidebar is fixed, we could do some calculations but even that is not enough if we want the sidebar to change its size in response to the size of its content.

Approach: flexbox that wraps  

This is a solution based on “The Sidebar” layout by “Every Layout”. Check out the GitHub repository rauschma/sidebar-layout to see it online.

body {
  display: flex;
  flex-wrap: wrap;
}

.sidebar {
  width: 8rem; /*A*/

  display: flex;
  flex-direction: column;
}

.main-col {
  flex-grow: 1; /*B*/
  
  display: flex;
  flex-direction: column;
}

In this case, we can specify precisely what we want:

  • The .sidebar should have a fixed width (line A).
  • The .main-col should have its minimum size dictated by its content and take up any additional horizontal space if the width increases (line B).

If there is not enough space to the right of the main column then the sidebar is wrapped and moves below it.

Wish: a combination of both approaches  

Both approaches have pros and cons:

  1. Container query with breakpoints + grid layout is powerful and intuitive but we can’t really specify the minimal sizes of its columns.
  2. Flexbox that wraps does let us specify minimal column sizes but neither powerful nor intuitive.

What if we could use approach #1 but specify breakpoints for sizes of HTML elements inside the container? I would find that most intuitive. I personally never disliked breakpoints, only the fact that they were not the breakpoints I pictured in my mind.

Does my idea make sense?  

My knowledge of CSS is limited so I don’t know if my idea makes sense and if it could even be implemented.

Feedback welcome: You can reach me via Mastodon, Bluesky and Disqus (add a comment below)

Further reading  

Material on container queries: