68

My HTML code is just dividing the pages into two columns, 65%,35% respectively.

<div style="float : left; width :65%; height:auto;background-color:#FDD017;">
   <div id="response">
   </div> 
</div>
<div style="float : left; width :35%;height:auto; background-color:#FDD017;">
   <div id="note">
   </div>
</div> 

In the response div, I have variable data; in the note div, I have fixed data. Even though the two divs have two different sets of data, I need them to display with the same height so that the background colors appear to fill a box containing both. Naturally, the problem is the response div, as its height varies depending on the amount of data currently being displayed within it.

How might I ensure that the height of the two columns are always equal?

Shog9
  • 156,901
  • 35
  • 231
  • 235
venkatachalam
  • 102,353
  • 31
  • 72
  • 77

11 Answers11

99

Wrap them in a containing div with the background color applied to it, and have a clearing div after the 'columns'.

<div style="background-color: yellow;">
  <div style="float: left;width: 65%;">column a</div>
  <div style="float: right;width: 35%;">column b</div>
  <div style="clear: both;"></div>
</div>

Updated to address some comments and my own thoughts:

This method works because its essentially a simplification of your problem, in this somewhat 'oldskool' method I put two columns in followed by an empty clearing element, the job of the clearing element is to tell the parent (with the background) this is where floating behaviour ends, this allows the parent to essentially render 0 pixels of height at the position of the clear, which will be whatever the highest priorly floating element is.

The reason for this is to ensure the parent element is as tall as the tallest column, the background is then set on the parent to give the appearance that both columns have the same height.

It should be noted that this technique is 'oldskool' because the better choice is to trigger this height calculation behaviour with something like clearfix or by simply having overflow: hidden on the parent element.

Whilst this works in this limited scenario, if you wish for each column to look visually different, or have a gap between them, then setting a background on the parent element won't work, there is however a trick to get this effect.

The trick is to add bottom padding to all columns, to the max amount of size you expect that could be the difference between the shortest and tallest column, if you can't work this out then pick a large figure, you then need to add a negative bottom margin of the same number.

You'll need overflow hidden on the parent object, but the result will be that each column will request to render this additional height suggested by the margin, but not actually request layout of that size (because the negative margin counters the calculation).

This will render the parent at the size of the tallest column, whilst allowing all the columns to render at their height + the size of bottom padding used, if this height is larger than the parent then the rest will simply clip off.

<div style="overflow: hidden;">
  <div style="background: blue;float: left;width: 65%;padding-bottom: 500px;margin-bottom: -500px;">column a<br />column a</div>
  <div style="background: red;float: right;width: 35%;padding-bottom: 500px;margin-bottom: -500px;">column b</div>
</div>

You can see an example of this technique on the bowers and wilkins website (see the four horizontal spotlight images the bottom of the page).

meandmycode
  • 17,067
  • 9
  • 48
  • 42
  • 3
    Won't help if the two columns has different background colors. – Arve Systad Feb 08 '09 at 22:42
  • 13
    His example does not have this requirement, thanks for the downvote though :). – meandmycode Feb 09 '09 at 22:21
  • I know this is really old, but +1 anyway. Can you explain why this works? – Parris Varney Nov 17 '10 at 01:25
  • Worked perfectly for me on a project I am futzing with. Thanks. +1 –  May 11 '11 at 07:58
  • Would you recommend using margin-padding hack or just putting content in to td tags on the same row? – grisevg Sep 09 '11 at 13:49
  • Very late to the party on this one. It seems like this solution won't be so good if your page can be of wildly varying heights. e.g. page 1 has an overall height of 600px, but page 2 lists out a ton of stuff, and so has an overall height of 3000px. Using this solution, you'd have to make *all* the pages on the site 3000px high, right? Or am I mis-reading how this is supposed to work. – hairbo Nov 02 '11 at 14:51
  • yes, the sizes of the bottom padding and margin are never rendered, most of the time I set these values to 9999px, however that can be annoying when debugging with chrome/firefox as the apparent size of the columns will be huge when the selection border shows. – meandmycode Nov 02 '11 at 16:00
  • Also using `min-height`, `max-height` is usefull, so that your content in the left or right colomn is always in-line, with more or less data allowed. – ArendE Jul 19 '12 at 14:50
  • +1 my friend; I can't believe how quick and simple this fix was yet I was unable to think of it myself. – lxndr Jun 07 '13 at 16:42
38

If you are trying to force a floating div to match another to create a column effect, this is what I do. I like it because it's simple and clean.

<div style="background-color: #CCC; width:300px; overflow:hidden; ">
    <!-- Padding-Bottom is equal to 100% of the container's size, Margin-bottom hides everything beyond
         the container equal to the container size. This allows the column to grow with the largest
         column. -->
    <div style="float: left;width: 100px; background:yellow; padding-bottom:100%; margin-bottom:-100%;">column a</div>
    <div style="float: left;width: 100px;  background:#09F;">column b<br />Line 2<br />Line 3<br />Line 4<br />Line 5</div>
    <div style="float:left; width:100px; background: yellow; padding-bottom:100%; margin-bottom:-100%;">Column C</div>
    <div style="clear: both;"></div>
</div>

I think this makes sense. It seems to work well even with dynamic content.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Dyson
  • 389
  • 3
  • 2
  • yea..100% sounds much better than a very high fixed number..thanks for this – Jags Oct 01 '11 at 17:46
  • 3
    The only problem with this is that I want a border around each column, and this will hide the bottom border. :( – Alexander Bird Apr 05 '12 at 17:13
  • +1 for an interesting technique. After some experimentation, I noticed that percentage values of padding actually is based on the width of the element, therefore it may be a good idea to go higher than 100% (for portrait views). See [mdn](https://developer.mozilla.org/en-US/docs/CSS/padding). – stianlik Feb 13 '13 at 09:01
  • One of the really great aspects about this technique is it seems to be highly compatible with CSS frameworks such as Foundation. Also it does not impact a matrix being condensed to a single column in mobile views. All in all i think this is the #1 solution. – Chris Marisic Aug 07 '14 at 18:38
  • One thing... instead of
    you can add a :after to the parent. This removes the meaningless markup
    – Katherine C Mar 17 '15 at 19:50
  • This doesn't seem to work with `vertical-align: center;`, any idea how to fix that? – Dan Bechard Oct 28 '16 at 13:54
15

Here is a jQuery plugin to set the heights of multiple divs to be the same. And below is the actual code of the plugin.

$.fn.equalHeights = function(px) {
$(this).each(function(){
var currentTallest = 0;
$(this).children().each(function(i){
    if ($(this).height() > currentTallest) { currentTallest = $(this).height(); }
        });
    if (!px || !Number.prototype.pxToEm) currentTallest = currentTallest.pxToEm(); //use ems unless px is specified
        // for ie6, set height since min-height isn't supported
    if ($.browser.msie && $.browser.version == 6.0) { $(this).children().css({'height': currentTallest}); }
        $(this).children().css({'min-height': currentTallest}); 
    });
    return this;
};
Justin Yost
  • 2,340
  • 19
  • 31
  • 2
    Depending on the design, using javascript like this might be the only option. – Johan Kronberg Jun 21 '10 at 11:26
  • 1
    The pure CSS solutions work very rarely because they are meant for simplistic designs. I generally uses scripts like these. But one should be careful when dealing with AJAX. – Eastern Monk Feb 20 '11 at 11:38
  • +1, and @JohanKronberg +1 I've just run into the one of those times so thanks. – lsl Nov 01 '11 at 01:23
  • 1
    `if (!px && Number.prototype.pxToEm)` fixes it in case you have the same problem I did. – lsl Nov 01 '11 at 01:51
  • 4
    @akshar-prabhu-desai AJAX?!?, please point me where is Asynchronous JavaScript in this answer. – gok Dec 10 '11 at 16:30
  • Readers be very wary of this script, if you include this plugin it is licensed as GPL v2. Embedding GPL v2 javascript in your application is commonly accepted to mean **you must open source your entire website**. – Chris Marisic Aug 07 '14 at 18:43
  • @ChrisMarisic you have a typo: "commonly accepted to mean **you must open source your entire website if you choose to distribute it. Even then, you are not required to put it up for download -- it simply must be available if someone wants it via fax and is willing to pay your "source code handling, copying, and 56k fax modem fees".** – dhaupin Jun 07 '16 at 17:49
  • @dhaupin **IANAL** however it's generally regarded that hosting javascript inside a webserver and a standalone web browser downloading it constitutes distribution. Distributing it from the webserver to the browser. Not many orgs would be comfortable allowing their competitor to request them to fax their entire application source code. This isn't a distinction of where the code is available but that it legally **must be available**. The GPL license is a virus and it infects you. The fact it's applied to a plugin for a true FOSS project borders on malevolent. – Chris Marisic Jun 07 '16 at 18:00
10

The correct solution for this problem is to use display: table-cell

Important: This solution doesn't need float since table-cell already turns the div into an element that lines up with the others in the same container. That also means you don't have to worry about clearing floats, overflow, background shining through and all the other nasty surprises that the float hack brings along to the party.

CSS:

.container {
  display: table;
}
.column {
  display: table-cell;
  width: 100px;
}

HTML:

<div class="container">
    <div class="column">Column 1.</div>
    <div class="column">Column 2 is a bit longer.</div>
    <div class="column">Column 3 is longer with lots of text in it.</div>
</div>

Related:

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
6

You should wrap them in a div with no float.

<div style="float:none;background:#FDD017;" class="clearfix">
    <div id="response" style="float:left; width:65%;">Response with two lines</div>
    <div id="note" style="float:left; width:35%;">single line note</div>
</div>

I also use the clearfix patch on here http://www.webtoolkit.info/css-clearfix.html

bendewey
  • 39,709
  • 13
  • 100
  • 125
  • 2
    Won't help if the two columns has different background colors. Unless you know that one of the columns will always be longer than the other: Give the "wrapper" the backgorund color of the shortest column and let the longest column have its own background to "fake" two equally long columns. – Arve Systad Feb 08 '09 at 22:44
  • @Arve Systad agreed, It doesn't seem like that is what the OP is looking for. – bendewey Feb 09 '09 at 02:19
  • What if I want to use two different colors for each div? – Vixed Feb 17 '16 at 10:26
4

I can't understand why this issue gets pounded into the ground when in 30 seconds you can code a two-column table and solve the problem.

This div column height problem comes up all over a typical layout. Why resort to scripting when a plain old basic HTML tag will do it? Unless there are huge and numerous tables on a layout, I don't buy the argument that tables are significantly slower.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Erich Richter
  • 73
  • 1
  • 1
  • Most of the customers know that "div based layout" is the hot thing and they tell us not to use tables. Have met many customers who wanted 0 tables in all the designs layouts. – Eastern Monk Feb 20 '11 at 11:39
  • 10
    Tables are for tables. CSS is for layout. The op question is simple, but the solution should scale to any complexity. What if i have a 16-columns layout? I can use a 16-column table, but what when i want to change the site style? I have a messy as hell code. – Marek Maurizio Aug 18 '11 at 11:42
1

Flex does this by default.

<div id="flex">
 <div id="response">
 </div> 
 <div id="note">
 </div>
</div>   

CSS:

#flex{display:flex}
#response{width:65%}
#note{width:35%}

https://jsfiddle.net/784pnojq/1/

BONUS: multiple rows

https://jsfiddle.net/784pnojq/2/

Nick Manning
  • 2,828
  • 1
  • 29
  • 50
0

You can always use a background image to do it too. I tend to vote for this option 100% of the time as the only other perfect solution is the Jquery option.

As with using the outer div with a background color you'll end up having to have the content in both divs reaching the same height.

Drew
  • 1
0

Having had the same sort of problem as well, requiring three divs next to each other with different content, with right-borders to 'seperate' them, the only solution that worked was a slightly modified version of the jQuery option in another answer. Remember you also need the script found here.

Below is my slightly modified version of the script, which just allows for a true min-height setting (as I needed my boxes to be at least a certain height).

/*--------------------------------------------------------------------
 * JQuery Plugin: "EqualHeights"
 * by:    Scott Jehl, Todd Parker, Maggie Costello Wachs (http://www.filamentgroup.com)
 *
 * Copyright (c) 2008 Filament Group
 * Licensed under GPL (http://www.opensource.org/licenses/gpl-license.php)
 *
 * Description:   Compares the heights or widths of the top-level children of a provided element
                  and sets their min-height to the tallest height (or width to widest width). Sets in em units
                  by default if pxToEm() method is available.
 * Dependencies: jQuery library, pxToEm method    (article:
                  http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/)
 * Usage Example: $(element).equalHeights();
                  Optional: to set min-height in px, pass a true argument: $(element).equalHeights(true);
                  Optional: to specify an actual min-height (in px), pass an integer value, regardless of previous parameter: $(element).equalHeights(false,150);
 * Version: 2.0, 08.01.2008
--------------------------------------------------------------------*/

$.fn.equalHeights = function(px,minheightval) {
    $(this).each(function(){
        if (minheightval != undefined) { 
            var currentTallest = minheightval;    
        } 
        else { 
            var currentTallest = 0;
        }
        $(this).children().each(function(i){
            if ($(this).height() > currentTallest) { 
                currentTallest = $(this).height();
            }
        });
        if (!px || !Number.prototype.pxToEm) 
            currentTallest = currentTallest.pxToEm(); //Use ems unless px is specified.
        // For Internet Explorer 6, set height since min-height isn't supported.
        if ($.browser.msie && $.browser.version == 6.0) { 
            $(this).children().css({'height': currentTallest});
        }
        $(this).children().css({'min-height': currentTallest});
    });
    return this;
};

It works like a charm and doesn't slow anything down :)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
David
  • 493
  • 2
  • 6
  • 16
  • Readers be very wary of this script, if you include this plugin it is licensed as GPL v2. Embedding GPL v2 javascript in your application is commonly accepted to mean **you must open source your entire website**. – Chris Marisic Aug 07 '14 at 18:43
0

This code will let you have a variable number of rows (with a variable number of DIVs on each row) and it will make all of the DIVs on each row match the height of its tallest neighbour:

If we assumed all the DIVs, that are floating, are inside a container with the id "divContainer", then you could use the following:

$(document).ready(function() {

var currentTallest = 0;
var currentRowStart = 0;
var rowDivs = new Array();

$('div#divContainer div').each(function(index) {

    if(currentRowStart != $(this).position().top) {

        // we just came to a new row.  Set all the heights on the completed row
        for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) rowDivs[currentDiv].height(currentTallest);

        // set the variables for the new row
        rowDivs.length = 0; // empty the array
        currentRowStart = $(this).position().top;
        currentTallest = $(this).height();
        rowDivs.push($(this));

    } else {

        // another div on the current row.  Add it to the list and check if it's taller
        rowDivs.push($(this));
        currentTallest = (currentTallest < $(this).height()) ? ($(this).height()) : (currentTallest);

    }
    // do the last row
    for(currentDiv = 0 ; currentDiv < rowDivs.length ; currentDiv++) rowDivs[currentDiv].height(currentTallest);

});
});
HardlyNoticeable
  • 497
  • 9
  • 26
0

I recommend you wrap them both in an outer div with the desired background color.

chaos
  • 122,029
  • 33
  • 303
  • 309