(OLDER) <- More Stuff -> (NEWER) (NEWEST)
Printer Friendly Version



Equal height CSS columns with filler text


2007/12/02

If you search for "column alignment" or "css columns", you'll probably eventually end up at In search of the One True Layout at positioniseverything.net. That's great stuff, but it is not what I wanted.

I want to fill the left hand column with text so that it matches the height (the page length) of the main text in the right hand column. I can't always do that - for one thing, I may not have enough filler text, because the text I want is links to related content (that is, other articles related to the content in the main text). Also, there's a certain amount of content I want on the left hand side no matter how short the right hand side is. So I can't always be perfect, but I can get everything aligned most of the time.



The problem, of course, is knowing when to stop writing text in the left column. At some point, the length of that column will exceed the text already displayed in the right column, and that produces an unattractive page. I could just write a few things in the left side, but that can leave lots of wasted space if the right hand side is long, and while that's not extremely ugly, it is unused space that I'd like to fill with content.

The problem with client side Javascript is that it can't read files on the webserver. You wouldn't want it to be able to, because it is running from the browser of the person reading your page and could be modified by them. Perl running on your server through a SSI (Server Side Include) of course can read files, so we'll use that to create Javascript code. If that confuses you, you probably just need to play with this to see it in action.

This is the Perl code that produces the Javascript that aligns the left column:

print <<EOF;
<script type="text/javascript">
function getht(h) {
 var x=0;
 while(h) {
   x += h.offsetTop;
   h= h.offsetParent;
  }
 return x;
}
 var nb =document.getElementById("nearbottom");
 var nbht=getht(nb);
 var cht=0;
 var leftside =document.getElementById("leftside");
 var leftheight=getht(leftside);
 var filler=new Array();
EOF
for ($x=0;$x < 50; $x++) {
print qq(filler[$x]=');
randompage();
print qq(';\n);
}
print <<EOF;
 for (var x=0; x < 50; x++) 
 {
if (nbht > leftheight ) {
   id='p' + x;
   var pfiller=document.createElement("p");
   pfiller.id=id;
   // use next line if you want to see the variables for debugging
   // pfiller.innerHTML=filler[x] + " " + leftheight + " " + nbht;
   pfiller.innerHTML=filler[x] + " ";
   leftside.appendChild(pfiller);
   leftheight=getht(document.getElementById(id));
}

 }
document.write('<br /></div>');
</script>
EOF
 

The "randompage()" is a subroutine that returns randomly sorted related pages - I'm not showing that here, but it should be easy to imagine what it does. If it has nothing more to return, it returns "<br />". After this runs, the page is going to contain something like this:

<script type="text/javascript">
function getht(h) {
 var x=0;
 while(h) {
   x += h.offsetTop;
   h= h.offsetParent;
  }
 return x;
}
 var nb =document.getElementById("nearbottom");
 var nbht=getht(nb);
 var cht=0;
 var leftside =document.getElementById("leftside");
 var leftheight=getht(leftside);
 var filler=new Array();
filler[0]='<a href="/Words2005/2005_07_30.html">Archiving All Email </a>';
filler[1]='<a href="/Security/fake_blacklists.html">Fake blacklists? </a>';
..
filler[48]='<a href="/Security/web-ip-filter.html">Web site IP filtering </a>';
filler[49]='<a href="/MDesrosiers/pci_dss.html">PCI DSS and ISO 17799 </a>';
 for (var x=0; x < 50; x++) 
 {
if (nbht > leftheight ) {
   id='p' + x;
   var pfiller=document.createElement("p");
   pfiller.id=id;
   // pfiller.innerHTML=filler[x] + " " + leftheight + " " + nbht;
   pfiller.innerHTML=filler[x] + " ";
   leftside.appendChild(pfiller);
   leftheight=getht(document.getElementById(id));
}

 }
document.write('<br /></div>');
</script>
 

What that does is fill an array of 50 items that can potentially be used to fill space. In the right side main text, the last paragraph is marked with an id tag: <p id="nearbottom>. The Javascript finds the position of the "nearbottom" paragraph to start with, and then starts creating new paragraphs filled with the text randompage() supplied. The code checks the position of each new paragraph, and stops writing them once that position reaches that of "nearbottom".

Of course the filler material could be anything: pictures, random jokes, whatever: even more Javascript scripts (though that gets really hard because of quoting).

cartoon

Keep in mind that I am no Javascript expert. I tested this on Firefox, Safari, Opera and Internet Explorer 7, but there may very well be places it will not work, and failure to work will either produce nothing at all or 50 lines of text no matter where "nearbottom" is. You do need to quote " ' "'s in your filler text returned by random() or whatever function you call.

If you are going to play with this, I strongly suggest using Firefox because of its built in Javascript console. That will let you see Javascript coding errors which are usually caused by quoting mistakes when you are producing the script from another program as we are here. Without that console, it can be really hard and very frustrating to find the most simple problems.

The only problem I have with this is that I can't use the W3C validator with this code. I don't understand why yet, but W3C seems to think that the "filler[0]=" lines are HTML that should be checked.. I haven't figured out why, but it's surely my mistake somewhere..


Technorati tags:








Click here to add your comments





Sun Dec 2 16:23:33 2007: Subject:   TonyLawrence

gravatar
So how about a reader challenge?

First person to figure out why W3C won't validate and provide a workaround gets $50 by Paypal. Fair enough?
Don't post your solution as a comment. Send it by email (see Contact Info on the menu links above).



Mon Dec 3 01:52:22 2007: Subject:   TonyLawrence

gravatar
Well, I've found a way around it:

Wrapping the Javascript in faux comments makes W3C happy..

<!-- this shouldn't be necessary
EOF
for ($x=0;$x < 100; $x++) {
print qq(filler[$x]=');
randompage();
print qq(';\n);
}
print <<EOF;
// -->

etc..

Wouldn't have thought I needed to do that.



Mon Dec 3 11:50:43 2007: Subject:   TonyLawrence

gravatar
And then finally I realized that this doesn't need to be dynamic for my use: the only time the filler content changes is when I add new content, so I can regenerate scripts at that time. For example, this page now calls "Web.js" . That unconfuses W3C .

I added random pictures and scrambled the links; you can see the current version by getting aplawrence.com/Web.js in your browser (well, Firefox, anyway).



Mon Dec 3 16:32:49 2007: Subject:   Niall


If you ever switch to XHTML:

<script type="text/javascript">
/* <![CDATA[ */
... javascript ...
/* ]]> */
</script>





Mon Dec 3 18:13:17 2007: Subject:   TonyLawrence

gravatar
It is XHTML now.. good idea, I forgot about that!



Thu Dec 6 21:54:55 2007: Subject: YUI Grids!   MikeHostetler


I'm a huge fan of YUI grids -- it's CSS-based, properly tested on all name-brand browsers, and well-documented and supported. Heck, you don't even had to host the files yourself!

http://developer.yahoo.com/yui/grids/




Thu Dec 6 21:58:52 2007: Subject:   TonyLawrence

gravatar
I certainly agree (if you look at "View Source" you'll see I use them here), but how could they help with this??




Don't miss responses! Subscribe to Comments by RSS or by Email

Click here to add your comments


If you want a picture to show with your comment, go get a Gravatar



Have you tried Searching this site?

Unix/Linux/Mac OS X support by phone, email or on-site: Support Rates

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more. We appreciate comments and article submissions.

Publishing your articles here

Jump to Comments



Many of the products and books I review are things I purchased for my own use. Some were given to me specifically for the purpose of reviewing them. I resell or can earn commissions from the sale of some of these items. Links within these pages may be affiliate links that pay me for referring you to them. That's mostly insignificant amounts of money; whenever it is not I have made my relationship plain. I also may own stock in companies mentioned here. If you have any question, please do feel free to contact me.

Specific links that take you to pages that allow you to purchase the item I reviewed are very likely to pay me a commission. Many of the books I review were given to me by the publishers specifically for the purpose of writing a review. These gifts and referral fees do not affect my opinions; I often give bad reviews anyway.

We use Google third-party advertising companies to serve ads when you visit our website. These companies may use information (not including your name, address, email address, or telephone number) about your visits to this and other websites in order to provide advertisements about goods and services of interest to you. If you would like more information about this practice and to know your choices about not having this information used by these companies, click here.

book graphic Internet Income guide

My Hard Truths about Easy Money on the Internet will show you how to make money on the Internet!

 I sell and support
 Kerio Mail server




pavatar.jpg
More:
       - Blogging
       - Web/HTML
       - Perl
       - Javascript
       - Programming
       - Code


Unix/Linux Consultants

Skills Tests

Guest Post Here








card_image






My Favorites

Change Congress