Legends of style

UPDATE: following on from comments by Thierry Koblenz, I have written an update to this article. The techniques described below will still work in different browsers, but the new article explains how it can be achieved with a little less mark-up.

It’s a well-established fact that achieving cross browser consistency when styling form controls is an “exercise in futility”. And one of those elements that just won’t play ball is the <legend> tag.

A legend is like a caption for a <fieldset> and a fieldset is used for grouping related form controls. You don’t have to use either in your forms, but if your forms are lengthy, using fieldsets can make your forms more usable by dividing them into smaller, manageable pieces, and if you use fieldsets, you must have a legend.[1]A legend is required when using a strict HTML 4.0 doctype. Pages using strict XHTML doctypes will validate without a legend, but from an accessibility point of view, it is still recommended that you have one.

The problem

Legends work just fine if you’re not doing much styling of your form. Their default state is to display along the top border of the fieldset and indented from the left slightly, as can be seen below. (The screenshot is from Firefox 2.0.0.1, Opera 9.02 and IE6 - IE7 is identical to IE6.)

Screenshots of unstyled fieldsets with legends

Problems occur when you try to use background-colors on your form or fieldset or if you try to position the legend in any way other than the default. Internet Explorer particularly has a problem with background-colors:

Screenshots of fieldsets with legends with a background-color applied to the fieldset

The solution

So what do you do if you want a more customised look to your forms? One solution is to add extra tags around both the fieldset and legend content and style those instead.

Unlike most form elements, fieldsets and legends are simply containers for content and don’t play any part in the processing of form information, so if we use other elements to mimic their display properties, no real harm is done either to the script that processes the submitted form or to the visitor to your site.

OK, so they get a bit of additional markup, but it’s not a lot (as we’ll see next) and it in no way reduces the usability and accessibility of the form. In fact, as a lot of people disregard fieldsets and legends and their associated accessibility and usability features due to their stubborn resistance to styling, the additional markup means we’re not sacrificing those aspects any more for the design.

So how’s it actually done? In place of fieldset and legend we’re going to use generic <div> and <span> respectively. We use a span inside the legend because legends can only contain inline content. We remove all the styling from the fieldset and legend and instead apply it to the div and the span.

The black sheep

The extra div wouldn’t be necessary if it weren’t for one particular browser. And no, it’s not IE this time: it’s Firefox. As evidenced on Bugzilla, how to style legends with the Gecko rendering engine is a bit of a thorny issue. I was suprised, however, when first looking into this issue that Firefox not only has trouble with the legend when trying to use position: absolute, but also when the same is applied to a span inside a legend.

The problem is highlighted in these examples. The examples of both fieldset/legend pairs look fine in IE6 & 7 and Opera 9 (Opera 8.5 has a little trouble with the positioning in the first example too), but in Firefox 2 and 1.5, the legend in Example 1 seems to take it’s top and left coordinates from the first element in the form after the legend (a label) and not from the fieldset which has position: relative on it to establish a new positioning context.

It’s only to get the same result in Firefox that we actually need to add the extra div around the fieldset and move all the styling from the fieldset to the div (Example 2). The div also needs to wrap the fieldset and not the other way around because then the HTML would be invalid.

The examples

Having established what needs to be done to bring consistency to the styling between browsers, let’s look at a few different examples of how the legend can be positioned.

Example 1 shows the legend inset within the frame of the fieldset (or the div that looks like a fieldset) that holds it.

fieldset { border: none; }

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

legend span {
  position: absolute;
  width: 29em;
  top: 0.5em; left: 1em;
  color: #000;
  font-weight: bold;
}

I’ve given the div that holds the fieldset a class of fieldset and applied the background-color and border to that instead of the fieldset which has its default border turned off. It’s also given position: relative to establish a new positioning context which means the legend span will be placed in relation to it.

The span inside the legend is given a width because Opera 8.5 won’t display the text in a single line otherwise. It’s also useful if you want to give it a background and border as in the second example. It’s then positioned absolutely and given the appropriate top and left values to place it where it’s wanted.

Example 2 shows the legend sitting in the middle of the top border, similar to its default display. The difference is, of course, that we don’t get the problem with the background of the fieldset showing above its top border in IE.

.two legend span {
  top: -0.75em; left: 1em;
  padding: 0 0.2em;
  background: #FFF;
  border: 1px solid #000;
}

.fieldset.two { padding-top: 1.5em }

It’s given a background and border and a bit of extra padding and a negative 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 { top: -2em; left: 0; }

.fieldset.three { padding-top: 0 }

This example doesn’t need any border, background etc., and the container doesn’t need any top padding at all this time.

Example 4 pushes the legend over into the empty space at the top right corner of the fieldset.

.four legend span {
  top: 0.5em; left: 26em;
  width: 5em;
  text-align: right;
}

I’ve given it a smaller width because I wanted it to run over several lines and given it a large left value to place it where I want.

Example 5 is probably something you would hardly ever do, particularly as this won’t work in anything but IE at the moment. That’s because it uses the word-wrap: break-word property which is only supported by IE (although it is in the working draft for CSS3).

.five legend span {
  top: 0; left: -1.5em;
  width: 0.5em;
  text-align: right;
  word-wrap: break-word;
  line-height: 1;
  text-transform: uppercase;
}

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

I won’t go into too much detail about this last example. Just check it out in IE. ;)

Browse by tags:

Tags: , , , , , , , ,

Share this article:
  • Twitter
  • FriendFeed
  • del.icio.us
  • Digg
  • StumbleUpon
  • Facebook
  • Reddit
  • Sphinn

Subscribe to this site for regular updates

37 responses to Legends of style. Add your own.

Comments

  1. 1

    Great article, John. I really like some of the methods you show on your examples page. Very clever and they open up a nice set of possibilities. Typically I just remove the fieldset border, make the background color close to the the parent background it not transparent so it doesn’t look like crap, and then negative margin the legend to line it up. Your suggestions will be implemented there is no doubt. I do wish browsers supported CSS properties on legends better, but with your ideas it becomes a moot point. Some people will no doubt object to the use of a span, but I think of it as adding a puff of air. A span means nothing so adding nothing to an element is not something I concern myself with.

  2. 2

    Hi Mike,

    Obviously the aim is to use as little markup as is essential (although I do remember reading an article not so long back that actually recommended adding in a few extra ‘hookable’ elements as a form of future-proofing your layouts for possible redesigns - didn’t remember to bookmark it though), but in some cases, it’s just not possible to achieve certain visual styling with the minimum set.

    With the current state of things, extra elements abound for things like image replacement and rounded corners techniques, so I think you have to weigh up the pros and cons of extra markup versus stylistic effect and in this case, I think the extra couple of elements is perfectly acceptable.

  3. 3

    Like I said, I’m all for it. I don’t mind throwing around a few spans to get the job done. :)

  4. 4

    You should try using position:fixed for the legend.
    form legend {position: fixed;}
    Since IE6 doesn’t recognize position:fixed, all it does is add positioning to that element. This allows you to add no more code and it works great! I believe this won’t work for IE7 since :fixed actually works, so you’ll have to find another solution.

  5. 5

    Hi Micah,

    Maybe I’m missing something but using position: fixed doesn’t seem to work very well at all cross browser. In Firefox, the legend is stuck firmly along the top border of the fieldset, no matter what top and left coordinates you apply; in Opera, it takes those coordinates from the window, rather than the fieldset; and in IE6 you get the same problem as highlighted in the second series of screenshots I’ve shown in the article.

    Do you have an example that illustrates how using position: fixed will work in this situation?

  6. 6

    Nice article!! It will help me to convert my client forms to accessible forms. Before this solution, I had a lot of problems to style the legends.

  7. 7

    Hmm.. I’m not using spans or divs to style my fieldset/legend pairs. Checked in FF2, IE6/7 and both look the same. Here’s some code:

    form fieldset.sr{
    border-width:1px;
    border-style: solid;
    border-color: #cccccc;
    background-color: #f3f3f8;
    margin: 20px 0px 6px 0px;
    position:relative;
    display:block;
    padding: 0px 14px 14px 10px;

    }

    form fieldset.sr legend{
    font-weight:bold;
    background-color:#FFFFFF;
    border-width:1px;
    border-style:solid;
    border-color:#888888;
    padding:2px;
    margin:0px 0px 0px 0px;
    position:relative;
    top: -10px;
    width: 130px;
     }

    Here’s the html:

    <fieldset class=”sr”>
    <legend class=”sr”>
    <img style=”vertical-align: middle”
    src=”../images/NewGUI/Icon_Select.gif”> Select an Activity  
    </legend>
    <div id=”icons”>Dynamic icon code goes here</div>
    </fieldset>

    If I could add an image, I would. My legends have an icon in them and then the text to the right. They have a different color background than the fieldset and both have borders. Seems fine in the browsers I’ve checked. Nobody using this app uses Opera. Most IE6/7 and possibly some Firefox and maybe Safari but unlikely.

  8. 8

    Hi Bob,

    I think there maybe something necessary missing from your code because when I test your example, I still see the fieldset background-color showing above the top border.

    I’ll think you’ll also find that you can’t position the legend to appear completely above the fieldset in Firefox, i.e. with a larger negative top position (you can with other browsers).

    And positioning the legend so it sits completely inside the fieldset’s borders produces the same bg-color problems in the versions of IE.

  9. 9

    Ah yes! There is something missing!

    I keep forgetting I’m developing in Visual Studio 2005 and it’s running on IIS.

    I viewed the source for Firefox 2.0.0.3 and it’s no different than what I posted and the fieldset/legend look exactly the same as in IE6/7. Just like the PNG I sent which was an IE6 screenshot.

    I’ll double-check my code and see if I missed something. I may have missed something in the css files because I’m using multiple ones and there’s a LOT of css.

  10. 10

    Sir

    This is a fine piece of work. On many occasions have I wanted to design the legend in to a form.

    My hat is duly tipped.

  11. 11

    It’s nice that you can give width to a legend field with a div inside it. It gives the wanted effect that the legend tag lacks.

  12. 12

    Hi John,
    Nice examples.
    I just checked this one:
    http://www.tyssendesign.com.au/examples/firefox-legend-bug.html
    I think it is possible to make it work without the DIV wrapper, by using the “margin-top” and “margin-left” properties *instead* of “top” and “left”.

    As a side note, for people who want to keep their markup clean, I wrote a short script that plugs “span” elements into legend:
     http://www.tjkdesign.com/articles/how_to_position_the_legend_element.asp

  13. 13

    Hi Thierry, do you have an example of what you mean because I’ve tested it out with:


    .one legend span {
    position: absolute;
    width: 25em;
    top: 0; left: 0;
    margin-top: -2em;
    display: block
    }

    and I get a completely different position in Firefox compared to all the others.

  14. 14

    Hi John,
    I borrowed the markup of your page to do a quick test:
    Demo without the wrapper DIV

  15. 15

    Hi Thierry, you’re quite right. It looks like I’ll have to revise the article.

  16. 16

    Regarding this statement in the entry:

    The div also needs to wrap the fieldset and not the other way around because then the HTML would be invalid.

    Are you sure that is an accurate statement? The only thing I could think of that would make that invalid is if fieldsets could not contain block-level elements, but according to SitePoint and W3C, they can:

    http://reference.sitepoint.com/html/fieldset

    Type
    block-level element
    Contains
    block-level elements, inline elements

    Also, I just tested it out and validated it on http://validator.w3.org, and it validated as XHTML 1.1 Transitional just fine. So what makes you think that wrapping a div in a fieldset is invalid HTML?

  17. 17

    @Rlively: it’s invalid because the legend needs to be the first child of the fieldset, so this:

    <fieldset><div><legend>

    is incorrect.

    You could do:

    <fieldset><legend><div>
    but for the purposes of positioning the legend, it needs to be contained within a div.

    Validator results

  18. 18

    Hey John — Just wanted to thank you for this excellent article. Saved me a lot of pain!
     Ben

Pingbacks

  1. 1

    […] Styling Fieldsets and Legends […]

  2. 2

    […] Legends of style — Tyssen Design […]

  3. 3

    […] há diferenças de posicionamento da <legend> entre os IEs e Firefox. O artigo Legends of style no site Tyssen Design resolveu o meu […]

  4. 4

    […] week I read an article about styling form legends and realised I could adapt the technique to solve a problem that had recently arisen on one of the […]

  5. 5

    […] you really need are the form elements, and maybe a single div wrapper, or an offset div, or maybe a legend span, but that’s about it. I’ve heard well-reasoned and seemingly logical arguments as to […]

  6. 6

    […] picked up that little tip from Tyssen Design. Hopefully browsers will start to become a bit more consistent with their handling of the fieldset […]

  7. 7

    […] Legends of Style by John Faulds […]

  8. 8

    […] You might remember earlier in the article that I touched on the subject of fieldsets and legends being something that I like to deal with slightly differently. Currently they’re practically impossible to style consistently across multiple browsers so I like to use John Faulds method which you can read more about on his website in the article Legends of Style. […]

  9. 9

    […]find useful references, tutorials, services, tools, techniques and articles we’ve found over the[…]

  10. 10

    […] Legends of Style – It’s a well-established fact that achieving cross browser consistency when styling form controls is an “exercise in futility”. And one of those elements that just won’t play ball is the legend tag. […]

  11. 11

    […] Legends of Style […]

  12. 12

    […]del.icio.us recent »Legends of style – Tyssen Design» […]

  13. 13

    […] form has floating divs, each wrapping a label-input pair, Tyssen-style. Two consecutive divs have been set to display: none just as they would be set by Jabba-da-Script. […]

  14. 14

    […] of puking a bunch of crap all over my lovely webpage. Specifically, John Faulds provided some basic concepts and examples for styling legends and Stephanie Sullivan wrote up the strategies for encouraging legend wrapping in Firefox 2 and 3. […]

  15. 15
  16. 16
  17. 17

    […] Legends of style — Tyssen Design (tags: forms legend) […]

  18. 18

    […] You might remember earlier in the article that I touched on the subject of fieldsets and legends being something that I like to deal with slightly differently. Currently they’re practically impossible to style consistently across multiple browsers so I like to use John Faulds method which you can read more about on his website in the article Legends of Style. […]

  19. 19

    […] I want to be able to hide the legend, because it can be very unreliable to attempt to style one appropriately across all browsers.[…]

Feed for this post's comments


Required indicates required field.
Email will not be published

You can use these tags in your reply:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Leave a Reply

Contact details

Spam Protection by WP-SpamFree