CSS: How to position two elements on top of each other, without specifying a height?
I have two DIVs that I need to position exactly on top of each other. However, when I do that, the formatting gets all screwed up because the containing DIV acts like there is no height. I think this is the expected behavior with position:absolute
but I need to find a way to position these two elements on top of each other and have the container stretch as the content stretches:
The top left edge of .layer2
should be exactly aligned to the top left edge of layer1
<!-- HTML -->
<div class="container_row">
<div class="layer1">
Lorem ipsum...
</div>
<div class="layer2">
More lorem ipsum...
</div>
</div>
<div class="container_row">
...same HTML as above. This one should never overlap the .container_row above.
</div>
/* CSS */
.container_row {}
.layer1 {
position:absolute;
z-index: 1;
}
.layer2 {
position:absolute;
z-index: 2;
}
Actually this is possible without position absolute
and specifying any height. All You need to do, is use display: grid
on parent element and put descendants, into the same row and column.
Please check example below, based on Your HTML. I added only <span>
and some colors, so You can see the result.
You can also easily change z-index
each of descendant elements, to manipulate its visibility (which one should be on top).
.container_row{
display: grid;
}
.layer1, .layer2{
grid-column: 1;
grid-row: 1;
}
.layer1 span{
color: #fff;
background: #000cf6;
}
.layer2{
background: rgba(255, 0, 0, 0.4);
}
<div class="container_row">
<div class="layer1">
<span>Lorem ipsum...<br>Test test</span>
</div>
<div class="layer2">
More lorem ipsum...
</div>
</div>
<div class="container_row">
...same HTML as above. This one should never overlap the .container_row above.
</div>
First of all, you really should be including the position on absolutely positioned elements or you will come across odd and confusing behavior; you probably want to add top: 0; left: 0
to the CSS for both of your absolutely positioned elements. You'll also want to have position: relative
on .container_row
if you want the absolutely positioned elements to be positioned with respect to their parent rather than the document's body:
If the element has 'position: absolute', the containing block is established by the nearest ancestor with a 'position' of 'absolute', 'relative' or 'fixed' ...
Your problem is that position: absolute
removes elements from the normal flow:
It is removed from the normal flow entirely (it has no impact on later siblings). An absolutely positioned box establishes a new containing block for normal flow children and absolutely (but not fixed) positioned descendants. However, the contents of an absolutely positioned element do not flow around any other boxes.
This means that absolutely positioned elements have no effect whatsoever on their parent element's size and your first <div class="container_row">
will have a height of zero.
So you can't do what you're trying to do with absolutely positioned elements unless you know how tall they're going to be (or, equivalently, you can specify their height). If you can specify the heights then you can put the same heights on the .container_row
and everything will line up; you could also put a margin-top
on the second .container_row
to leave room for the absolutely positioned elements. For example:
http://jsfiddle.net/ambiguous/zVBDc/
Great answer, "mu is too short". I was seeking the exact same thing, and after reading your post I found a solution that fitted my problem.
I was having two elements of the exact same size and wanted to stack them. As each have same size, what I could do was to make
position: absolute;
top: 0px;
left: 0px;
on only the last element. This way the first element is inserted correctly, "pushing" the parents height, and the second element is placed on top.
Hopes this helps other people trying to stacking 2+ elements with same (unknown) height.
Here's another solution using display: flex instead of position: absolute or display: grid.
.container_row{
display: flex;
}
.layer1 {
width: 100%;
background-color: rgba(255,0,0,0.5); // red
}
.layer2{
width: 100%;
margin-left: -100%;
background-color: rgba(0,0,255,0.5); // blue
}
<div class="container_row">
<div class="layer1">
<span>Lorem ipsum...</span>
</div>
<div class="layer2">
More lorem ipsum...
</div>
</div>
<div class="container_row">
...same HTML as above. This one should never overlap the .container_row above.
</div>