Legends of Style Revised

By John Faulds

When I wrote the original article on how to achieve cross-browser consistency when styling form legends, I noted that there was a bug in the way Firefox handled legends which required an additional div to be wrapped around the fieldset with positioning and other styling applied to the div rather than the fieldset. The bug appears to still have not been resolved, but as Thierry Koblenz pointed out in the comments on the original article, there is a way to achieve the same effect across browsers that doesn't require the additional div.

Thierry believes the bug is due to the way Firefox handles the top property, so the solution is to use margin-top instead (Internet Explorer still needs top: 0 though).

The examples

Based on Thierry’s suggestion, I’ve reworked the examples from the previous article. Example 1 shows the legend inset within the frame of the fieldset that holds it.

fieldset {
  width: 30em;
  position: relative;
  padding: 2.5em 1em 0.5em 0;
  border: 1px solid #000;
  background: #F8F8F8;
  font-size: 90%;

fieldset * { margin-left: 1em }

legend span {
  position: absolute;
  left: 0;
  color: #000;
  font-weight: bold;

.one legend span { margin-top: .5em }

The previous example had a 1em padding-left but that’s now been set to 0 and instead replaced with a margin-left on all the elements because we’re using margins for positioning rather than left, top etc.

The fieldset is given position: relative to establish a new positioning context which means the legend’s span will be placed in relation to it. The left value is set to 0 because margin-left will be used for positioning instead.

The first example’s legend’s span is then positioned with a small margin-top.

Example 2 shows the legend sitting in the middle of the top border, similar to its default display.

.two legend span {
  width: 28.5em;
  margin: -0.75em 0 0 1em;
  padding: 0 0.2em;
  background: #FFF;
  border: 1px solid #000;

.two { padding-top: 1.5em }

It’s given a background and border and a bit of extra padding and a negative margin-top value to pull it up over the top border. The containing div is given a smaller padding-top in this case because it doesn’t need to make as much room for the legend in this example.

Example 3 takes it one step further and moves the legend completely above the fieldset.

.three legend span { margin-top: -2em }

.three { padding-top: .5em }

This example doesn’t need any border, background etc., and the container needs a smaller top padding this time.

Example 4 pushes the legend over into the empty space at the top right corner of the fieldset, this time using margins instead of the right property.

.four legend span {
  margin: 0.5em 0 0 25em;
  width: 5em;
  text-align: right;

.four { padding-top: .5em }

There is a spanner in the works here though and more predictably, it’s IE this time that is the cuprit. Using margin-left actually pushes the legend too far to the right, so for this example, we need to use a left value and set the left margin to 0 (or we could just give IE a smaller margin-left). IE also requires that the legend spans be set to top: 0 but as this causes problems in Firefox, we’ll include it within the conditional comments as well.

<!--[if IE]>
<style type="text/css" media="screen">
  legend span { top: 0 }
  .four legend span {
    margin-left: 0;
    left: 25em

Example 5 now also works in Safari 3 as well as IE because it uses the word-wrap: break-word property which is part of the working draft for CSS3.

.five legend span {
  margin: 0 0 0 -1.5em;
  width: .5em;
  text-align: right;
  word-wrap: break-word;
  line-height: 1;
  text-transform: uppercase;

.five { margin-left: 1.5em; padding-top: .5em }

Credit for the update to this article must go to Thierry Koblenz. Thanks Thierry! :)