5

I have the following snippit, where I add container-type: inline-size on a span and a button.

<span style="container-type: inline-size; outline: 1px solid blue;">
  This is a span
</span>

<button style="container-type: inline-size;">
  This is a button        
</button>

When running the snippit you will see that the span renders normally and the button renders collapsed.

Does anyone know why this happens?

Note: It happens in both Chrome and Safari.

  • Adding `appearance: auto` to the span also breaks the width. But removing the style from the button doesn't fix the button. – Rogier de Ruijter Oct 06 '22 at 14:57
  • I have found that it is related to `display: inline-block` if you create a div with these styles ` – Rogier de Ruijter Oct 06 '22 at 15:18

2 Answers2

15

tl;dr Containers can't be sized by their contents, and inline elements can't be containers.

There are a few things going on here:

  1. container-type: inline-size applies various types of 'containment' to the element, including inline-size containment.

    Size containment 'turns off' the ability for an element to get size information from it's contents. That's important for container queries, since it breaks the 'infinite loop' where a container query changes the content size, which changes the query, which changes…

    So the container size has to come from either from context (eg block elements stretch by default, elements in grid flex can also stretch, etc) or explicit sizing in CSS. Outside of those cases, elements with size containment will collapse. Since inline-block elements like buttons shrink-wrap to their contents, and size containment removes content-sizing, they collapse by default. Put them into a flex or grid, or add block display, and they'll stretch to fit their context.

  2. Size containment doesn't work on inline elements (unless they are 'atomic inlines', eg images and videos and stuff without other content).

    Using an inline element as a container just isn't going to work. You can still use a span, just have to give it a non-inline display. This should be shown as a non-applied style in browser devtools, but I guess it isn't yet. I hope browsers clarify that.

So all your code is behaving according to spec. The fact that containers have to ignore their content size is the main reason we don't just make everything a container. It's also the trick that was required to make Container Queries work at all.

Miriam Suzanne
  • 13,632
  • 2
  • 38
  • 43
1

this answer it will show you some solutions with code,
But make sure to accept the @MiriamSuzanne answer for know the details of how/why this isn't working.

final result (gif)

enter image description here

how to solve

for making this concept work:

  1. you need a <div> as a container first.

  2. then wrap the content you want inside, like a button or whatever.

  3. and then give it to all elements Childs width: 100%; so now all children have the same @container width.

now you can have fun using @container

like this:


simple example

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

.container>* {
  width: 100%;
}

.container button {
  background-color: lightgreen;
}

@container (width > 500px) {
  .container button {
    background-color: red;
  }
}
<div class="container">
  <button>this is a button</button>
</div>

enter image description here


real world example

now I will prove that @container is different from @media

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

.container,
.container>* {
  width: 100%;
}

.container button {
  background-color: lightgreen;
}

@container (width > 400px) {
  .container button {
    background-color: red;
  }
}
<!-- 1 item -->
<div class="container">
  <button>this is a button</button>
</div>

<!-- 2 items -->
<div style="display: flex">
  <div class="container">
    <button>this is a button</button>
  </div>
  <div class="container">
    <button>this is a button</button>
  </div>
</div>

<!-- 4 items -->
<div style="display: flex">
  <div class="container">
    <button>this is a button</button>
  </div>
  <div class="container">
    <button>this is a button</button>
  </div>
  <div class="container">
    <button>this is a button</button>
  </div>
  <div class="container">
    <button>this is a button</button>
  </div>
</div>

enter image description here

Laaouatni Anas
  • 4,199
  • 2
  • 7
  • 26