Absolute positioning ignoring padding of parent

CssPaddingCss Position

Css Problem Overview


How do you make an absolute positioned element honor the padding of its parent? I want an inner div to stretch across the width of its parent and to be positioned at the bottom of that parent, basically a footer. But the child has to honor the padding of the parent and it's not doing that. The child is pressed right up against the edge of the parent.

So I want this:

enter image description here

but I'm getting this:

enter image description here

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
      <div style="background-color: gray; position: absolute; left: 0px; right: 0px; bottom: 0px;">css sux</div>
    </div>
  </body>
</html>

I can make it happen with a margin around the inner div, but I'd prefer not to have to add that.

Css Solutions


Solution 1 - Css

First, let's see why this is happening.

The reason is that, surprisingly, when a box has position: absolute its containing box is the parent's padding box (that is, the box around its padding). This is surprising because usually (that is, when using static or relative positioning) the containing box is the parent's content box.

Here is the relevant part of the CSS specification:

> In the case that the ancestor is an inline element, the containing block is the bounding box around the padding boxes of the first and the last inline boxes generated for that element.... Otherwise, the containing block is formed by the padding edge of the ancestor.

The simplest approach—as suggested in Winter's answer—is to use padding: inherit on the absolutely positioned div. It only works, though, if you don't want the absolutely positioned div to have any additional padding of its own. I think the most general-purpose solutions (in that both elements can have their own independent padding) are:

  1. Add an extra relatively positioned div (with no padding) around the absolutely positioned div. That new div will respect the padding of its parent, and the absolutely positioned div will then fill it.

    The downside, of course, is that you're messing with the HTML simply for presentational purposes.

  2. Repeat the padding (or add to it) on the absolutely positioned element.

    The downside here is that you have to repeat the values in your CSS, which is brittle if you're writing the CSS directly. However, if you're using a pre-processing tool like SASS or LESS you can avoid that problem by using a variable. This is the method I personally use.

Solution 2 - Css

One thing you could try is using the following css:

.child-element {
    padding-left: inherit;
    padding-right: inherit;
    position: absolute;
    left: 0;
    right: 0;
}

It lets the child element inherit the padding from the parent, then the child can be positioned to match the parents widht and padding.

Also, I am using box-sizing: border-box; for the elements involved.

I have not tested this in all browsers, but it seems to be working in Chrome, Firefox and IE10.

Solution 3 - Css

Well, this may not be the most elegant solution (semantically), but in some cases it'll work without any drawbacks: Instead of padding, use a transparent border on the parent element. The absolute positioned child elements will honor the border and it'll be rendered exactly the same (except you're using the border of the parent element for styling).

Solution 4 - Css

Here is my best shot at it. I added another Div and made it red and changed you parent's height to 200px just to test it. The idea is the the child now becomes the grandchild and the parent becomes the grandparent. So the parent respects its parent. Hope you get my idea.

<html>
  <body>
    <div style="background-color: blue; padding: 10px; position: relative; height: 200px;">
     <div style="background-color: red;  position: relative; height: 100%;">	
      	<div style="background-color: gray; position: absolute; left: 0px; right: 0px;bottom: 0px;">css sux</div>
     </div>
    </div>
  </body>
</html>

Edit:

I think what you are trying to do can't be done. Absolute position means that you are going to give it co-ordinates it must honor. What if the parent has a padding of 5px. And you absolutely position the child at top: -5px; left: -5px. How is it suppose to honor the parent and you at the same time??

My solution

If you want it to honor the parent, don't absolutely position it then.

Solution 5 - Css

Solution 6 - Css

1.) you cannot use big border on parent -- in case you want to have a specific border

2.) you cannot add margin -- in case your parent is a part of some other container and you want your parent to take the full width of that grand parent.

The Only Solution that should be applicable is to wrap your children's in an another container so that your parent becomes the grandparent and then apply padding to the new children's Wrapper / Parent. Or you can directly apply padding to the children.

In your case:

.css-sux{
  padding: 0px 10px 10px 10px;
}

Solution 7 - Css

Could have easily done using an extra level of Div.

<div style="background-color: blue; padding: 10px; position: relative; height: 100px;">
  <div style="position: absolute; left: 0px; right: 0px; bottom: 10px; padding:0px 10px;">
    <div style="background-color: gray;">css sux</div>
  </div>
</div>

Demo: https://jsfiddle.net/soxv3vr0/

Solution 8 - Css

add padding:inherit in your absolute position

.box{
  background: red;
  position: relative;
  padding: 30px;
  width:500px;
  height:200px;
 box-sizing: border-box;
 

}

<div  class="box">

  <div style="position: absolute;left:0;top:0;padding: inherit">top left</div>
  <div style="position: absolute;right:0;top:0;padding: inherit">top right</div>
  <div style="text-align: center;padding: inherit">center</div>
  <div style="position: absolute;left:0;bottom:0;padding: inherit">bottom left</div>
  <div style="position: absolute;right:0;bottom:0;padding: inherit">bottom right</div>


</div>

Solution 9 - Css

I would set the child's width this way:

.child {position: absolute; width: calc(100% - padding);}

Padding, in the formula, is the sum of the left and right parent's padding. I admit it is probably not very elegant, but in my case, a div with the function of an overlay, it worked.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questiond512View Question on Stackoverflow
Solution 1 - CssKevin Christopher HenryView Answer on Stackoverflow
Solution 2 - CssWinterView Answer on Stackoverflow
Solution 3 - CssNewSpenderView Answer on Stackoverflow
Solution 4 - CssTouchView Answer on Stackoverflow
Solution 5 - CssNiloctView Answer on Stackoverflow
Solution 6 - Cssbhavya_wView Answer on Stackoverflow
Solution 7 - CssasankasriView Answer on Stackoverflow
Solution 8 - CssßãlãjîView Answer on Stackoverflow
Solution 9 - CssGigaView Answer on Stackoverflow