DEV Community

Konnor Rogers
Konnor Rogers

Posted on

Revisiting box-sizing best practices

We've all googled "best way to set box-sizing: border-box;" and come across this fun article from CSS Tricks about setting box sizing.

https://css-tricks.com/box-sizing/

If you haven't read it, let me spare you some time.

Here's the "recommended" approach due to increased flexibility.

https://css-tricks.com/box-sizing/#aa-universal-box-sizing-with-inheritance

html {
  box-sizing: border-box;
}
*, *:before, *:after {
  box-sizing: inherit;
}
Enter fullscreen mode Exit fullscreen mode

While this works if all of your elements are in the light DOM, tonight I discovered a fun bug plaguing my site.

If you have an element that is "slotted" into a custom element's shadow DOM, it will "inherit" the box-sizing of the slot element.

Example:

<script type="module">
  class MyElement extends HTMLElement {
    connectedCallback () {
      this.attachShadow({ mode: "open" })

      // These slots are automatically 
      // "box-sizing: content-box;" 
      // so this default slot causes all its children to have
      // the same box-sizing properties...
      this.shadowRoot.innerHTML = `<slot></slot>`
    }
  }
  window.customElements.define("my-custom-element", MyElement)
</script>

<style>
  html {
    box-sizing: border-box;
  }

  *, *:after, *:before {
    box-sizing: inherit;
  }
</style>

<my-custom-element>
  <div>My box sizing is "content-box"</div>
</my-custom-element>

<div>My box sizing is "border-box"</div>
Enter fullscreen mode Exit fullscreen mode

If you'd prefer, I also made a CodePen reproducing this issue.

https://codepen.io/paramagicdev/pen/abRPJjB?editors=1111

The "fix" is to use the "universal" box-sizing selector.

*,*:after,*:before {
  box-sizing: border-box;
}
Enter fullscreen mode Exit fullscreen mode

Now, I don't know if the inherited box-sizing is a bug, but it sure does feel like a bug. But, at least there is a workaround. I tested in Firefox, Chrome, Safari, and Edge and got the same result in all 4. Modifying the box-sizing of the parent slot element does indeed fix it like you would expect.

Top comments (2)

Collapse
 
bendelarre profile image
Ben Delarre • Edited

I think this makes sense.

Slot elements are inside the shadow root of their host. As such they don't get the inherit applied to their border-box because they are not selected by the universal with inheritance selector. Therefore they get the default content-box box-model, and the children slotted inside which do get specified to inherit will naturally inherit through their new projected hierarchy and end up content-box too.

This also happens with some other native elements like the details element which is implemented with a shadowdom.

So, not a bug, just a surprising consequence of properties which are not inherit by default and the side effect of shadowdom encapsulation. When you think about it you really don't want this selector kicking in all down a shadowdom hierarchy, you might inadvertently break a lot of layout behaviors if it did.

Collapse
 
konnorrogers profile image
Konnor Rogers • Edited

Perhaps "bug" is the wrong word here. Perhaps "surprising" at first, but I think it does technically make sense as I've had time to think about it.