FireworksColdFusionDreamweaverFreehandFlashMXHome
Latest New Content

Latest Free Content
View All
Free Content
Accessibility
CMX Learning Guides
Hosted by enterhost

The Jello Mold: A New Look at Min- and Max-width For Web Pages - Part One

By: John Gallant , Holly Bergevin ,

A New Way To Wrap A Page

When designing a web page, a very important factor is width. More specifically, how wide will your page content appear on the screen? This is not a trivial question because users may set their screen resolution to a variety of pixel widths, and you have no control over that decision.

Pros and Cons of Basic Page Layout

If you do not assign an overall width to your page (via some kind of wrapper element), it will fill the user's browser window, which puts the true content width under their control. Thus your page is considered to be "liquid" and might be squashed down quite thin or widened out tremendously. You have no way to know, and the page will have to be designed so it displays acceptably both ways.

A particularly bad issue that can occur in liquid designs is text lines that get stretched out to absurd lengths, making it difficult to read the text. Conversely, too much content fit into a narrow space can make line lengths short, and again difficult to read.

A very common design method is to surround the content with a "wrapper" element of some kind, and set a width on that wrapper. You may use a pixel, EM, or percentage width, each with its own problems.

A "rigid" pixel-width wrapper will keep the page content at a constant width, but a very wide browser window will show lots of extra space to the sides of the rigid wrapper. However, if the window is made narrower than the wrapper, there will be some horizontal scrolling which most users really dislike.

EM widths for the wrapper element are better than pixels when the user adjusts the text size; the size of the container will adjust, hopefully keeping things in proportion.But otherwise, they are no better than pixel widths because horizontal scrolling can still occur.

A percentage width on the wrapper is a bit of an improvement, because while the content width may vary somewhat, there is also less wasted side space in the wider browser windows. Another improvement to this layout type is to set a minimum pixel width on the wrapper element using the CSS min-width property. This will cause the width of the element to "lock up" at some minimum predefined width, keeping content from being crushed down too narrow for comfort.

Sadly, Internet Explorer browsers for both Windows and Mac do not support the min-width property as of this writing (mid-2005). Since IE5/Mac is no longer in development, it is unlikely that the browser will ever support the property. Future support for the property in IE/Win is unknown. Currently, many coders resort to JavaScript or other scripting solutions to simulate support for min-width in these browsers. Script-enabled solutions can work but sometimes lead to various bugs, and using a script for layout purposes is not always desirable.

Finding a New Way

What if there were some method of CSS layout that had a "natural" min-width that IE browsers could support? How useful would that be? Yes, you're all correct, the answer is "Very useful indeed!" Is there such a method? Indeed there is, and it was recently invented by two coders, Mike Purvis and Stu Nicholls. These gentlemen independently developed the negative margining trick we will be discussing. Mike went even further, providing a way to make the layout moldable (like Jello) so that it flexes in a customizable manner. We'll be getting into the complete Jello Mold method in Part Two of this series.

Minimum Width, the Natural Way

Be aware that while this method of layout is a bit tricky to understand, it is not that complex to code and it works very well across modern browsers, including IE5/Win and up.

Body Padding

The first step of the natural min-width method is to place sizable side paddings on the body element. This forces any content within the body to display between those paddings, but more importantly, such side paddings will make it impossible for the body to be squeezed any smaller than the combined widths of those paddings. If you select 200px for the size of the left and right body paddings, the page can never be narrower than 400px. When the page is viewed in a window that is narrower than 400px, a horizontal scrollbar appears, just as happens when body {min-width: 400px;} is viewed in a modern, non-IE browser.

By setting these side body paddings, we have just set an "automatic" min-width that all browsers will recognize. But what good is a page where all the content is pushed in by 200px on each side? If the window is narrowed down to 400px, there will be no room left for any content! Clearly something else is needed.

Getting the Sides Back

The next step is to insert a full wrapper DIV into the body, and call it .expander. That DIV has {width: auto;} by default, so it will fill whatever body content area is available, but won't go into the body padding areas.

Now we apply a CSS trick called negative margining to the sides of .expander so that they are "pulled" out to the sides by the same distance as those body paddings:

The HTML
 
<body>
 <div class="expander">
  Some page content...
 </div>
</body>
 
The CSS
 
body {
  padding-left: 200px;
  padding-right: 200px;
}
 
.expander {
  margin-left: -200px;
  margin-right: -200px;
}

Code Block 1

The result of this is that the .expander DIV now covers the entire body width and the side padding areas as well. The display is exactly the same as if the body had no .expander inside and had no side paddings, with one single exception. Specifically, the body can now never be narrowed to less than 400px! If you do narrow it to that width, the content area shrinks to zero width and so does our DIV. Yet .expander retains its 400px of negative margining, so it still fills the window. We think that's pretty neat!

Before we go further, we need to make sure that the concept of negative margins is clear, so that what we just explained won't be so mysterious. For those of you who are already familiar with this technique, consider this just a little refresher course focused on the specific application of negative margins to this particular type of layout. Mini-tutorial time!

A Mini-tutorial on Negative Margining

Image shows a DIV with no assigned width filling 
the entire width of its containing element.

Image 1: Think of a rigid container holding a DIV that has no assigned width.

You may wonder how the smaller body content area can hold a DIV that is 400px wider, but the fact is it can, and it's perfectly legal. The .expander DIV is still inside the body content area, but its sides are made to flow out across those body padding areas without moving or changing them at all.

It may be a little hard to grasp, but think about how positive side margins would work. If those side margins were +200px, then .expander would be pinched in by that amount on each side from its normal width, which by default fully spans across the body content area between the side body paddings.

Image representation of a DIV with a 
left margin inside a container element.

Image 2: The DIV's edge is pushed to the right by its own positive left margin. The red arrow shows movement of DIV's edge in response to the margin spacing.

One way to think of that side margin is to imagine it coming invisibly out of the DIV and contacting the inside edge of a surrounding container. If it is a left margin, the outside edge of the margin touches that rigidly fixed container "wall," forcing the left DIV edge to back off to the right, creating a space between the div edge and the container edge as shown in Image 2 (the black arrows represent this side margin).

When a margin is used on an interior element such as the nested DIV, it is the DIV edge generating the margin that gets moved over, rather than the outer container. It wouldn't be logical for the margin to push the container out to the left, so it's the inner DIV's left edge that does the moving, and it moves to the right. The margin tries to extend outward from the DIV, but the visual effect is that of narrowing the no-width-specified DIV by the value of that margin. In Image 2 the left border edge of the DIV actually moves to the right, as shown by the red arrow.

Reversing Directions

First we need to be clear on what the term negative really means in regards to margins. A common error is to assume that "negative" in this case refers to the leftward direction, and "positive" to the right. In fact, a positive margin always tries to push outward from the center of the generating box as we have previously described. It is important to remember that the outer margin edge and the container edge remain in contact at all times.

Imagine what happens when our example DIV's left margin is made negative. Since the outer margin edge (the points of the black arrows in our images) is permanently glued to the container side, when the direction of the margin gets reversed by making it negative, the actual margin flips around and points toward the center of the div.

Image representation of the widthless DIV expanding 
its size in the amount of the negative margin.

Image 3: The DIV's edge is pulled to the left by its negative left margin. The red arrow shows the leftward movement of DIV's edge.

Since the outer margin edge remains in contact with the container edge, and the container is rigid and cannot move, the only thing that can move is the DIV's left edge. That edge is forced to move left when the reversed left margin is pressing to the right against the immovable container edge. The left edge of the inner DIV is still driven away from the left container wall, but outward rather than inward. This is the action that "pulls" out the side of the inner DIV, as shown in Image 3.

If the inner DIV is given a specific width, then that negative margin will drag the entire DIV to the left, but if that DIV is left widthless then its right edge is still tied to the right edge of the outer container. This causes the inner DIV to be widened by that negative margin. When both sides of the DIV are negatively margined, they will both be pulled outward.

Those outer margin edges are still tied to the container edges just as before, so the DIV really is "inside" the outer container, but it is displayed as though it were overflowing the container. Any other elements out there will not be moved around by this action, but they can be covered up by the widened DIV, so a negative margin may produce a "layering" effect similar to absolute positioning.

Now we return you to our regularly scheduled tutorial...

Not So Fast!

You thought we were all done, didn't you? Hah! Not in a universe that contains Internet Explorer for Windows. Sorry, but those browsers once again need special treatment, and Safari also pops up with a weird but easy to fix bug.

Safari Negative Margin Bug

Safari's problem is that if the negative margins on #expander do not have sufficient room within the window at load time, the margins are simply ignored, resulting in an #expander DIV with no width at all, totally destroying the layout. The fix is just to add the two negative margins, change the sum to a positive value, and apply that value to #expander as a CSS min-width value:

The CSS
 
.expander {
  margin-left: -200px;
  margin-right: -200px;
  min-width: 400px;
}

Code Block 2

That's all it takes! Sorry Safari, you just aren't in IE's league, bugwise. Since IE6 doesn't support min-width it can never be harmed by this fix, and all other tested browsers are fine with it as well. Whew!

Explorer Gets Its Fixes, As Usual

Unlike other modern browsers, Internet Explorer for Windows has special problems which must be addressed before this min-width method is ready for general use. The most critical consideration is the issue of layout, which we described in List Display Problems In Explorer For Windows - Part Two; available by subscription or for purchase by non-subscribers.

For this method to work properly in IE/Win, .expander must be given layout. This can be done by assigning any dimension to the box. Other properties can trigger layout too, such as {display: inline-block;} or {position: absolute;}. However, the only layout-triggering property that is suitable for this method (other than adding a dimension) is the float property applied to the DIV. But this leads to strange bugs in IE/Win that must then be corrected with special margining and padding that only IE/Win can see. We would rather avoid that if we can.

So what about some width or height? Well, a 100% width won't work because .expander needs to remain widthless. Can a height trigger layout while leaving the layout otherwise unharmed? Sure it can.

Normally when IE/Win needs a box to have layout, the Holly hack is used. This method feeds IE/Win a 1% height on the box with the IE bugs. IE/Win will then ignore that height because the content inside is (generally) larger than that, and IE/Win never allows content to protrude outside a dimension-controlled box, except in the cases of negative margining and relative shifting. IE/Win just makes the box as tall as needed, but in the mean time we have triggered layout.

Unfortunately, that {height: 1%;} trigger can't be used because of the percentage bug that occurs on .expander. Fortunately, using a variation of {height: 0;} is just as good when it comes to triggering layout in IE/Win! So, using a modified Holly hack we can give .expander the layout it needs to avoid bugs in IE/Win:

The CSS
 
/* \*/
* html .expander {height: 0;}
/* */

Code Block 3

The next issue is IE/Win's well known tendency to hide negatively margined elements when they protrude outside their parent containers. The standard fix for this is to give the clipped element {position: relative;}, and indeed that fix still works just fine. This property may be applied in the regular .expander rule, because it does not change anything in other browsers.

The CSS
 
.expander {
  position: relative;
  margin-left: -200px;
  margin-right: -200px;
  min-width: 400px;
}

Code Block 4

The remaining fixes involve applying layout to an additional pair of DIVs. The first of these additional DIVs will be placed around .expander, enclosing it, and the second will be nested inside as .expander's direct child. We know this is annoying, but it has to be done to get IE's conformance. Besides, that outer DIV will come in handy in our next tutorial, so it's not quite as bad as it sounds.

Here is what the new markup will look like:

The HTML
 
<body>
 <div class="sizer">
  <div class="expander">
   <div class="innerwrapper">
   Some page content...
   </div>
  </div>
 </div>
</body>

Code Block 5

Both .innerwrapper and .sizer need layout. .innerwrapper needs it so that any percentage sized page elements will calculate their dimensions based on .expander and not on .sizer or the body element. .sizer needs layout for the benefit of IE versions prior to IE6. Without this DIV, bad things happen to the layout.

Since we are already using a modified Holly hack on .expander, it's easy to just add the two new DIVs:

The CSS
 
/* \*/
* html .sizer,
* html .expander,
* html .innerwrapper
{height: 0;}
/* */

Code Block 6

Here is the complete code set all at once:

The HTML
 
<body>
 <div class="sizer">
  <div class="expander">
   <div class="innerwrapper">
   Some page content...
   </div>
  </div>
 </div>
</body>
 
The CSS
 
body {
  padding-left: 200px;
  padding-right: 200px;
}
 
.expander {
  position: relative;
  margin-left: -200px;
  margin-right: -200px;
  min-width: 400px;
}
 
/* \*/
* html .sizer,
* html .expander,
* html .innerwrapper
{height: 0;}
/* */

Code Block 7

The above code is the absolute minimum needed to achieve cross-browser compliance with this min-width method. As we mentioned, .innerwrapper is only specifically needed to fix percentage bugs in IE, but .sizer will come in quite handy in the next tutorial when we show an exciting modification that greatly enhances this layout.

Seeing Is Believing

Here is a live demo (opens in a new window) of the natural min-width in action. If you haven't done so already, click and drag your browser window to narrow the demo page. Note that when the window narrowing causes the body element to drop below 400px in width, a scrollbar is forced to appear. This is happening because the 400px total side padding on the body won't let it get any narrower than that.

To Be Continued

So we now have a natural minimum width for the body element or any other element for that matter. In Part Two of the series we will show modifications we can add to this method to further customize how our page will behave. It's going to be very interesting and useful, so stay tuned!


Keywords
CSS, Jello Mold, min-width, max-width, negative margins, position: relative, width, liquid, liquid layout, wrapper, holly hack, layout, padding