FireworksColdFusionDreamweaverFreehandFlashMXHome
Latest New Content

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

The Practice of CSS Column Design: Boxes in Columns

By: John Gallant , Holly Bergevin ,

Minimal Bordered Boxes

In out last article, The Theory of CSS Column Design: Semantic Construction, we discussed making accessible layouts using divs for basic page construction blocks. Now we will show how to build a column of separate bordered boxes, each with a colored header, similar those currently in use on the CMX main page (as of July, 2004), shown in the graphic to the right.

This paragraph has a green background, yellow text, and has 10px margins on all sides, along with 5px padding to keep the text from touching the sides of the green paragraph.

The outer black border is only there to show the exact position of the containing div element. The paragraph background-color is used for the same reason.

Demo 1: from the Semantic Construction article

An example of the right 
column on CMX.

Image: CMX Column Design

We ended the previous article with an example demo of plain paragraphs inside a bordered div column, as reproduced in the live demo to the left. Since the aim of the current exercise is to have a vertical row of bordered boxes, we will start by removing that indicator border on the container div and apply it to the paragraph selector instead. While we're at it, we'll also remove those awful colors from the paragraphs (Holly insists!).

Once that is done, what is left is a column of bordered and colored boxes, each with a paragraph's worth of text. The code for this is in Code Block 1 below.

One thing you must be aware of when arranging margined boxes vertically like this is the confusing way in which their margins can interact. The behavior is often referred to as "escaping margins," but it is not clearly described as such by the W3C. That part of the margin specifications is not easy to explain.

Take a look at Demo 1 above and think about the upper 10px margin on the top paragraph. In the demo, you can see how that top margin is trapped in between the top div border (black line) and the green paragraph top. The margin is the white area. Well, according to the specifications, the only thing that keeps the margin there is that top border!

The HTML:
 <div id="holderdiv">
   <p>Just a typical paragraph</p>
   <p>Just another typical paragraph</p>
 </div>
 
The CSS:
#holderdiv {width: 250px;}
 
#holderdiv p {
  margin: 10px;
  padding: 5px;
  color: #363636;
  background-color: #eec;
  border: 1px solid black;
}

Code Block 1

We retained a background-color on the paragraph, but muted it to a less dangerous level. Not many people like a bordered box showing the same background as the page.

See how the paragraph margins are still here, even though it is no longer obvious.

Demo 2

Now take a look at Demo 2. There we have removed the div border as shown in Code Block 1. Even though you can't see it, the top margin on the first paragraph now actually sticks out the top of the div. It sounds weird, but that is the way the W3C decided to do it.

Comparative screenshots between Mozilla and Explorer.

Unfortunately, Explorer for Windows only obeys this part of the margin specs when the containing div does not have a dimension. Since the containing divs in all the demos here do have widths, IE/Win acts like the border is still there, keeping the margin trapped instead of letting it escape like the specifications require. This is nothing unusual for Explorer; all kinds of spec violations can happen in that browser when a critical element is given a dimension.

To the right are screenshots showing the true margin arrangements in IE/Win and Mozilla. The div has been colored gray to indicate its location and size. Notice how Mozilla lets the invisible vertical margins go out the top (and bottom) of the div. The bottom escaping margin then collapses with the top margin on the caption paragraph below. If the div did not have an assigned width then IE/Win would display just like Mozilla.

Happily, once this problem is understood, it's easy to avoid the differences in display it may cause in various browsers. Just remove the top margin from the paragraphs and use a top padding on the div instead. Vertical padding on a box with no assigned height does not cause the box model problem, so it's perfectly safe. Yes, all the paragraphs will have their top margins stripped off, but their bottom margins will still keep the spacing between paragraphs the same.

Below is how the code might look when using this technique:

#holderdiv {
  width: 250px;
  padding-top: 10px;
}
 
#holderdiv p {
  margin: 0 10px 10px 10px;
  padding: 5px;
  color: #363636;
  background-color: #eec;
  border: 1px solid black;
}

Code Block 2

Be aware that either borders or padding can trap the margin inside the div, so it's possible to use as little as 1px top and bottom padding on the div to permanently trap the margin of a child element within the div. These workarounds are often not needed, but in some layouts it is the only way to make things look the same in all browsers, so it's good to know about them in advance. Many a margin newbie has been brought close to madness while trying to figure out this puzzle. Don't let it happen to you.

Box Tops

So far, we have created a container div, filled it with semantic box elements (the paragraphs in our examples), and discussed the main issues involving margins. Only one thing remains to be added, namely those full-width colored headings across the tops of the boxes. Those are the things that turn a ho-hum box into a "Labeled Resource Environment." Not bad eh? We just made that up.

To do this properly we can't just stick our headings into the paragraphs we started with, because other block elements are not allowed inside paragraphs, and that includes <h1> through <h6> headings. Instead, we transform our original paragraphs into divs, and then insert additional paragraphs and headings into those new divs. The backgrounds and borders that were on the original paragraphs are moved to the divs, leaving the new paragraphs unstyled. The headings are also placed first in each inner div.

The HTML:
 <div id="holderdiv">
   <div> <!-- a bordered box -->
     <h2>1st Box</h2>
     <p>Just a typical paragraph</p>
   </div>
   <div> <!-- a bordered box -->
     <h2>2nd Box</h2>
     <p>Just a typical paragraph</p>
   </div>
 </div>
 
The CSS:
#holderdiv {width: 250px;}
 
#holderdiv div { /* Selects any div inside #holderdiv */
  margin: 0 10px 10px 10px; /* moved from paragraph */
  color: #363636;
  background-color: #eec;
  border: 1px solid black;
}
 
#holderdiv p {margin: 5px;} /* changed from padding */

Code Block 3

1st Box

The paragraph display has remained the same, although the properties used have been changed or moved to different elements.

2nd Box

The headings are not yet styled, however, so they seem a little bit ugly, but soon...

Note how the margins between this paragraph and the one above don't add together, but instead collapse down to the width of the largest margin.

Demo 3

The most important change made in this new arrangement is that the bordered boxes (the new divs) no longer have padding. This is crucial because it will allow these boxes to be entirely filled with content, from top to bottom and from edge to edge. We need that to happen because when the headings are styled, we want them to contact the box border rather than be pushed inward by padding on the box. You can see this in the Demo 3 to the left, where the headings touch the box border but the paragraph text does not.

The padding may be retained within the paragraphs, but if more than one paragraph is to be placed in a single bordered box, it is better to use margins on the paragraphs instead. This is because vertical margins collapse neatly while paddings do not. To demonstrate this, we have replaced the paragraph padding with margins in Demo 3, as indicated in Code Block 3 above. Observe how the margins look just like padding, but when two paragraphs come together it does not behave like padding.

Tweaking the Headings

At last we arrive at the headings themselves. Whew! Okay, so we want the headings to fill the width of the bordered box, which is easy because that is the default behavior of all block elements. However, headings also have default vertical margins just like paragraphs, so we must zero out those margins. If not, the heading background will be detached from the div's upper box border, creating something less than pretty. So let's do that.

#holderdiv h2 {
  margin: 0;
  background-color: #7a7;
  color: white;
  font-size: 0.9em;
}

Code Block 4

1st Box

These boxes are starting to look a bit more like we expected them to. The heading stretches from edge to edge and is shaping up nicely.

2nd Box

Just a little more styling and these boxes will look really great!

Demo 4

Now our boxes look pretty good, but the headings are rather cramped and perhaps would look better if they were centered. So let's take care of those things.

First though, you should know that in certain types of layouts, the colored background on the headings can be buggy, particularly in IE5/Win. Usually this happens when floats are mixed with positioning. If anything funny happens to any background, for example getting cut off after the last letter, it is easily fixed by applying a dimension to the offending element.

But, you might ask, what kind of dimension? We can't put a width on any of the elements within the bordered box, because then they won't automatically adjust to fit the bordered box. Sure, you can use {width: 100%;} on the heading, but then side padding could cause trouble by making the heading even wider than 100%. This is a problem best avoided if possible.

You might apply a specific height to the heading, but then text resizing by the user can make it look incorrect. Conveniently, there is another way to apply a height without causing any problems, via the Holly hack, which you can find described in our article How To Attack An Internet Explorer (Win) Display Bug. Note that in the article you are reading, the demos do not have any problems in IE/Win. We just mention it because sooner or later this problem will cause you trouble. Trust us.

By the way, the Holly hack has actually been used on on CMX's main page to fix the box headings for the benefit of IE5/Win.

Finishing Up

Now we'll look at the final code for our column of bordered boxes. First, a bit of padding has been added to the headings to improve the look, as well as the text-align property to center them.

1st Box

Now this is one fine looking Labeled Resource Environment! Yeah!

2nd Box

Any number of boxes may be added to the stack. No problem.

Hey, guess what? Now you can have any number of paragraphs in each box, or anything else for that matter. Woohoo!

Demo 5

Next, to create the dividers between the paragraphs seen on the CMX main page, we made a special class called .p-divider, which gets applied to any paragraph in our box that needs a line above it. This class places a top border on any element that gets the class, but we can't leave it at that.

The paragraphs have 5px margins all around, so any borders given to them will stay inside that margin, failing to meet the sides of #holderdiv. The way to correct this is to remove the side paragraph margins and replace them with side paddings.

Now the top paragraph border does meet the holder sides, but there's another problem. We want the divider to be spaced away from both of the paragraphs, but instead it will touch the top of the text in the lower paragraph, since that paragraph has no top padding to push its top border away. This is actually no problem, we'll just add some top padding to that paragraph, via the same class we used to apply the top border. The paragraph margins will collapse as usual above the divider, leaving everything looking great. Take a look at the final code:

The HTML:
 <div id="holderdiv">
   <div> <!-- a bordered box -->
     <h2>1st Box</h2>
     <p>Just a typical paragraph</p>
   </div>
   <div> <!-- a bordered box -->
     <h2>2nd Box</h2>
     <p>Just a typical paragraph</p>
     <p class="p-divider">This p has the top border</p>
   </div>
 </div>
 
The CSS:
#holderdiv {width: 250px;}
 
#holderdiv div {
  margin: 0 10px 10px 10px;
  color: #363636;
  background-color: #eec;
  border: 1px solid black;
}
 
#holderdiv h2 {
  margin: 0;
  background-color: #7a7;
  color: white;
  font-size: 0.9em;
  padding: 5px;
  text-align: center;
}
 
#holderdiv p {
  margin: 5px 0; /* Only vertical margins on the p */
  padding: 0 5px; /* Also side padding */
}
 
#holderdiv .p-divider {
  border-top: 1px solid black;
  padding-top: 5px; /* This one gets top padding */
}

Code Block 5

In case you're wondering why we don't just use a horizontal rule to create the divider, it's because browsers vary quite a bit in their handling of this element, and by using a border all those variances are side-stepped. Since horizontal rules are purely visual and add nothing to the semantics, nothing is lost doing it this way.

Things to Watch Out For

IE5/Win may show display differences with later versions of that browser, especially with unstyled headings. This has to do with the escaping margins we discussed earlier. In this instance, the problem is easily solved with the judicious use of the Holly hack on the bordered div. For our styled headings in Demo 4 and 5, the margins were completely removed from the headings, allowing IE5/Win to display just as IE6 and other browsers do. We would explain this in greater detail, but since IE5/Win is now a very minor browser, you may not want to be buried with details on old behavior variations. Suffice it to say that such margin problems, when present, will never hide content, so if a rare visitor happens to see something that is less than perfect, it won't be the end of the world.

The one issue that really can cause trouble with these narrow boxes, is placing wide images or long URLs within them. The more standards-compliant browsers will just allow such too-wide content to stick out the right side of the box. That's not exactly pretty but the content is still available.

IE/Win does not do this, however, but instead forces the box to become wider, even though we specifically made the column 250px wide! This behavior pushes out the right edge of the box, but strangely does not allow the rest of the content to flow into that new box area, leaving an empty zone to the right of the content, save for that one piece of wide content.

Even worse, if the bordered box with the too-wide content is a part of a larger design, it can overlap other boxes, or if it happens to be a float it might "wrap" down to a lower screen position where it can find more room for itself. This is not a good thing. Nothing can be done about wide images, other than to be careful about the size of the images you use. "Unbreakable text" can, however, be prevented from extending a box in IE/Win by use of a handy IE proprietary CSS property that forces a break in the text. When there is no point in the text line that normally would break to a new line (like with long URLs), just add this declaration to the bordered box rule in the CSS:

#holderdiv div {word-wrap:break-word}

Code Block 6

That's all there is to it! Now any pesky long URL that sneaks into the box will get snapped off to a new line, like it or not. Ain't that nice?

Note: word-wrap, as we indicated above, is a proprietary CSS property that IE/Win browsers can use. No other browsers currently respond to this property. In addition, a style sheet using the word-wrap property will not validate. This may or may not be important to you, but we wanted to make sure you knew all the "consequences" of using the property.

Conclusion

We have included a sample HTML page in the support files, showing a simple 3-column layout using these methods described in this and the previous article. The CSS is embedded in the page, but initially, much of it is commented out. Look at the source of that page for the section about Bordered Box selectors.

There are many things you can put in a bordered box in addition to paragraphs. What you have learned here may also be employed for lists, forms, and even floats. In addition to the content itself, embellishing these boxes is fairly straightforward. You might add a bottom border to the headings, or use a background image instead of a plain color. Extra headings can be used farther down within a single box, each with different stylings. Or the paragraphs might themselves get styled, to create "box-in-a-box" effects. The possibilities are endless.

Another way to dress up such boxes is to apply custom corners and sides. There are several techniques for accomplishing these effects, but they require greater time and effort than the methods in this article. In an upcoming "Practice" article we will "round off" our box discussion by showing that sometimes it's okay to cut corners. Stay tuned!

Approximate download size: 161k


Keywords
CSS, column design, design, headings, bordered boxes, escaping margins, collapsing margins, layout