39

Im trying to set an automatic height a div that contains 2 child elements, positioned fixed and absolutely respecitvely.

I want my parent container to have an auto height but I know this is hard as the child elements are taken out of the page structure with their positions.

I have tried setting a height to my parent div that works, but with my layout being responsive, when its scaled down to mobile, the height remains the same where as the content within becomes stacked and so the height needs to increase with its children.

Not sure if this makes sense, I dont have my actual code on me atm but ive made a fiddle trying to explain...

http://jsfiddle.net/dPCky/

Liam
  • 9,725
  • 39
  • 111
  • 209

8 Answers8

38

The parent div can not use height:auto when its children are positioned absolute / fixed.

You would need to use JavaScript to achieve this.

An example in jQuery:

var biggestHeight = 0;
// Loop through elements children to find & set the biggest height
$(".container *").each(function(){
 // If this elements height is bigger than the biggestHeight
 if ($(this).height() > biggestHeight ) {
   // Set the biggestHeight to this Height
   biggestHeight = $(this).height();
 }
});

// Set the container height
$(".container").height(biggestHeight);

Working example http://jsfiddle.net/blowsie/dPCky/1/

Blowsie
  • 40,239
  • 15
  • 88
  • 108
  • Ahh brilliant @Blowise, Can I ask what does the * in the selector do? and I can I ask how does this work exactly? – Liam Jan 30 '12 at 09:25
  • 1
    * selects all children, I could have also written $(".container").children().each(), which would probably be more efficient. If you wanted to select only direct children and not children of children you do something like $(".container > *") – Blowsie Jan 30 '12 at 09:30
  • 2
    read more on the * selector, and other selectors here. http://net.tutsplus.com/tutorials/html-css-techniques/the-30-css-selectors-you-must-memorize/ – Blowsie Jan 30 '12 at 09:33
  • Thanks @Blowsie, but how does biggestHeight var work? does it take the value of all the children heights added together? – Liam Jan 30 '12 at 09:35
  • This wont work if you use actual positioning, see altered fiddle: http://jsfiddle.net/ugdn8khn/ – N4ppeL Jul 24 '15 at 14:10
  • @N4ppeL of course it won't. This to me at least seems obvious. – Blowsie Jul 29 '15 at 11:03
  • This code sets the height of all elements with class `container` to `biggestHeight`. You must only set height for each container individually. – djmj Mar 28 '16 at 15:38
  • @djmj yes the above example assumes there is only one `.container` on the page, feel free to update the answer if you feel its required. – Blowsie Mar 29 '16 at 12:45
  • @Blowsie is there a way to update the .container when the browser window size changes? Because the value seems to remain static? I was using your code but doesnt seem to update when the children DIVs sizes change. Thanks. – Ninjab Jul 05 '18 at 05:54
  • 1
    @Ninjab of course, you can wrap the function in a `$(window).on('resize', function(){})` However if you do this you should definitely use two things to help the performance. - *Debounce the function calls - to prevent them being called too often* - *Cache the elements you are going to resize into variables, for performance* – Blowsie Jul 11 '18 at 15:08
  • 1
    @Ninjab, since this answer is fairly old, depending on your use case you may want to use newer CSS only methods, which are now more viable due to modern browsers support for CSS – Blowsie Jul 11 '18 at 15:11
  • @Blowsie thanks for the detailed response. I did the resize function and seems to work ok. But how would you do it with CSS instead as would prefer to use that instead? Thanks :) – Ninjab Jul 11 '18 at 18:29
  • 1
    @Ninjab depends on your scenario, but using `vh` units is a possibility. – Blowsie Jul 12 '18 at 14:00
7

http://jsfiddle.net/dPCky/32/ - A similar effect using float:left;

http://jsfiddle.net/dPCky/40/ - An even closer result to your desired effect.

If you're willing to change your html, then you could do what I have done above.

I learned positioning from the following tutorials which I would highly recommend to anyone who wants to become a positioning pro in html/css:

http://www.barelyfitz.com/screencast/html-training/css/positioning/

I would generally avoid using javascript where possible when doing something that could potentially have a css or html level fix, if you're willing to adjust your html.

feelinferrety
  • 197
  • 1
  • 14
Anicho
  • 2,647
  • 11
  • 48
  • 76
  • 3
    "I would generally avoid using JavaScript where possible" very true in this example, especially if your content is dynamic or your width is fluid – Blowsie Jan 30 '12 at 10:01
  • @Blowsie can I ask why you would avoid it if your width is fluid? Can you not run the function with .resize() ? – Liam Jan 30 '12 at 12:59
  • 1
    @Liam You could indeed use the $(window).resize(); event to re-run your function. The reason for not using the script in fluid widths is if the elements themselves have fluid widths the height of the elements will change depending on your screen window width, so you would have to resize them every time the window size changes. – Blowsie Feb 01 '12 at 10:35
5

If you don't want to use JavaScript, you could refer this answer https://stackoverflow.com/a/33788333/1272106.

Short description: duplicate one element and set visibility to hide to expand the parent.

Ricky Jiao
  • 531
  • 4
  • 10
3

A little late to the party, but this may help someone as this is how I resolved the issue recently without JS - IF the children maintain their aspect ratio as they shrink for mobile devices. My example relates to making a jQuery.cycle slideshow responsive, for context. Unsure if this is what you're trying to achieve above, but it involved absolutely positioned children within a container which has 100% page width on mobile and explicit dimensions on larger screens.

You can set the parent's height to use viewport width units (vw), so the height adapts relative to the device's width. Support is broad enough these days that most mobile devices will use these units correctly, bugs and partial support don't relate to vw (but rather, to vmin and vmax in IE). Only Opera Mini is in the dark.

Without knowing what the children are doing between responsive points in this example (the jsfiddle has explicit heights set), let's assume the height of the children scales down predictably relative to the device width, which allows you to fairly accurately assume the height based on aspect ratio.

.container{ height: 75vw; }

http://caniuse.com/#feat=viewport-units

Do note known issue #7 on caniuse if you're going for 100vw as a width measure, but here we're playing with height!

Shale
  • 31
  • 2
1

Enjoy this auto height for container that adapts to any device and viewport resize or rotation.

It has been tested with float, inline-block, absolute, margins and padding set to the childs.

<div class="autoheight" style="background: blue">
    <div style="position: absolute; width: 33.3%; background: red">
    Only
        <div style="background: green">
        First level elements are measured as expected
        </div>
    </div>
    <div style="float:left; width: 33.3%; background: red">
    One Two Three Four Five Six Seven Eight Night Ten
    </div>
    <div style="float:left; width: 33.3%; background: red">
    One Two Three Four Five Six
    </div>
</div>

<script>
function processAutoheight()
{
    var maxHeight = 0;

    // This will check first level children ONLY as intended.
    $(".autoheight > *").each(function(){

        height = $(this).outerHeight(true); // outerHeight will add padding and margin to height total
        if (height > maxHeight ) {
            maxHeight = height;
        }
    });

    $(".autoheight").height(maxHeight);
}

// Recalculate under any condition that the viewport dimension has changed
$(document).ready(function() {

    $(window).resize(function() { processAutoheight(); });

    // BOTH were required to work on any device "document" and "window".
    // I don't know if newer jQuery versions fixed this issue for any device.
    $(document).resize(function() { processAutoheight(); });

    // First processing when document is ready
    processAutoheight();
});
</script>
Heroselohim
  • 1,241
  • 1
  • 18
  • 23
0

Related to @Blowsie's answer:

/**
 * Sets the height of a container to its maximum height of its children. This
 * method is required in case
 * 
 * @param selector jQuery selector
 */
function setHeightByChildrenHeight(selector)
{
    $(selector).each(function()
    {
        var height = 0;

        $(this).children("*").each(function()
        {
            height = Math.max(height, $(this).height());
        });

        $(this).height(height);
    });
};
djmj
  • 5,579
  • 5
  • 54
  • 92
-1

The right way... simple. No Javascript.

<div class="container">
    <div class="faq-cards">    
      <div class="faq-cards__card">Im A Card</div>
      <div class="faq-cards__card">Im A Card</div> 
      <div class="faq-cards__card">Im A Card</div> 
      <div class="faq-cards__card">Im A Card</div> 
      <div class="faq-cards__card">Im A Card</div> 
      <div class="faq-cards__card">Im A Card</div> 
      <div class="faq-cards__card">Im A Card</div>
    </div>
</div>
.container { 
    height: auto;
    width: 1280px;

    margin: auto;
    background: #CCC;
}

.faq-cards { 
    display: flex;
    flex-wrap: wrap;
    justify-content: center;

    position: relative;
    bottom: 40px;

    height: auto;
}

.faq-cards__card {
    position: relative;

    margin: 10px;
    padding: 10px;

    width: 225px;
    height: 100px;

    background: beige;
    text-align: center;
}

https://codepen.io/GerdSuhr/pen/jgqOJp

Foobar
  • 7
  • 1
-5

An easier way is:

$(".container").height($(document).height());
arulmr
  • 8,620
  • 9
  • 54
  • 69