design and development for the web

An experiment with relative units

I had this great idea to test out relative units. What if you defined the body's font-size based off of the window's width (or height). So, now you've got a dynamic font-size setting for the body tag... big deal, right? Absolutely!

With a little DOM-Scripting, some creative CSS, and a little elbow grease, we can make a fully scalable page!

Do everything in relative units!

Set up your entire layout based off of the body's font-size. Those of you who understand the nature of Fluid Layouts will understand where I'm headed. My initial idea was to create a layout that would expand and contract with the window. This is generally called a fluid layout or a "liquid design". But, I didn't want to stop there. I wanted the entire page grow and shrink -- not just the layout.

A Proof of Concept

For those of you who are skimmers like me, this is where you stop reading and go directly to the proof of concept.


I first designed a simple 2 column layout for a 1024x768 display. I made sure to use "em" units for all dimensions (except border-widths, but I'll get to that fiasco in a minute.)

  2. #content_main { position: absolute; top: 1em; left: 1em; width: 37em; }
  3. #content_sub { position: absolute; top: 1em; left: 41em; width: 19em; }

The DOM Script...

The script deals with two event handlers: the initial window.onload, and the eventual window.onresize. Both event handlers send the current window size to the "change_font_size" function. From this point, all that is required is some basic math to deduct the new percentage based on the ratio of the original layout's font-size/window-size to the new font-size/window-size combination.

  2. var original_layout_size = 1024; // arbitrary
  3. var root_element = document.getElementsByTagName("html")[0];
  4. var original_window_size = root_element.clientWidth;
  5. var original_font_size =;
  6. function change_font_size(window_size) {
  7. var new_font_size = Math.floor(100 * window_size / original_layout_size);
  8. = new_font_size + "%";
  9. }
  11. window.onload = function () {
  12. if (original_window_size != original_layout_size) {
  13. change_font_size(original_window_size);
  14. }
  15. };
  17. window.onresize = function () {
  18. var new_window_size = root_element.clientWidth;
  19. change_font_size(new_window_size);
  20. };

Disclaimer: Keep in mind, this javascript is not portable in anyway. If i were to actually use this code for a practical purpose, I would definitely implement the logic in a more portable fashion.

The Markup

The xhtml for this example is very simple. The two content division tags must be at the same level within the DOM.

  2. ... the CSS and DOM-Script go here.
  3. </head>
  4. <div id='content_main'> some content would go nice in here </div>
  5. <div id='content_sub'> you can put some content here </div>
  6. </body>


I was surprised to find out that Firefox did not resize the window "on the fly". The browser waits for you to finish resizing the page before it triggers the onresize event. The only other way to trigger the event is to force a line to wrap differently, which forces the browser to redraw the entire page. But, because both onload and onresize perform the exact same task, further testing is required to determine whether the line-wrap "redraw" is actually triggering the onresize event.

IE6 performs the best? Really?

Believe it or not... the browser that has the smoothest refresh rate that I have personally tested has been my version of IE6 installed through Multiple-IE. I've heard that it also runs smoothly on Konqueror in Linux.

In fact, Internet Explorer (including IE7) has one crucial issue. The default user-agent styles are not defined relative to the body font-size as expected. The h1 through h6 tags do not resize at all when the body font size is changed.


Refresh rate aside, each browser has it's own little strange way of reacting to this flexible design. Border-widths defined by em's were a complete mess across all browsers. Horizontal borders would be of a certain thickness, while the vertical borders would be another. If you set your border style to dashed, the distances of the dashes varied greatly. Basically, when it comes to borders, stick to static units.

So far, FireFox 3.0b2 has the best results

Theoretically speaking, when I wrote this page, I knew that no matter what the size of the window, the page would have the exact same proportions. For the most part, this is true. The only browser that makes this theory a reality is Firefox 3.0b2.

(Note: I have not tested border-widths in Firefox 3.0b2.)


Recommended Materials