Absolute positioning ignoring padding of parent
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:
Add an extra relatively positioned
div
(with no padding) around the absolutely positioneddiv
. That newdiv
will respect the padding of its parent, and the absolutely positioneddiv
will then fill it.The downside, of course, is that you're messing with the HTML simply for presentational purposes.
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
orLESS
you can avoid that problem by using a variable. This is the method I personally use.
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.