Page Layout 101

In the beginning, the Internet, and more specifically the world wide web, was a way of exchanging information between universities and government agencies. The Hypertext Markup Language (HTML) was developed to accommodate exchanging documents between different computer systems where most existing document types would be incompatible with the different computer systems.

These documents were largely text and there was no need for any complicated layout mechanism. HTML used tags to define what various objects were on the page and let the user's browser to decide how to present it. In HTML, the document content flows from left to right and top to bottom. There were no provisions for positioning objects at some specific point on the page. There was simply no need for it.

Well, that was then. This is now. What a difference a couple of decades makes! Web pages have now become works of art with complex designs that require content to be in a particular place on the page. When web designers first started trying to position content, they borrowed the <table> tag used to present rows and columns of data. They bent and twisted the table in ways the originators of the HTML language never dreamed. It was effective, but messy. Then, along comes CSS, the ubiquitous acronym for Cascading Style Sheets. To be specific, CSS2. That's level 2 of the CSS specification. CSS2 provided for methods of positioning page content. Finally!

Using Layers

If you, like me, use Macromedia Dreamweaver for web design, you may be familiar with something that Macromedia calls a "layer" or what is referred to in Dreamweaver CS3 and later as an absolutely positioned (AP) <div>. You should know that there is no such thing as a layer; not in the HTML specification, nor in the CSS specification. That's why the term layer was dropped in Dreamweaver CS3. Layer is Dreamweaver terminology that refers to an absolutely positioned page element, usually using a <div> tag.. Using absolute positioning allows you a huge amount of freedom in creating a design and enables you to drag objects around on a page and put them exactly where you want them like you would with a desktop publishing (DTP) application..

About now, if you weren't already familiar with absolute positioning, you'd be saying "WOW! That's fabulous!" Okay, you've probably heard the phrase, there's no such thing as a free lunch. It was never more true than it is in this discussion. So, what's the price of this fabulous feature? The price is that absolute positioning is, well ... absolute. Objects using absolute positioning are positioned relative to their nearest positioned parent object, or if there is no positioned parent object, relative to the upper left corner of the browser viewport.

Sorry for that bit of geek-speak. What's it mean? Let's say you have positioned two layers on a page. You've got everything lined up perfectly and it looks like this:

Image of initial perfect alignment

Note that I've put different colored borders on the two layers to illustrate what happens here. The two <div> tags, generated by Dreamweaver for those two "layers" look like this in versions of Dreamweaver prior to 8:

<div id="Layer1" style="position:absolute; left:100px; top:100px; width:200px; height:100px; z-index:1">
<div id="Layer2" style="position:absolute; left:100px; top:210px; width:200px; height:100px; z-index:1">

Dreamweaver 8 and later will put the layer styles in a <style> block. For older versions of Dreamweaver, we're going to extract the styles from those two "layers", put them into a style block similar to the way it is done in newer versions only slightly more efficient, and add the borders. Here is the pertinent CSS, extracted from the layers:

   <style type="text/css">
   #Layer1, #Layer2 {
      border: 1px solid;
      height: 100px;
      position: absolute;
      width: 200px; 
   }
   #Layer1 {
      border-color: red;
      left: 100px;
      top: 100px; 
   }
   #Layer2 {
      border-color: blue;
      left: 100px;
      top: 210px;
   }
   </style>

The reason this was done was only to make it easier to illustrate what happens. It, in no way, affects the result. You'd get exactly the same result if you edit the in-line style created by older versions of Dreamweaver.

The Problems with Layers

Overlapping text

Now, let's say someone with less than perfect vision views the page. Because their eyesight isn't very good, they have the text size in their browser set a bit larger than you did when you designed the page. What does your perfect layout look like now? It looks like this:

Image demonstrating overlapping text

WOW again!!! That's clearly not what you had in mind when you so carefully laid out the page. Look how the text overflows and overlaps. Why does that happen? It's because your layers are positioned absolutely, from the top left corner of the browser. The second layer doesn't move down to allow space for the first one. There is a small difference in the way Gecko browsers (Netscape 6+, Mozilla and Firefox) handle this and the way Internet Explorer does it. Gecko browsers will render it as shown in the images above, where the text simply overflows its container. Internet Explorer expands the "layers" to contain the text, so that the borders will also overlap. In either case, the result is the same. You wind up with overlapping text.

The other noteworthy point here is that absolutely positioned page content (layers) do not affect the layout of any other content. That means that you will encounter the same problem of things overlapping with content that is not in layers. If either one of the boxes above were a table instead of a layer, the content of the layer would still overlap it.

My Layers Move

This one jumps up to bite you when you use layers in conjunction with some other page layout methodology, like a flexible table, or a centered content design. Consider this layout:

Centered table example

The top text section (with the blue border) is in a 300 pixel wide, centered table. The bottom text area (with the red border) is in a 300 pixel wide layer. The two line up nicely when the browser viewport is about 800 pixels wide. Now, see what happens when the browser window is about 1024 pixels wide:

Centered table example with misaligned layer

Uh oh! Look at that. Our layer moved! Well, the truth is that they layer did not move a single pixel. Layers use absolute positioning and it's EXACTLY where is was in the preceding screen shot. It's 232 pixels from the left edge of the browser viewport and 44 from the top. Note that these two screen shots are scaled down to fit in this page. You'll have to trust me on this one.

Okay, so if the layer didn't move, what happened? The table moved. Because it is centered, when the browser viewport got wider the table had to move to the right to stay centered. The layer, because it is positioned absolutely, did not move. This example used a centered, fixed width table. You would run into exactly the same issue if you used a percentage width table because the contents of that table would move to accommodate changes in the viewport width, while the layer remained rock solid, right where you put it.

How Do I Fix It?

So, how do you prevent such ugliness. If you're new to web design, or have a strong background in print design, you'll be asking how to prevent the user from re-sizing the text, or how to keep the browser window exactly the right size to maintain your layout. Those are the wrong questions. The user may need larger text to be able to read it. The fact is, you cannot prevent the user from re-sizing the text. Neither can you control, with any reliability, how wide the browser viewport is going to be. The right question is how to you make the page accommodate the changes in text and/or window size without destroying itself. One answer is to not use absolute positioning. Absolute positioning is just a small subset of the positioning possibilities introduced by CSS2. Instead, use "static" positioning and control the position of page elements using their margin and padding properties.

Positioning with Margin and Padding

So, how would you go about that? It's easier than you think. Let's change the CSS we extracted from the "layers" and make it look like this:

   #Layer1, #Layer2 {
      border: 1px solid;
      width: 200px; 
   }
   #Layer1 {
      border-color: red;
      margin-left: 100px;
      margin-top: 100px; 
   }
   #Layer2 {
      border-color: blue;
      margin-left: 100px;
      margin-top: 10px;
   }

What have we done here? We simply removed the "position: absolute" and "height: 100px" assignments, changed all the top and left assignments to margin-top and margin-left, and changed the second layer's positioning from top: 210px to margin-top 10px. Now, what does our "perfect" layout look like? With normal text size, it looks exactly the same:

So what happens now, when the user increases the text size? You get something more like this:

Image demonstrating enlarged text maintaining alignment

See how the top, red bordered <div> now expands to contain the text and the second <div> moves down to allow the expansion without overlapping the text. That was what we wanted. Let's look at one more thing while we're here. Notice how the text butts right up against the border? That doesn't look good. It needs just a little bit of white-space. You add space between the content and the border using the padding property. Let's add five pixels of padding to both <div> tags. To do this, we change the first style (for both div's) to this:

   #Layer1, #Layer2 {
      border: 1px solid;
      padding: 5px;
      width: 190px; 
   }

Note that we simply added the padding, but that we also changed the width from 200 pixels to 190 pixels. That's because the width assignment applies to the content area. Because we wanted our border to remain 200 pixels wide, and it has five pixels of padding on each side, we had to subtract that from the width. The result is a 200 pixel wide border that looks like this:

Image with some padding added

In this case, the content is not centered. It will always be 100 pixels from the left edge of the browser viewport. If you wanted multiple items to be centered in the browser, but retain their positions relative to each other, you'd simply use a wrapper <div> with a fixed width, and center that wrapper.

Now we have a flexible layout that does exactly what we want. Well ... almost.

Accommodating Browser Bugs

There's one more thing we have to consider. As mentioned, width applies to the content area. Padding and borders are added to that to determine the exact area occupied by an element on a page ... except when a browser get's it wrong. The standards explain the box model, which is what describes all these width, height, margin, padding and border calculations. The problem is that there is an ancient browser that hasn't been updated in years except to address its many security holes and this browser is still widely used. You guessed it: Internet Explorer. Do a Google search for "box model bug" and you'll get something in the neighborhood of 1,780,000 results that describe how IE gets it wrong and address ways to compensate for it.

The short description of the problem is that IE version 5.x uses the width property to calculate the overall width and subtracts the padding and border from that to determine the space available to the content. That's wrong. It's just the opposite of what it should do. The bug was fixed in IE version 6 as long as the browser is rendering the page in standards compliance mode. When in quirks mode, IE6 still renders it wrong. IE5.x and IE6 in quirks mode render the above like this:

IE quirks mode rendering

Since we used a small amount of padding, the difference is not obvious, but trust me, the border here is only 190 pixels wide instead of 200 pixels wide. That small difference may not be worth addressing, but what if we were using 20 pixels of padding. When you add 20 pixels padding and one pixel border for each side, you have 42 pixels difference in the width. Now, your content only has 158 pixels and that's significant. That's worth addressing. So how do we get IE to render the page correctly? Google has 1,780,000 answers. Here is one of them.

Compensating for IE's Box Model Bug

The first thing we do is ensure that IE6 renders the page in standards mode instead of quirks mode. We do this by including a full DOCTYPE in the page. See the W3C specifications for the details, but for now, we'll use the HTML 4.01 Transitional DOCTYPE:

   <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
      "http://www.w3.org/TR/html4/loose.dtd">

That must be the very first thing sent to the browser. It should be the first lines in your page. If you have anything, including comments or blank lines, before the DOCTYPE, IE6 will jump into quirks mode. Now, with a correct DOCTYPE, IE6 will render the page correctly. Frankly, IE5.x is a dead issue. Most stats have it at nearly zero usage. However, if your audience still includes some IE5.x users and you want to accomodate them, it's not too hard. There are many ways to do this. There are various CSS "hacks" that will allow you to filter styles, but one way that uncomplicates the style sheet and segregates the IE specific code is called a conditional comment. You can read more about conditional comments on Microsoft's MSDN web site, but suffice it to say that you can give IE5 it's own code like this:

   <!--[if IE 5]>
   <style type="text/css">
   #Layer1, #Layer2{width: 200px;}
   </style>
   <![endif]-->

We place this code in the <head> of the document after the other styles or link to an external style sheet. That will provide the fix for IE5.x. All browsers other than Internet Explorer will see this as a comment and ignore it. IE6 and newer will see that it only applies to prior version 5 and ignore it. IE5 will see it and, instead of rendering the <div> elements as 190-10 pixels wide, render it as 200-10 pixels wide like the rest of the browsers on the planet.

We now have the final solution. We have a page that renders the same in different browsers and that will allow users to re-size the text as needed to be able to read it. Remember, site users are the reason that the web site exists. If they cannot read the text, there's no reason to put it on the web.

Conclusion

This has been a brief introduction to positioning with Cascading Style Sheets (CSS). It doesn't begin to address all of the many features available in the CSS specification. The purpose was to identify a problem (absolute positioning) and suggest a solution. That doesn't mean that absolute positioning is the road to ruin. There are times when absolute positioning is the only way to accomplish something. The problem, like with everything else, is that you need to understand it and know how to use it to be able to use it effectively.

My hope is that this brief intro will prompt you to learn more by doing a few of the many tutorials available around the web and perhaps reading a book or two.

Happy reading!