home file-empty pencil screen user heart reply share social loading

Keith J. Grant

Photo of Keith

Atlanta, GA
United States

Twitter
@keithjgrant
Github
keithjgrant
Author
CSS in Depth

Width and Absolute Positioning

I recently came across this question on Twitter:

“That’s easy”, I thought. “They often seem the same in practice, but width and height are based on the parent (or nearest block-level ancestor). Top, right, bottom, and left are based on the nearest positioned ancestor. Those aren’t necessarily the same element.”

Shows what I know: my quick mockup to illustrate the difference proved me wrong.

On first pass, top: 0; right: 0; bottom: 0; left: 0; and top: 0; left: 0; width: 100%; height: 100%; are equivalent. Of course, we always treat them as equivalent, because in most real-world cases, the nearest positioned ancestor is the nearest block-level element (usually the parent). But my codepen showed me an absolutely positioned element whose width and height are derived from the positioned ancestor, not the immediate container.

In retrospect, this makes a certain kind of sense, because the absolutely positioned element is removed from the normal flow. It’s then “contained” by the positioned ancestor.

So, the two scenarios are effectively the same. But a quick look at the spec made it clear that padding and margin would weigh in. So it might worth a little experimenting to see what we get.

Experimenting

So here’s the basic scenario I set up. Three elements: one relatively positioned as the anchor for the absolute positioning, one to serve as the parent, and then the child, which will be absolutely positioned. For better visibility, the positioned container has a faint background color, the parent has a purple border, and the child has a medium gray background (transparent, so the others will show through).

  <div class="positioned">
    <div class="parent">
      <div class="child">
      </div>
    </div>
  </div>
  .positioned {
    position: relative;
    background-color: rgba(0,0,255, 0.1);
  }

  .parent {
    width: 200px;
    min-height: 200px;
    border: 2px solid #936;
  }

  .child {
    position: absolute;
    background-color: rgba(0, 0, 0, 0.4);
  }

Then, we’ll play around with the child’s properties to see what happens. We’ll create two variations. First, one with top, right, bottom, and left all set to zero. And second, one with a top and left of zero, and a width and height of 100%.

.child {
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}
.child {
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

The two children appear identical. They overflow outside the parent, and fill the size of the positioned container. Visually, you can’t tell the difference between the container and the child. Let’s add some padding to the child and see what happens…

  .child {
    padding: 1em;
  }
...nothing. Note, I've got box-sizing: border-box set globally on the page. Let's turn that off:
  .child {
    box-sizing: content-box;
    padding: 1em;
  }

The padding still has no effect on the size of the first variation. But it adds to the width and height in the second; that child now overflows the positioned container. That makes sense. So there’s a key difference here, if you don’t have a global box-sizing fix in place.

Now let’s see what a margin does:

  .child {
    margin: 1em;
  }

Now that was unexpected, at least to me. With right: 0; bottom: 0, the margin is contained inside the positioned descendant; they will shrink the size of the element.

With width: 100%; height: 100%, the top and left margins are contained, but the element is shifted, maintaining its original size. The right and bottom margins are then added outside the whole structure.

What’s interesting is that in all these scenarios, the parent element doesn’t affect the shape of the child element at all—Though it does provide the height to the positioned container.

Take-away

So what does this mean? It seems to me that top: 0; right: 0; bottom: 0; left: 0 is probably the one to favor, as it’s a little more predictable, unless you have a particular reason to use height or width instead.

Loading interactions...

Recent posts