ChatGPT解决这个技术问题 Extra ChatGPT

Make absolute positioned div expand parent div height

As you can see in the CSS below, I want child2 to position itself before child1. This is because the site I'm currently developing should also work on mobile devices, on which the child2 should be at the bottom, as it contains the navigation which I want below the content on the mobile devices. - Why not 2 masterpages? This is the only 2 divs which are repositioned in the entire HTML, so 2 masterpages for this minor change is an overkill.

HTML:

<div id="parent">
    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

parent { position: relative; width: 100%; }
child1 { width: auto; margin-left: 160px; }
child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; }

child2 has dynamic height, as different subsites could have more or less navigation items.

I know that absolute positioned elements are removed from the flow, thus ignored by other elements.
I tried setting overflow:hidden; on the parent div, but that didn't help, neither does the clearfix.

My last resort will be JavaScript to reposition the two divs accordingly, but for now I'll try and see if there exist a non-JavaScript way of doing this.

I'm not 100% sure but I think you'll probably have to go for a JS solution which works out the height of child2 and moves child1 accordingly.
This can be done by setting the parent's position to relative and the child to absolute.
See this Workaround maybe it can help.
If the parent is relative and the child is absolute and you wish to position the child at the bottom (ie the height of the parent), simply use top:100%.

M
Mrchief

You answered the question by yourself: "I know that absolute positioned elements are removed from the flow, thus ignored by other elements." So you can't set the parents height according to an absolutely positioned element.

You either use fixed heights or you need to involve JS.


I'm marking this as it technically is the correct way, though I found another solution to my problem, which is practically to nest the required css on the specific pages which has to differenciate (2 out of 40 at the moment).
Just thinking... If it's really out of the flow, how come the left padding of the parent element affects the absolutely positioned child element as well?
@user557419 if you found another solution pls put it in the answer
Hi, I tried put togeter a Javascript in React to adjust parent height, but get stuck, do you have any idea? stackoverflow.com/questions/69498478/…
l
lex82

Although stretching to elements with position: absolute is not possible, there are often solutions where you can avoid the absolute positioning while obtaining the same effect. Look at this fiddle that solves the problem in your particular case http://jsfiddle.net/gS9q7/

The trick is to reverse element order by floating both elements, the first to the right, the second to the left, so the second appears first.

.child1 {
    width: calc(100% - 160px);
    float: right;
}
.child2 {
    width: 145px;
    float: left;
}

Finally, add a clearfix to the parent and you're done (see the fiddle for the complete solution).

Generally, as long as the element with absolute position is positioned at the top of the parent element, chances are good that you find a workaround by floating the element.


M
MMB

There is a quite simple way to solve this.

You just have to duplicate the content of child1 and child2 in relative divs with display:none in parent div. Say child1_1 and child2_2. Put child2_2 on top and child1_1 at the bottom.

When your jquery (or whatever) calls the absolute div, just set the according relative div (child1_1 or child2_2) with display:block AND visibility:hidden. The relative child will still be invisible but will make parent's div higher.


This got me thinking in the right direction. In my case setting display: none on the "size holder" content makes the div not size, however opacity: 0, sizes the div correctly and doesn't require any additional jquery.
The way I did was to get two duplicate divs the first one is the visible content with position absolute and the second one is a div with visibility hidden that keeps the parent div with the correct height all works fine =D
L
Laurianti

Feeela is right but you can get a parent div contracting or expanding to a child element if you reverse your div positioning like this:

.parent {
    position: absolute;
    /* position it in the browser using the `left`, `top` and `margin` 
       attributes */
}

.child {
    position: relative;
    height: 100%;
    width: 100%;

    overflow: hidden;
    /* to pad or move it around using `left` and `top` inside the parent */
}

This should work for you.


S
Sam

This question was asked in 2012 before flexbox. The correct way to solve this problem using modern CSS is with a media query and a flex column reversal for mobile devices. No absolute positioning is needed.

https://jsfiddle.net/tnhsaesop/vjftq198/3/

HTML:

<div class="parent">
  <div style="background-color:lightgrey;">
    <p>
      I stay on top on desktop and I'm on bottom on mobile
    </p>
  </div>
  <div style="background-color:grey;">
    <p>
      I stay on bottom on desktop and I'm on top on mobile
    </p>
  </div>
</div>

CSS:

.parent {
  display: flex;
  flex-direction: column;
}

@media (max-width: 768px) {
  .parent {
    flex-direction: column-reverse;
  }
}

You could also use order: 2 on the first item if for example there are a lot of options and this specific option is required at the front.
A
AndrewL64

With pure JavaScript, you just need to retrieve the height of your static position child element .child1 using the getComputedStyle() method then set that retrieve value as the padding-top for that same child using the HTMLElement.style property.

Check and run the following Code Snippet for a practical example of what I described above:

/* JavaScript */ var child1 = document.querySelector(".child1"); var parent = document.getElementById("parent"); var childHeight = parseInt(window.getComputedStyle(child1).height) + "px"; child1.style.paddingTop = childHeight; /* CSS */ #parent { position: relative; width: 100%; } .child1 { width: auto; } .child2 { width: 145px; position: absolute; top: 0px; bottom: 0px; } html, body { width: 100%;height: 100%; margin: 0; padding: 0; }

STATIC
ABSOLUTE


b
bernatfortet

There's a very simple hack that fixes this issue

Here's a codesandbox that illustrates the solution: https://codesandbox.io/s/00w06z1n5l

HTML

<div id="parent">
  <div class="hack">
   <div class="child">
   </div>
  </div>
</div>

CSS

.parent { position: relative; width: 100%; }
.hack { position: absolute; left:0; right:0; top:0;}
.child { position: absolute; left: 0; right: 0; bottom:0; }

you can play with the positioning of the hack div to affect where the child positions itself.

Here's a snippet:

html { font-family: sans-serif; text-align: center; } .container { border: 2px solid gray; height: 400px; display: flex; flex-direction: column; } .stuff-the-middle { background: papayawhip url("https://camo.githubusercontent.com/6609e7239d46222bbcbd846155351a8ce06eb11f/687474703a2f2f692e696d6775722e636f6d2f4e577a764a6d6d2e706e67"); flex: 1; } .parent { background: palevioletred; position: relative; } .hack { position: absolute; left: 0; top:0; right: 0; } .child { height: 40px; background: rgba(0, 0, 0, 0.5); position: absolute; bottom: 0; left: 0; right: 0; }

I have stuff annoyingly in th emiddle
I'm inside of my parent but absolutely on top
I'm the parent
You can modify my height
and my child is always on top
absolutely on top
try removing this text


if there's a second child in hack class element with height say 300px and sibling element for parent class height 150px. We still cannot see the new sibling element of parent class
b
btx9000

I came up with another solution, which I don't love but gets the job done.

Basically duplicate the child elements in such a way that the duplicates are not visible.

<div id="parent">
    <div class="width-calc">
        <div class="child1"></div>
        <div class="child2"></div>
    </div>

    <div class="child1"></div>
    <div class="child2"></div>
</div>

CSS:

.width-calc {
    height: 0;
    overflow: hidden;
}

If those child elements contain little markup, then the impact will be small.


This can give some problems with search engine ranking
J
Juliano

I had a similar problem. To solve this (instead of calculate the iframe's height using the body, document or window) I created a div that wraps the whole page content (a div with an id="page" for example) and then I used its height.


N
Nikolay

"You either use fixed heights or you need to involve JS."

Here is the JS example:

---------- jQuery JS example--------------------

    function findEnvelopSizeOfAbsolutelyPositionedChildren(containerSelector){
        var maxX = $(containerSelector).width(), maxY = $(containerSelector).height();

        $(containerSelector).children().each(function (i){
            if (maxX < parseInt($(this).css('left')) + $(this).width()){
                maxX = parseInt($(this).css('left')) + $(this).width();
            }
            if (maxY < parseInt($(this).css('top')) + $(this).height()){
                maxY = parseInt($(this).css('top')) + $(this).height();
            }
        });
        return {
            'width': maxX,
            'height': maxY
        }
    }

    var specBodySize = findEnvelopSizeOfAbsolutelyPositionedSubDivs("#SpecBody");
    $("#SpecBody").width(specBodySize.width);
    $("#SpecBody").height(specBodySize.height);

This answer could benefit from better explanation and direction of the proposed solution.
r
rlasch

There is a better way to do this now. You can use the bottom property.

    .my-element {
      position: absolute;
      bottom: 30px;
    }

this will work only if you know the final height of the parent, which you don't
r
roy riojas

This is very similar to what @ChrisC suggested. It is not using an absolute positioned element, but a relative one. Maybe could work for you

<div class="container">
  <div class="my-child"></div>
</div>

And your css like this:

.container{
    background-color: red;
    position: relative;
    border: 1px solid black;
    width: 100%;
}

.my-child{
    position: relative;
    top: 0;
    left: 100%;
    height: 100px;
    width: 100px;
    margin-left: -100px;
    background-color: blue;
}

https://jsfiddle.net/royriojas/dndjwa6t/


I
Iegor Benzyk

Also consider next approach:

CSS:

.parent {
  height: 100%;
}
.parent:after {
  content: '';
  display: block;
}

Also since you are trying to reposition divs consider css grid


I
Isaac Sekamatte

Absolute views position themselves against the nearest ancestor that isn't statically positioned (position: static), therefore if you want an absolute view positioned against a given parent, set the parent position to relative and the child to position to absolute


s
sk8terboi87 ツ

Try this, it was worked for me

.child {
    width: 100%;
    position: absolute;
    top: 0px;
    bottom: 0px;
    z-index: 1;
}

It will set child height to parent height


great solution!
@AlexanderCherednichenko Not really, it misses the point of the question.