Div doesn't expand to fill relevant part of wrapper div

I am having difficulty getting around the following problem. I have 3 divs - a wrapper, a left bar, and a right bar. The html looks like this:

<div id="overallwrapper">

	<div id="leftbar">
		<p>content left</p>
	</div>

	<div id="rightbar">
		<p>content right</p>
	</div>

</div>

The CSS looks like this:


#overallwrapper {
border: solid;
border-color: black;
width: 960;
margin-left: auto; 
margin-right: auto;
overflow: auto;
}

#leftbar {
float: left;
width: 30%;
background-color: blue;
}

#rightbar {
float: right;
width: 70%;
background-color: green;
}

If I cause one of the divs to expand by putting content in it, the other div doesn’t expand with it, apparently; the background color remains in place, only covering that particular div’s text (filler content). If I expand the rightbar div, the leftbar div remains the same size, unless I add an equivalent amount of text or content to it. I want both divs to expand to be the size of its sibling div, so if I have a bunch of text in the rightbar or leftbar, either would grow to to be a solid color as long as the other div.

How can I cause one div to match the size of the other? (This is a basic two column layout, or so I thought.)
(If you do load my code, you will have to add your own filler content to see the problem)

There’s a couple of ways you can set the column heights to be the same in both columns.

Either pure CSS, and the trade off is slightly more complicated HTML markup and css code (Paul O’B is an expert on that) or you can use javascript, in which case your current html markup is all you need.

If you go the javascript route, all you need to do is on page load get the rendered column heights of each column (leftbar and rightbar) and then set each column height to the rendered height of the tallest column.

The only downside to using the javascript option is that in javascript disabled browsers, although all the content and styling will still be visible, the column heights might not be equal. If equal column heights is not a “must have” then using the easier javascript option is not an issue.

The easiest and most common method is to use “faux columns”, meaning a repeating background image on the wrapper that fakes the appearance of columns. Very easy, and the most efficient solution.

Whether it is the most common method or not I have no idea, but I disagree it is the easiest. I guess what is “easy” is largely subjective.

Unless equal height columns is a “must have” in 100% of cases I will always use javascript and so avoid mucking around with tiling bg images to fake the appearance of columns. The js is fairly minimal and straight forward and imo more efficient.

I can’t think of anything easier than a simple repeating bg image, and it works in more scenarios (as it doesn’t depend on JS).

Anyhow, the OP should be aware that the line in red needs a value, such as px:

#overallwrapper {
border: solid;
border-color: black;
[COLOR="#FF0000"]width: 960;[/COLOR]
margin-left: auto; 
margin-right: auto;
overflow: auto;
}

width: 960 has no meaning. It needs to be width: 960px;

EDIT: also, the border needs a width. So try something like:

border: 2px solid black;

and remove the other border statements.

I have a prewritten 6 line js function that sets the column heights to the height of the tallest column. I just copy and paste it to the website’s js file and I then just call it when I need it. Can’t be simpler for me.

Unless necessary, I don’t want to muck around with bg images whose sole purpose is to fake the appearance of columns.

Admittedly, I am trying to move away from images as much as possible, so it’s certainly a viable option—especially as it doesn’t really matter much if the columns don’t show up with js off (as long as text color etc. is accounted for). Any chance you’d be willing tho share that code? I hate using jQeury for something so simple.

With js off in the browser, the columns’ content and styles (borders, bg colours etc) will still show up. It’s just that the column heights will not be equal if js is turned off.

This is a demo of using js to set equal column heights. You can have as many columns as you like without having to touch the js.


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
    <head> 
        <title></title> 
        <style type="text/css"> 

            ul { 
                margin: 0px 0px 0px 0px;
                padding: 0px 0px 0px 0px;
                list-style-type: none}

            #container { 
                border: 1px solid red; 
                width: 800px;
                overflow: hidden; 
                margin: 0px auto 0px auto;
                padding: 20px 20px 20px 20px} 
            /* sidebar's and content's padding values must be the same */
            #sidebar { 
                margin: 0px 0px 0px 0px;
                padding: 10px 10px 10px 10px;
                border: 1px solid green; 
                float: left; 
                width: 250px} 

            #content { 
                margin: 0px 0px 10px 0px;
                padding: 10px 10px 10px 10px;
                border: 1px solid blue; 
                float: right; 
                width: 490px} 

            #content div {
                margin: 0px 0px 0px 0px;
                padding: 0px 0px 70px 0px;
            }

        </style> 
        <script type="text/javascript"> 
            window.onload=function() {
                var maxHeight = 0;
                var colsA = document.getElementById("container").childNodes;
                for(var i=0; i < colsA.length; i=i+1) {
                    if(colsA[i].clientHeight > maxHeight) maxHeight = colsA[i].clientHeight;
                }
                for(var i=0; i < colsA.length; i=i+1) {
                    if(colsA[i].nodeType == 1) colsA[i].style.height = maxHeight+'px';
                }   
            } 
        </script> 
    </head> 
    <body> 
        <div id="container"> 
            <div id="sidebar"> 
                <ul id="menu_list">
                    <li>Menu item 1</li>
                    <li>Menu item 2</li>
                    <li>Menu item 3</li>
                    <li>Menu item 4</li>
                </ul>
            </div>  
            <div id="content"> 
                <div>
                    Lorem ipsum dolor sit amet, tellus et. Molestie auctor nisl faucibus ut, lorem tortor mattis, fusce nullam enim fringilla vel. 
                    Mauris vitae gravida dolor praesent. Id in nascetur aut odio, nam et. Pede libero bibendum sit felis pretium sodales, fusce 
                    pharetra vestibulum bibendum morbi ultricies nullam, est nulla, id amet mollis. Nec consectetuer urna dapibus luctus ut, 
                    ipsum nascetur consequat dapibus dui ac molestie, est nascetur id nec nunc. Mi etiam mauris facilisi sed, nec ut id, 
                    aliquam non, taciti donec ut. Risus integer hymenaeos velit, nisl suspendisse sollicitudin ut, sed tempor sagittis curae dolor, 
                    volutpat massa ut sagittis. Voluptatem a enim, lobortis lectus volutpat, vitae vero diam purus morbi class, tristique donec 
                    ante sed, ac turpis dis dui vestibulum aut.
                </div>
            </div> 
        </div> 
    </body> 
</html>

Duh, yes, silly comment on my part.

You can have as many columns as you like without having to touch the js.

Nice example. Thanks for posting it. I’m finally forcing myself to start to learn JS, so I look forward to studying this code. :slight_smile:

Yes that’s a neat little script and thanks for sharing :slight_smile:

Not to be picky but I do have a couple of issues with it.:slight_smile:

What happens when the user resizes the text? The layout is fixed to the pixel height you set so it won’t grow and the text will overlap. The same issue would be apparent for fluid columns and should the window be resized then the columns won’t grow and the content will spill out.

You would therefore need to add some onresize rules to cater for this but then you end up with a sluggish screen and one that appears to jump into position at each window change. As soon as you start digging into the detail it becomes less simple that the demo above for a real world application.

It’s probably fine for the odd few elements but a page really needs to resize with the text or change with the window size.

Of course you could limit the problem by giving the routine to just ie7 and under and let others use display:table instead.

e.g. Exactly the same html as yours:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
<style type="text/css">
ul {
	margin: 0;
	padding: 0;
	list-style-type: none
}
#container {
	border: 1px solid red;
	width: 800px;
	overflow: hidden;
	margin: 0 auto;
	display:table;
	border-spacing:20px;
}
/* sidebar's and content's padding values must be the same */
#sidebar {
	margin:0;
	padding: 10px;
	border: 1px solid green;
	width: 250px;
	display:table-cell;
	vertical-align:top;
}
#content {
	margin:0 0 10px 0;
	padding: 10px;
	border: 1px solid blue;
	width: 490px;
	display:table-cell;
	vertical-align:top;
}
</style>
<!--[if lt IE 8]>
<style type="text/css">
#container {padding: 20px}
#sidebar{float:left}
#content{float:right}
</style>
<![endif]-->

</head>
<body>
<div id="container">
		<div id="sidebar">
				<ul id="menu_list">
						<li>Menu item 1</li>
						<li>Menu item 2</li>
						<li>Menu item 3</li>
						<li>Menu item 4</li>
				</ul>
		</div>
		<div id="content">
				<div> Lorem ipsum dolor sit amet, tellus et. Molestie auctor nisl faucibus ut, lorem tortor mattis, fusce nullam enim fringilla vel. 
						Mauris vitae gravida dolor praesent. Id in nascetur aut odio, nam et. Pede libero bibendum sit felis pretium sodales, fusce 
						pharetra vestibulum bibendum morbi ultricies nullam, est nulla, id amet mollis. Nec consectetuer urna dapibus luctus ut, 
						ipsum nascetur consequat dapibus dui ac molestie, est nascetur id nec nunc. Mi etiam mauris facilisi sed, nec ut id, 
						aliquam non, taciti donec ut. Risus integer hymenaeos velit, nisl suspendisse sollicitudin ut, sed tempor sagittis curae dolor, 
						volutpat massa ut sagittis. Voluptatem a enim, lobortis lectus volutpat, vitae vero diam purus morbi class, tristique donec 
						ante sed, ac turpis dis dui vestibulum aut. </div>
		</div>
</div>
<!--[if lt IE 8]>
        <script type="text/javascript"> 
            window.onload=function() {
                var maxHeight = 0;
                var colsA = document.getElementById("container").childNodes;
                for(var i=0; i < colsA.length; i=i+1) {
                    if(colsA[i].clientHeight > maxHeight) maxHeight = colsA[i].clientHeight;
                }
                for(var i=0; i < colsA.length; i=i+1) {
                    if(colsA[i].nodeType == 1) colsA[i].style.height = maxHeight+'px';
                }   
            } 
        </script>
<![endif]-->
</body>
</html>

I’m sure you could update your script to size in ems instead and cater for resize and that would go some way to address the issues I mentioned but then it no longer becomes a simple fix.

There are other css methods that will work back to ie6 for multiple equal columns but they aren’t really simple either and have the downside that the html needs to be altered. Here’s an old demo showing the technique in action.

The “faux column” approach as already mentioned is pretty easy to implement and doesn’t usually add to the html but of course doesn’t allow you to change the design easily and gets complicated if you want separate or fluid columns.

In the end it’s a matter of choice (unless you don’t need to support older browsers) as there are pros and cons to each method.:slight_smile:

Think again :slight_smile:

There is no reason why an unrelated column in css should automatically resize with a neighbour (although css3 does have the tools for this with the flexible box layout and also the aforementioned display:table properties (ie8+)).

You make some valid points and like you say, there are pros and cons to both methods.

The css in the demo is just quick and simple to facilitate how you can use js to set equal column heights. The css is not the main purpose of the demo - the js is. If anyone wants to use the js they can then also tweak the css to suit their website.

That was a longer discussion than I anticipated! Thanks for the many workarounds presented. I apologize about the errors in the code sample; I actually re-did it from scratch based a more complex layout I am working on for the sake of commentators here.

Can you suggest the best method for ie8+? I do not have to support browsers older than this, for the most part. (I do prefer to work with CSS over JS, although if JS gets the job done better, I have no problem there.)

Another question about the faux column method. I may not understand it correctly, but would the column width have to match the width of your image? Or could you use something small, like 1px image, in order to achieve the same effect (while still maintaining a column’s css-defined width)?

In that case, use Paul’s display:table; example in post #10.

Another question about the faux column method. I may not understand it correctly, but would the column width have to match the width of your image?

Basicall yes. You pretty much need to work with a fixed-width layout when using a bg image like that. You could use an image wider than the content area, more of which shows as the content area gets wider, but you’d have to be careful about the placement of the background image to ensure that the dividing line remained where you wanted it to. I’ve tried that before, but have seen it fail badly in some devices such as iPad, so wouldn’t use it again.

Thanks again.

I just tried display: table out with my code above but it did not appear to work. Tried in ie8 and ff7.

Here’s how I added it:


#leftbar {
float: left;
width: 30%;
background-color: blue;
display: table;
}


What am I doing wrong here? This is the div that represents the column that I want to extend all the way down the page.

You need to set the container to display: table and the columns to display:table-cell. Floats are not relevant in this kind of layout. Have a good look at Paul’s code above, as it shows how things tie together. Going the display: table route is a major design decision that affects all aspects of your layout, not just small parts of it. :slight_smile:

I am trying to use the display: table method now and have a few questions. I don’t see many people using this method - what are some concerns that I should have with it? (I realize it doesn’t work in IE7 or earlier.) Does it suit fluid layouts well and work well in mobile browsers? I am new to css layouts and the “big thing” people keep repeating in design articles (maybe old articles?) is to use floats for layout.

The main reason display: table has been so underused is because of its lack of support in IE, the major browser on the web. It’s hard to change that now. In a way, it’s not a terrible thing, as display: table is better used sparingly. For example, it’s not as flexible if you want to change your design around a bit, making it similar to using tables for layout. It’s best role is probably for isolated parts of a page rather than for a whole layout—except perhaps were there’s a need like yours.

In terms of its functioning on mobiles, I’d think it would be pretty good, but you’d need to do some tests. One thing that is popular these days is “responsive design”, which often involves the use of media queries. Often on wider screens you’ll see columns, but when the browser window narrows, or you view on a smartphone, you’ll see that everything has adjusted to one column. This is probably easier to do if you’ve used floats rather than display: table. (But I might have to think about that some more, as it’s not something I’ve really considered, I admit.)

As Ralph said you can use display:table for your equal columns and then for mobiles you could set up media queries to float the columns instead (or preferably vice versa - simple first and then enhanced for more capable devices).

However the real issue is you are letting your design dictate what the content looks like. If you force the content into places it doesn’t flow naturally then you make it harder all around. Equal columns aren’t all they are cracked up to be and sometimes a more logical and natural flow of the page is easier to manage for all devices and can look better. Getting the balance right is of course difficult as you don’t want just plain text but if you are creative it can be done well and more simply.