Backgrounds for the Box Model (and why it can be useful)

I had someone write to me the other day that they were trying to visualize the different parts of the box model. They said they would just code up an example themselves, but there is no way to, say, set a background color for just the “padding” area of an element.

What they were talking about is something like this, the box model diagram available in DevTools:

Box Model in Chrome DevTools

I said, I think you… can! actually!

The trick lays in using the background-clip property in CSS, which allows you to stop the background-image property at different points in the box model. Here’s a really basic example of doing that, using the same colors as the model above:

The only one I’m “faking” there is the very outer shape (margin), which is drawn with an outline. It does match the value of margin though so it’s basically real!

I was a bit inspired to keep going, making all the values dynamic, so I made this, which labels the section as well.

I put a grid of content around it so that you could see the element push others away like the real box model does.

Is this actually useful ever? Sometimes!

Just the other day Wes Bos posted a really nice button effect and then re-created in HTML and CSS:

There is no real big problem with how Wes did it there, but he did use an extra element as well as pseudo elements to get it done. Here’s his demo.

Ana Tudor chimed in that it could be done without using any extra elements, and guess how? Background clipping!

I took a crack at that, and aside from a bit of an awkward need to set the background-size, I think I got it working:

This may actually be truly useful sometimes. For example, a CMS that is happy to spit out a <button> element but doesn’t offer inner HTML control of it. If you don’t need that anyway and can pull of the effect in CSS entirely, you’re in business.

Because I’m a glutton for punishment sometimes, I also decided to have a crack at it using border-image as well, which despite being the lest scrutable CSS property of all time, seems at least conceptually like the correct thing to use. I was able to get it working!

But for whatever reason border-image is incompatible with border-radius, so, whatever, that sucks.

Want to expand your CSS skills?

2 responses to “Backgrounds for the Box Model (and why it can be useful)”

  1. Mojtaba Mojtaba says:

    I made a video explaining three more way to create such an effect and how to decide which way is the right one for your situation: https://www.youtube.com/watch?v=SRdZj0KfZ5s

  2. Ana Tudor Ana Tudor says:

    “I took a crack at that, and aside from a bit of an awkward need to set the background-size”

    You don’t need to set background-size (nor background-position for that matter), you need to set background-origin to border-box. That’s what I meant with “make the conic-gradient() relative to border-box” and that’s why the border-box after the conic-gradient() in my example code.

    Generally, “relative to” = background-origin, “restricted to” = background-clip.

    Gradients are sized and positioned relative to the background-origin. By default, this is set to padding-box, so if there’s a border the gradient stretches from the top left corner of the padding-box across the entire padding-box. Then, since backgrounds are repeating by default, it repeats outside the padding-box in the border area.

    But if we change the background-origin to border-box, then the gradient stretches across the border-box from its top left corner.

    Both background-origin and background-clip can be set in the shorthand. If we have two box values in the shorthand, the first applies to background-origin and the second to background-clip. If we have a single box value in the shorthand, it applies to both.

    The first gradient is the cover and we want to set its background-clip to padding-box, not just its background-origin (which is already padding-box by default). So a single padding-box value after it does it – it sets the background-origin to its default and background-clip to the value we want in this case.

    The second gradient is the one we want to see in the border area and we want it sized relative to the border-box. So we want to set its background-origin to border-box, not just its background-clip (which is already border-box) by default. So a single border-box value after the conic-gradient() does it – it sets background-origin to the value we want in this case and background-clip to its default.

    Basically, the code is just:

    background: 
      var(--cover) padding-box, 
      conic-gradient(var(--stop-list)) border-box
    

    As for seeing the box model, I made a demo showing it in 3D too and how the roundings for the inner boxes are computed (border-radius applies to the border-box) https://codepen.io/thebabydino/pen/ZNeRbZ

Leave a Reply

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

$966,000

Master.dev donates to open source projects through thanks.dev and Open Collective, as well as donates to non-profits like The Last Mile, Annie Canons, and Vets Who Code.