CSS based design is really a powerful approach for most Web developers who consciously keep a website's contents separated from their visual presentation, which improves the site's overall maintenance and flexibility. Without a doubt, these virtues have provided designers with new possibilities for styling and positioning elements within Web documents very easily.
While tables still remain, for good compatibility reasons, the most used technique to define the layout of Web pages, <div> elements have gained considerable territory because they efficiently perform the same task. However, div-based layout exposes some undesirable artifacts when it is applied. Certainly, one of the most common pitfalls encountered when building up a two or more column liquid layout is the inability to give each general <div> containers the same height. It is desirable to achieve a consistent look, but also difficult, because of the dynamic nature of contents to be included in general <div> containers. Due to this issue, many websites present layout columns with uneven heights, which looks very inconsistent to the eyes of visitors.
However, we can do much more to solve this problem. Over the course of this article, I'll show you a simple but powerful approach to match heights for general layout divs, thus eliminating that ugly effect that makes some sites appear quite unprofessional. Using CSS and JavaScript, we'll find a nice solution without feeling a sense of doom. So, it's time to move on and tame those wild divs!
The kingdom of non-matching heights
Say we've set up a generic three-column layout for Web pages, which suits our needs for displaying some dynamic content. We might start writing the code for doing that, defining the basic CSS styles and markup, respectively:
<html>
<head>
<title>THREE-COLUMN LAYOUT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
body {
margin: 0;
}
#leftcol {
background: #ccf;
float: left;
width: 17%;
}
#content {
width: 65%;
float: left;
background: #ccf;
}
#rightcol {
float: right;
width: 17%;
background: #ccf;
}
</style>
</head>
<body>
<div id="leftcol">
Left Section<br />
Content goes here...
</div>
<div id="rightcol">
Right Section<br />
Content goes here...
</div>
<div id="content">
Content Section<br />
Content goes here...
</div>
</body>
</html>
As we can see in the above example, a simple three-column layout has been defined using the "float" property to properly position each container <div> element in the document. Following the document structure, the "leftcol" <div> element is floated to the left side, the "rightcol" <div> is similarly floated to the right side, and finally, in a similar fashion, the "content" <div> has been floated to the left, sticking to the "leftcol" <div> element, being displayed nearly the center of the screen. Also, widths for each element have been defined by percentages. It's simple enough and effective to use in liquid designs.
Although we've used floating boxes to achieve the general page layout, other techniques are perfectly valid, such as using absolute positioning and margin specifications. At this point, we have a good three-column design in which each column has the same height. Of course, this case is not a real representation of most Web pages out there. What if we start adding more content to, for example, the left positioned column and a little more to the content <div>? We might see something similar to the code shown below, derived from the initial example:
<html>
<head>
<title>THREE-COLUMN LAYOUT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
body {
margin: 0px;
}
#leftcol {
background: #ccf;
float: left;
width: 17%;
}
#content {
width: 65%;
float: left;
background: #ccf;
}
#rightcol {
float: right;
width: 17%;
background: #ccf;
}
</style>
</head>
<body>
<div id="leftcol">
Left Section<br /><br />
Content goes here...<br />
Content goes here...<br />
Content goes here...
</div>
<div id="rightcol">
Right Section<br /><br />
Content goes here...
</div>
<div id="content">
Content Section<br /><br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...
</div>
</body>
</html>
This spoils the party! As we can appreciate, heights for each <div> element won't be the same and columns will be unequally displayed. We might end up with a visual output like this:
Certainly, this is not what we want for our rendered Web pages, right? Those <div> elements are causing big headaches, and making our pages look pretty unprofessional. What's more, other possible variations to the example might be feasibly implemented. Let's see them in turn, in order to illustrate each of them.
More non-matching heights just around the corner
Based on the previous examples, suppose we need to add more content to the left column of the Web document, while the content <div> maintains its original height. This simple code will do the trick:
<html>
<head>
<title>THREE-COLUMN LAYOUT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
body {
margin: 0px;
}
#leftcol {
background: #ccf;
float: left;
width: 17%;
}
#content {
width: 65%;
float: left;
background: #ccf;
}
#rightcol {
float: right;
width: 17%;
background: #ccf;
}
</style>
</head>
<body>
<div id="leftcol">
Left Section<br /><br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...
</div>
<div id="rightcol">
Right Section<br /><br />
Content goes here...
</div>
<div id="content">
Content Section<br /><br />
Content goes here...<br />
Content goes here...
</div>
</body>
</html>
Once again, unfortunately, <div> elements will be unequally displayed in the document, resulting in the following undesirable visual output:
The last remaining case to be analyzed, which certainly would render non-matching <div> heights for the Web document's columns, will occur when additional content is included in the right column. This situation might be represented with the following code, based on the previous examples:
<html>
<head>
<title>THREE-COLUMN LAYOUT</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<style type="text/css">
body {
margin: 0px;
}
#leftcol {
background: #ccf;
float: left;
width: 17%;
}
#content {
width: 65%;
float: left;
background: #ccf;
}
#rightcol {
float: right;
width: 17%;
background: #ccf;
}
</style>
</head>
<body>
<div id="leftcol">
Left Section<br /><br />
Content goes here...<br />
Content goes here...
</div>
<div id="rightcol">
Right Section<br /><br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...
</div>
<div id="content">
Content Section<br /><br />
Content goes here...
</div>
</body>
</html>
As we've done with the above samples, the visual output for this code is illustrated below:
Consciously, we've taken a detailed look at the most common cases where the columns and content sections are displayed with different heights, according to the content that each element should contain. Indeed, the problem must be quickly tackled, preventing its ugly side effects, when we're utilizing <div> elements for page layout. So, how can we make column heights match properly, showing a very polished and consistent look, independently from the content generated? Fortunately, the answer is quite simple: a JavaScript function that will set <div> heights to the same value, achieving the desired matching height. Now, let's take a look at the JavaScript code.
The JavaScript solution
Since originally we defined three columns for page layout, the solution will be developed while sticking to the initial example. However, due to the portability of JavaScript code, it is perfectly applicable to any number of columns which we want to be efficiently matched. Our CSS code closely matches the previous examples, and is listed here:
<style type="text/css">
body {
margin: 0px;
}
#leftcol {
float: left;
width: 17%;
}
#content {
width: 65%;
float: left;
}
#rightcol {
float: right;
width: 17%;
}
.container {
background: #ccf;
border: 1px solid #000;
}
</style>
As you can see, we've defined the three <div> main columns originally presented, and an additional "container" class that will be used to hook up a style for each column, if we really wish to do it. In the example, I've chosen to give a background color and borders. However, this is not mandatory at all. Also, the "container" class will provide us with an easy way to identify the columns to be targeted by the script within the markup.
The HTML markup is nearly identical to the previous examples. We just added the "container" class to each <div> element susceptible to being affected by the JavaScript function. Here's the code:
<div id="leftcol" class="container">
Left Section<br /><br />
Content goes here...
</div>
<div id="rightcol" class="container">
Right Section<br /><br />
Content goes here...
</div>
<div id="content" class="container">
Content Section<br /><br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...<br />
Content goes here...
</div>
Nothing unexpected, is it? Finally, we list the JavaScript code, necessary to perform column height matching. It is as follows:
<script language="javascript">
matchHeight=function(){
var divs,contDivs,maxHeight,divHeight,d;
// get all <div> elements in the document
divs=document.getElementsByTagName('div');
contDivs=[];
// initialize maximum height value
maxHeight=0;
// iterate over all <div> elements in the document
for(var i=0;i<divs.length;i++){
// make collection with <div> elements with class attribute 'container'
if(/\bcontainer\b/.test(divs[i].className)){
d=divs[i];
contDivs[contDivs.length]=d;
// determine height for <div> element
if(d.offsetHeight){
divHeight=d.offsetHeight;
}
else if(d.style.pixelHeight){
divHeight=d.style.pixelHeight;
}
// calculate maximum height
maxHeight=Math.max(maxHeight,divHeight);
}
}
// assign maximum height value to all of container <div> elements
for(var i=0;i<contDivs.length;i++){
contDivs[i].style.height=maxHeight;
}
}
// execute function when page loads
window.onload=function(){
if(document.getElementsByTagName){
matchHeight();
}
}
</script>
As we usually do, let's break down the code to give a detailed explanation about each section of it:
At first, the function obtains the <div> elements present in the document. The line
divs=document.getElementsByTagName('div');
takes care of that.
Then, the script initializes the array structure for storing all of the <div> elements with class attribute set to "container," followed by the initialization of the variable "maxHeight," which will store the maximum height value found for the divs targeted. Next, the function traverses all of the <div> elements and checks for those with class attribute set to "container." These elements are stored in the array "contDivs" for further processing. The lines below perform that task:
if(/\bcontainer\b/.test(divs[i].className)){
d=divs[i];
contDivs[contDivs.length]=d;
---
}
Now, let's explain the key section of the script. For each targeted <div> element, we need to calculate its height, in order to determine which <div> has the greatest height value. To do that, we're using alternatively the offsetHeight and pixelHeight properties in order to determine the height value expressed in pixels for an element. This snippet performs the above mentioned process:
if(d.offsetHeight){
divHeight=d.offsetHeight;
}
else if(d.style.pixelHeight){
divHeight=d.style.pixelHeight;
}
Finally, the code determines the greatest <div> height of all of the elements analyzed, with the following expression:
maxHeight=Math.max(maxHeight,divHeight);
Once the function has determined the greatest height value of all the <div> elements, the only thing left to do is assign that value to each container <div> height, performing the needed matching for <div> height values. The last thing to do is wrap the whole code into a JavaScript function that will be executed when the page finishes loading. After the execution of the script, the visual output for the example might look similar to this:
Definitively, that looks a lot better than the previous cases, don't you agree? We've implemented height matching with the columns present in the Web page. That's pretty good!
Summary
In this article we've shown the specific problem of non-matching heights when working with <div> based layout, and hopefully demonstrated a very simple and portable solution. One worthy suggestion about this approach is that if we have a footer section in the page, as is commonly present on most websites, it'd be convenient to initially hide it from view, and once the height matching process have been completed with columns, turn it visible again. After all, those divs are not so wild as they seem to be!
By Alejandro Gervasio
Source: devarticles.com
