Need a Fluid-Height Sidebar - Same Height as Container

I need a sidebar to stretch down as much as its container div does. I haven’t set a height for the container because I want it to be as tall as whatever content goes in it. I wanted the sidebar to be height:100% but since I haven’t set the container height, it’s still on ‘auto’, so that doesn’t work.

How do you get a sidebar height to be 100% of its container, while keeping the container fluid?

(Sorry I can’t post markup and css to explain what I mean yet, I will soon if needed… but I’ll have to make a whole new example page for that + I’m a bit busy right now. )

Generally the best way to achieve this is to “fake” it, this is only possible if the side bar has some form of background or border. You apply a background image to the wrapping div or a div that contains both the content and the side bar and set it to show only where the side bar will be, this will then stretch the height of the container regardless of how tall the side bar is.

An alternative that I would avoid is using Javascript to get the exact height of the container and then set the side bar to that height.

You can do it quite easily like this if you don’t mind one extra non semantic div.


<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
h1,h2{margin:.53m 0 1em;text-align:center;}
p { margin:0 0 1em }
.wrap:after {
	content:".";
	display:block;
	height:0;
	clear:both;
	visibility:hidden;
}
.wrap {
	width:70%;
	min-width:800px;
	margin:50px auto;
	position:relative;
	border:1px solid #000;
	background:#fcf;
}
.sidebar {
	float:left;
	width:180px;
	padding:10px;
	margin:0 20px 0 0;
	position:relative;
	z-index:2;
}
.main {
	overflow:hidden;
	zoom:1.0;
}
.abs {/* empty element to provide background color*/
	position:absolute;
	left:0;
	top:0;
	bottom:0;
	width:200px;
	border-right:10px solid #fff;
	background:#f00;
	color:#fff;
	z-index:0;
}
* html .wrap { overflow:hidden; }
* html .abs {
	bottom:0;
	height:999em;
}
</style>
</head>

<body>
<h1>Equal column test</h1>
<div class="wrap">
		<div class="sidebar">
				<p>Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: </p>
		</div>
		<div class="main">
				<h2>Testing</h2>
		</div>
		<div class="abs"></div>
</div>
<div class="wrap">
		<div class="sidebar">
				<p>Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: Sidebar content goes here: </p>
		</div>
		<div class="main">
				<h2>Testing</h2>
				<p>Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :Main content goes here :</p>
		</div>
		<div class="abs"></div>
</div>
</body>
</html>


That will work back to ie6 (and ie5 if you want to do the box model hacks). It uses my absolute overlay technique and overlays the background on the wrapper using absolute positioning because absolute elements can keep track of a relative height container unlike static elements. It doesn’t matter that the element is absolute because it holds no content and just provides the background under the normal floated column. The rest of the layout is exactly the same as normal and its just the extra div that provides the colour.

If you only want IE8+ support then use the display:table and table-cell properties for the equal columns.

The background image approach mentioned in the post above is also a good and easy method if you don’t mind using images for the effect.

  1. Faux colum bg, as Nutty mentioned, are REALLY easy to do, and offer great support… if your site is simple and static that might be the most easily understood technique.

  2. Paul, as always, that’s a brilliant solution. You could clean up the markup further: the .abs div can even be removed and pseudo elements (.wrap:before) used instead. Since the element is AP’ed and empty it really doesn’t matter whether it’s (generated) at the top of the source or the bottom. ( At least if only one column is needed)

.wrap:before {/* empty element to provide background color*/
	position:absolute;
	left:0;
	top:0;
	bottom:0;
	width:200px;
	border-right:10px solid #fff;
	background:#f00;
	color:#fff;
	z-index:0;
}

/* we can add further IE support*/

.wrap{	zoom:expression(
		runtimeStyle.zoom=1,
		insertAdjacentHTML('beforeEnd','<span class="after"></span>')
	);	

  zoom:expression(
		runtimeStyle.zoom=1,
		insertAdjacentHTML('afterBegin','<span class="before"></span>')
	);
}

  1. But there is also the camp that shies away from AP or is reserving it for something else. The following method works great,no empty tags, and can be expanded to any number of columns. Tho, you have to be able to WRAP (pun) you head around how the shells hold images… for two or 3 columns… it’s still pretty simple.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Untitled Document</title>
<style type="text/css">
h1,h2{margin:.53m 0 1em;text-align:center;}
p { margin:0 0 1em }
.wrap {
	width:70%;
	min-width:800px;
	margin:50px auto;
	border:1px solid #000;
	background:#fcf;
}
.sidebar {
	float:left;
	width:180px;
	padding:10px;
	margin:0 20px 0 -210px;
}
.main {
	overflow:hidden;
	padding:0 10px;
	zoom:1.0;
}
.inner {/* main area color*/
	margin-left:200px;
	border-left:10px solid #fff;
	background:pink;
	color:#fff;
}
.inner:after {content:""; visibility: hidden; height:0; display:block; clear: both}
* html .wrap .inner{ overflow:hidden; }
</style>
</head>

<body>
<h1>Equal column test</h1>
<div class="wrap"><div class='inner'>
		<div class="sidebar">
				<h2>Test Sidebar</h2>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
		</div>
		<div class="main">
				<h2>Testing Main</h2>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
		</div>
</div></div>

<h1>Equal column test</h1>
<div class="wrap"><div class='inner'>
		<div class="sidebar">
				<h2>Test Sidebar</h2>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
		</div>
		<div class="main">
				<h2>Testing Main</h2>
				<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
		</div>
</div></div>

Faux columns, ey? Ok, I’ll give those a go. Thanks guys.

In the meantime I’ve just manually extended the height to far more than I needed.

What if user resizes the text Fretman?

Can they still do that? I thought it was all zooming these days.

IIRC I know AT LEAST FF still has it.

CTRL+ I believe? Or View>Zoom>Zoom Text Only

I think Ctrl + by default has just zoomed for the last few versions of ff. I see that choosing ‘zoom text only’ does create problems. That’s why I’ll be trying out the faux column method, is that immune to it? Right now, nothing’s online though so no immediate panic.

Just in theory, if you convert all your px values to em’s will that sort that problem out WITHOUT creating new problems?

Yes the Faux column will be “immune” to it so to speak. The height won’t be restricted.

It depends. Ems will make it so font sizes never escape the boundaries, but it could also throw the entire page out of wack.

@people, thre is an article that’s something like “Fixed vs Fluid vs Elastic”. If someone knows what I’m talking about could you post it? I thought it was on alistapart but I’m not seeing it.

What’s wrong with the solutions already offered?

They won’t suffer from any re-size problems or are you looking for multiple columns? You said you just wanted a full height sidebar and the code we have given above does that very easily.

As a rule of thumb you never want to give heights to containers that hold text. You can as you say size the containers in ems and assuming that the font size of the parent is the same as the text content then they will scale together but that still doesn’t solve the problem as you have to guess the height. Browsers also render text to different line lengths and will seldom wrap at the same place so the height will vary between browsers. Even if you get that working it means you can never change or update or insert dynamic content into the page without changing the height every time. It’s usually the first mistake that beginners make where they try to size everything like a drawing but web pages are living breathing things :slight_smile:

Oh nothing, I just meant that in the meantime (before reading the solutions) I had done that (extended the height in px). I’ll update again when I’ve tried it out.

Thanks, I’ll remember that.

I wonder if it’s a general consensus here that the latest Sitepoint book “build your own website the right way” wrongly led people to think too far into the future. Again and again I’m finding that the presumptions and methods recommended in that book (excellent though I still think it is) were jumping the gun a little… css3 & html 5 that is still not widely recommended, they led me to believe that text-resizing was going out of fashion (and this coming from a book that’s a year old led me to place extra confidence in that).

I haven’t read the book yet so I can’t c omment, but I’d still use CSS3 where possible (HTML 5 I’d hold off on just because theres really no need for me to use it yet (personally)).

You can still give newer browsers who support it, CSS3, but the older browsers will just have to suffer. You can’t get it 100% the same across every browser with the same code. I wouldn’t say they led people on with those two things.

Not many people purely text resize, as many just zoom. But still, people can still do it if they wish.

Good coding/designinbg will remove any need to worry about these issues though…:slight_smile:

I can read some advice saying using fixed-widths in px is fine or preferable… then others saying always use fluid Em’s or percentages. What do I do? Which is “good design”?

I have to presume, Paul, your advice was about containers with text directly inside them… because - thinking about it - most pages use containers for some huge chunk of the entire body, don’t they? Or was that advice more radical than I thought, i.e. almost never set heights at all?

It’s really up to you and how you want your page to appear. Certain things I do PX, although I do a majority in %s. I just like using them more. I can’t speak for anyone else though.

You should almost never set heights. Most places you would set a height has content in it, and you should almost never set a height due to it possibly overflowing.

Now, if you, for some reason, had an empty <div> to hold a BG image, of course you’d need to set a height there to make the BG image show.

There are a few places to set heights, but this is not a case :).

There is no one real answer to the question but IE can’t scale text set in pixels although IE8+ has zoom but that’s not the same thing which is why its generally always been bad to use px. The main reason for not using px is that you don’t create a relationship between the elements on your page unlike ems. If your page is using ems then the page will scale nicely and all things grow or shrink proportionately. Jason (deathshadow) had a good post on here about font-sizing so do a search of his posts (or forum search) as the question comes up regularly.

I have to presume, Paul, your advice was about containers with text directly inside them… because - thinking about it - most pages use containers for some huge chunk of the entire body, don’t they? Or was that advice more radical than I thought, i.e. almost never set heights at all?

As Ryan said you more or less never set height on containers that have text inside them unless perhaps its one line only or a nav item and then you should set the height in ems and make sure the text doesn’t break out if resized.

If its a banner or a fixed height image then you can set a height. Or if you have a background that needs to show you may need a height. You can always use min-height anyway and that will allow the element to grow if text resized.

Ok, makes sense. Cheers. I’ll have to do a complete overhaul of my css today. I fear the layout is gonna go nuts.

At least it’s just a case of a new stylesheet, the old one will be there waiting for me if I need it. :slight_smile:

Hi Fretman,

I have a solution here. Works in all modern browsers, including IE9 and IE8. IE 7 and 6 do not take it, though.

HTML:

<div id="wrapper">
   <div id="main_col" class="same_height_col">
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque bibendum gravida nibh,
             nec adipiscing ante pretium nec. Pellentesque suscipit magna nibh. In pulvinar dolor et massa
             ultricies adipiscing. Proin aliquam odio in ligula pellentesque quis semper tortor fermentum.
             Duis libero metus, tempus porta rutrum non, pulvinar in libero. Praesent nec eleifend augue.
             Aenean laoreet malesuada interdum. Morbi quis metus id velit suscipit sagittis vitae vel libero.
             Aliquam erat volutpat. Maecenas et turpis sed justo fermentum vulputate a et dui. Aliquam erat
             volutpat. Pellentesque elementum iaculis suscipit. Duis pellentesque quam quis urna dapibus
             sodales. Mauris posuere, mi non faucibus ullamcorper, nulla orci luctus ipsum, id sollicitudin
             sapien est sit amet mauris.</p>
   </div>
   <div id="sidebar_col" class="same_height_col">
      <p>Maecenas nibh eros, feugiat ac varius vel, sodales eu augue. Mauris quis orci ac tortor feugiat
             fringilla. Donec ac justo in mauris hendrerit pellentesque in at orci.</p>
   </div>
</div>

CSS:

#wrapper {
   width: 720px;  /* this is just arbitrary, to avoid making the whole thing fill up the entire screen */
   overflow: visible;
   display: table;
   table-layout: fixed;
   border: 1px solid #666; /* to make the height of the container div visible */
   }
	
#main_col {
   width: 65%;
   background-color: #8CE; /* this makes the column height visible */
   }

#sidebar_col {
   width: 30%;
   background-color: #FDF; /* this makes the column height visible */
   }
	
#wrapper .same_height_col {
   display: table-cell;
   overflow: hidden;
   vertical-align: top;
}

Cheers