Container Query for “is there enough space outside this element?”

Chris Coyier Chris Coyier on

Say you had a UI component that had pagination arrows for whatever reason. If there was enough space on the outside of that component, you wanted to put those arrows outside, like this this:

But if there isn’t enough room for them without shrinking the main content area, then place them inside, like this:

You could do that with plenty of magic numbers, especially in how big the main content area is. But wouldn’t it be cool if you didn’t have to know? Like the main content area could be whatever, fluid/responsive/flexible, and you could still test if there is “room” outside for the arrows or not.

I was playing with this trick because I remember Adam Argyle talking about it one time, but couldn’t find where he used it. So I wrote this article up to re-learn and document it. Then of course I find the original article. So full credit to Adam here. Mine approach here is super similar of course. I think I prefer how his @container query uses cqi units inside of it in case the parent isn’t the viewport. Clever.

The trick is in combining viewport units within a container query. You could probably do it by using container units within a media query too, but we’ll go with the former because I tried it and it worked.

We’re going to need a “wrapper” element because that’s just how @container queries tend to be most useful. You can’t query the same element that is the container, so easier if the container is a wrapper.

<div class="box">
  <div class="box-inner">
    <div class="arrow arrow-left">
       <svg ...></svg>
    </div>
    <div class="arrow arrow-right">
       <svg ...></svg>
  </div>
</div>Code language: JavaScript (javascript)

The box will be the container:

.box {
  container: box / inline-size;
  inline-size: min(500px, 100vw);
}Code language: CSS (css)

I love using that second declaration, which says: “Make the element 500px wide, but if the entire browser window is smaller than that, do that instead.” That element is the container.

Then we can use a @container query on the inside. If we wanted to make a style change exactly when the container is the same size as the browser window, we could do this:

.box-inner {
  background: rebeccapurple;
  ...

  @container box (inline-size >= 100vw) {
    background: red;
  }
}Code language: CSS (css)

That will do this!

But we’re actually dealing with the arrows here, so what we want to know is “is there enough space outside for them?” Meaning not the exact size of the element, but that:

Element <= Viewport - Arrows - Gap

Which we can express like this:

.box-inner {
  background: rebeccapurple;
  ...

  @container box (inline-size <= calc(100vw - 80px * 2 - 1rem * 2)) {
    /* move arrows here */
  }
}Code language: CSS (css)

I’ll use a bit of translate to move the arrows here:

And here’s a video of the success:

Again what’s kinda cool about this is that we don’t know what the size of the container is. It could be changed anytime and this will continue to work. The only hard coded numbers we used were for the size of the arrow elements and the gap, which you could abstract out to custom properties if you wanted to be more flexible.

Wanna learn modern CSS layout?

Frontend Masters logo

Laying out designs on the web with CSS has gotten a lot more powerful in recent years. CSS grid, flexbox, and container queries are incredibly powerful tools for that, and we have a complete learning course on them from Jen Kramer.

7-Day Free Trial

One response to “Container Query for “is there enough space outside this element?””

  1. pd says:

    Thanks for sharing.

    Always the way to find a reference after the fact 😊

    I wonder if this might be applied to popover ‘foot’ notes in vacant margin space. A use case that looked handy when everyone was looking at popover a few months ago.

Leave a Reply

Your email address will not be published. Required fields are marked *

Did you know?

Frontend Masters Donates to open source projects. $363,806 contributed to date.