CSS: How to position two elements on top of each other, without specifying a height?

Css

Css Problem Overview


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;
}

Css Solutions


Solution 1 - Css

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>

Solution 2 - Css

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/

Solution 3 - Css

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.

Solution 4 - Css

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>

Solution 5 - Css

Here's some reusable css that will preserve the height of each element without using position: absolute:

.stack {
    display: grid;
}
.stack > * {
    grid-row: 1;
    grid-column: 1;
}

The first element in your stack is the background, and the second is the foreground.

Solution 6 - Css

I had to set

Container_height = Element1_height = Element2_height

.Container {
    position: relative;
}

.ElementOne, .Container ,.ElementTwo{
    width: 283px;
    height: 71px;
}

.ElementOne {
    position:absolute;
}

.ElementTwo{
    position:absolute;
}

Use can use z-index to set which one to be on top.

Solution 7 - Css

Due to absolute positioning removing the elements from the document flow position: absolute is not the right tool for the job. Depending on the exact layout you want to create you will be successful using negative margins, position:relative or maybe even transform: translate. Show us a sample of what you want to do we can help you better.

Solution 8 - Css

Of course, the problem is all about getting your height back. But how can you do that if you don't know the height ahead of time? Well, if you know what aspect ratio you want to give the container (and keep it responsive), you can get your height back by adding padding to another child of the container, expressed as a percentage.

You can even add a dummy div to the container and set something like padding-top: 56.25% to give the dummy element a height that is a proportion of the container's width. This will push out the container and give it an aspect ratio, in this case 16:9 (56.25%).

Padding and margin use the percentage of the width, that's really the trick here.

Solution 9 - Css

After much testing, I have verified that the original question is already right; missing just a couple of settings:

  • the container_row MUST have position: relative;
  • the children (...), MUST have position: absolute; left:0;
  • to make sure the children (...) align exactly over each other, the container_row should have additional styling:
    • height:x; line-height:x; vertical-align:middle;
    • text-align:center; could, also, help.

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
QuestionAndrewView Question on Stackoverflow
Solution 1 - CssinsteadView Answer on Stackoverflow
Solution 2 - Cssmu is too shortView Answer on Stackoverflow
Solution 3 - CsskraenhansenView Answer on Stackoverflow
Solution 4 - CssCorneliusView Answer on Stackoverflow
Solution 5 - CssKen MuellerView Answer on Stackoverflow
Solution 6 - CssArun Prasad E SView Answer on Stackoverflow
Solution 7 - CssLuiz SócrateView Answer on Stackoverflow
Solution 8 - CssLuke PuplettView Answer on Stackoverflow
Solution 9 - CssjustaguestpassingbyView Answer on Stackoverflow