DEV Community

Cover image for Resolving Issues from Unexpected Changes to `container-type: inline-size` in Chrome 129
Michael Charles Aubrey
Michael Charles Aubrey

Posted on

Resolving Issues from Unexpected Changes to `container-type: inline-size` in Chrome 129

Chrome 129 introduced a change in the behavior of container queries affecting elements with container-type: inline-size. This change, while small, has the potential to break your web app's layout. I'm going to go over what changed, how it behaved before, and how it behaves starting with Chrome 129.

What Changed?

Prior to Chrome 129, container-type: inline-size implicitly:

  1. Created a containing block for absolutely positioned elements
  2. Established a new stacking context

To illustrate this, consider the following:

<!DOCTYPE html>
<html lang="en">
  <head>
    <style>
      .container {
        container-type: inline-size;
        width: 300px;
        height: 300px;
        border: 2px solid black;
        padding: 1rem;
        margin: 2rem;
        contain: layout;
      }

      .child,
      .sibling {
        position: absolute;
        display: flex;
        justify-content: center;
        align-items: center;
        color: white;
      }

      .child {
        width: 200px;
        height: 200px;
      }

      .child-1 {
        background-color: rgba(255, 0, 0, 0.7);
        top: 100px;
        left: 100px;
        z-index: 2;
      }

      .child-2 {
        background-color: rgba(0, 255, 0, 0.7);
        top: 30px;
        left: 0;
        z-index: 1;
      }

      .sibling {
        width: 150px;
        height: 150px;
        background-color: rgba(0, 0, 255, 0.7);
        top: 165px;
        left: 50px;
        z-index: 1;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <div class="child child-1">Child 1 (z-index: 2)</div>
      <div class="child child-2">Child 2 (z-index: 1)</div>
    </div>
    <div class="sibling">Sibling (z-index: 1)</div>
  </body>
</html>
Enter fullscreen mode Exit fullscreen mode

Before Chrome 129, the above code rendered as follows:

A screenshot of a web page containing a white square outlined with a black border. On top of the white square are a stack of three smaller squares. A green square on the bottom, red in the middle, and blue on top. All of the colored squares appear within the confines of the white squares black borders.

The children of the black-outlined .container div are absolutely positioned. child-2 (the green div) is positioned left: 0, however it aligns with the left-side boundaries of the parent .container div. This is because in Chrome 128 and older, container-type: inline-size implicitly created a containing block for absolutely positioned children.

Additionally, the container-type: inline-size element is implicitly creating a new stacking context, resulting in green being on the bottom, red in the middle, and blue on top.

However, as of Chrome 129, the same HTML and CSS renders like so,

A screenshot of a web page containing a white square outlined with a black border. On top of the white square are a stack of three smaller squares. A green square on the bottom, blue in the middle and red on top. The green square has escaped the boundaries of the white squares black border.

No containing block is created for the .container element's children, and therefore the absolutely positioned elements are positioned relative to the web page rather than relative to their container. This results in the green square entirely escaping the container and touching the left side of the web page.

Additionally, since no new stacking context was created, the order in which the children and siblings stack has changed. The green square is still on the bottom, but now the blue square is in the middle, and the red square is on top.

Why the Change?

According to the Chromium team on the official Chromium bug tracker this was an intentional change to fix what is considered by the team to be a design mistake in original specification.

The specification itself has yet to be updated, but the team made the change in the browser behavior prior to any change having been made in the specification due to agreement within the working-group.

As of the time of writing this article (October 3rd, 2024), all other major browsers (Firefox, Safari) still follow the pre-Chrome 129 behavior.

Mitigating the Changes

If you just want to restore things to how they were pre-Chrome 129 (and in the meantime maintain consistency across browsers until Firefox and Safari update to follow Chrome's implementation), you can simply add contain: layout; to the element which has container-type: inline-size;.

If you want to add the containing block behavior but not create a new stacking context, you could alternatively add position: relative to the container-type: inline-size; element, which will create a containing block for child elements but not create a new stacking context. However, this will result in different behavior in different browsers until the point that other browsers update to follow Chrome's lead.

Try It Yourself

Below is a CodePen that you can play with that demonstrates what I am talking about above. If you remove contain: layout from the .container style, and if you're using Chrome 129 or later, the layout will show as it does in the second image I provided above. However, if you view the CodePen in Firefox 131 (latest as of writing), it should display the same regardless of whether contain: layout is set or not.

I wasn't able to find mention of this change in the release notes for Chrome 129, and as was already mentioned this change was made ahead of any specification change, so it really caught us off guard and significantly broke the layout on one of our web apps. I hope that this information can help anyone else having the same problems.

Top comments (0)