The WHATWG Blog

Please leave your sense of logic at the door, thanks!

Supporting New Elements in Firefox 2

by Simon Pieters in Browsers, DOM, Elements

We have previously talked about how to get Internet Explorer to play ball when using the new HTML5 elements, but today I'm going to talk about Firefox 2.

Firefox 2 (or any other Gecko-based browser with a Gecko version pre 1.9b5) has a parsing bug where it will close an unknown element when it sees the start tag of a "block" element like p, h1, div, and so forth. So if you have:

<body>
 <header>
  <h1>Test</h1>
 </header>
 <article>
  <p>...</p>
  ...
 </article>
 <nav>
  <ul>...</ul>
 </nav>
 <footer>
  <p>...</p>
 </footer>
</body>

...then in Firefox 2 it will be parsed as if it were:

<body>
 <header>
  </header><h1>Test</h1>
 
 <article>
  </article><p>...</p>
  ...
 
 <nav>
  </nav><ul>...</ul>
 
 <footer>
  </footer><p>...</p>
 
</body>

So if you style the new elements with CSS it will probably look completely broken in Firefox 2.

If you care about Firefox 2 then there are some ways to fix this:

  1. Go back to using div elements
  2. Use content type negotiation between text/html and application/xhtml+xml
  3. Fix up the DOM with scripting

(1) is probably wise if your content structure changes between pages or over time. (2) also works but means that users will be exposed to the Yellow Screen of Death should a markup error slip through your system. Otherwise (3) can be worth to consider.

Fixing up Firefox 2's DOM is actually pretty simple if you have a consistent structure. Using the same markup as above it could look something like this:

<body>
 <header>
  <h1>Test</h1>
 </header>
 <article>
  <p>...</p>
  ...
 </article>
 <nav>
  <ul>...</ul>
 </nav>
 <footer>
  <p>...</p>
 </footer>
 <!--[if !IE]>--><script>
  // dom fixup for gecko pre 1.9b5
  var n = document.getElementsByTagName('header')[0];
  if (n.childNodes.length <= 1) { // the element was closed early
    var tags = ['ARTICLE', 'NAV', 'FOOTER', 'SCRIPT'];
    for (var i = 0; i < tags.length; ++i) {
      while (n.nextSibling && n.nextSibling.nodeName != tags[i]) {
        n.appendChild(n.nextSibling);
      }
      n = n.nextSibling;
    }
  }
 </script><!--<![endif]-->
</body>

You might think that this script would work for IE, too, when not using the createElement hack, but apparently IE throws an exception when trying to append a child to an unknown element. So you still have to use the createElement hack for IE.

If you want to move the script to head and run it on load and you don't have anything after the footer then you would replace 'SCRIPT' in the tags array with undefined to make it work.

(If you want to do content type negotiation and want to just serve XHTML to Gecko-based browsers with this bug then you should look for the substrings "Gecko/" and "rv:1.x" where x is less than 9, or "rv:1.9pre" or "rv:1.9a" or "rv:1.9bx" where x is less than 5.)

17 Responses to “Supporting New Elements in Firefox 2”

  1. Sean Hogan says:

    Another fix is generating XHTML5 files and serving them as application/xml+xhtml to XHTML enabled browsers.

    This has issues of its own, but could be a simpler solution. YMMV.

  2. yeah, what Sean said.

  3. Sean Hogan says:

    A simpler markup might be to append all HTML5 block elements with ‘wbr’ elements. This should have no effect on page semantics or rendering, but provides a marker indicating the end of a HTML5 block element.

    So the script would be something like:
    Array.forEach(["SECTION", "ARTICLE", "NAV", "HEADER", "FOOTER"], function(tagName) {
    Array.forEach(document.getElementsByTagName(tagName), function(n) {
    while (n.nextSibling.tagName != “WBR”) {
    var next = n.parentNode.removeChild(n.nextSibling);
    n.appendChild(next);
    }
    });
    });

  4. Asa says:

    Or you could just ignore Firefox 2 which is no longer supported by Mozilla, accounts for less than 2% of the web, and is falling at about a quarter point a month. If your logs don’t show significant use coming from Firefox 2, why bother with hacks and workarounds.

    - A

  5. I completely forgot about the possibility of using XHTML5. :-) Updated the post, thanks.

  6. RichB says:

    It would be simpler to display a message saying Firefox 2 has known security vulns and the user should upgrade to Firefox 3

  7. Robert says:

    @RichB, a “this site is optimized for Firefox 3″ message? I like the web the way it is going now. I’m with @Asa. If you aren’t getting a significant number of Firefox 2 users, drop / lower your support level for that browser. Otherwise, you should probably be using HTML 4. There’s no shame in that, especially given HTML 5 is still a working draft and support for a lot of the spec is still limited.

  8. [...] Simon Pieters explains it as: [...]

  9. Leif Halvard Silli says:

    Another good advice for all user agents, is to close the closing tag of the p element. Otherwise new elements, such as hgroup (knowns as header when you wrote this article) might become the child of the preceding p element.

    See demo in Live DOM Viewer

  10. [...] usar una técnica basada en Javascript que Simon Pieters nos ofrece, o servir XHTML en lugar HTML al [...]

  11. Andy Brice says:

    I get the same problem in Firefox 3.5.1 for Mac with Gecko rv:1.9.1.1 when the header is within an a, like:

    Lorem Ipsum

    (This is valid.)

  12. Andy Brice says:

    (Correction for Above.)

    I get the same problem in Firefox 3.5.1 for Mac with Gecko rv:1.9.1.1 when the header is within an a, like:

    \
    \
    \
    Lorem Ipsum
    \
    \
    \

    (This is valid.)

  13. Ricardo says:

    Andy, you can’t put block level elements inside an anchor (which is inline), since HTML4.

  14. Ken says:

    @Ricardo: In HTML 5, you are explicitly allowed to wrap blocks in anchors (new feature ;)

  15. [...] et de réarranger les éléments au fur et à mesure qu’un problème surgit. Simon Pieters a un petit exemple fonctionnel [en] sur la méthode à suivre (vers le bas de la page). Toutefois, personellement je n’ai jamais [...]

  16. [...] This rule sends the xhtml content-type to all Gecko based browsers where version is less than 1.9, or “rv:1.9pre” or “rv:1.9a” or “rv:1.9bx” where x is less than 5 (source). [...]

  17. Matthijs says:

    It’s a good thing mobile devices already support much of the new HTML5 syntax. Hopefully they’ll drive innovation forward.