Supporting New Elements in Firefox 2
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:
- Go back to using
div
elements - Use content type negotiation between
text/html
andapplication/xhtml+xml
- 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.)
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.
yeah, what Sean said.
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);
}
});
});
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
I completely forgot about the possibility of using XHTML5. 🙂 Updated the post, thanks.
It would be simpler to display a message saying Firefox 2 has known security vulns and the user should upgrade to Firefox 3
@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.
[…] Simon Pieters explains it as: […]
Another good advice for all user agents, is to close the closing tag of the
p
element. Otherwise new elements, such ashgroup
(knowns asheader
when you wrote this article) might become the child of the precedingp
element.See demo in Live DOM Viewer
[…] usar una técnica basada en Javascript que Simon Pieters nos ofrece, o servir XHTML en lugar HTML al […]
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.)
(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.)
Andy, you can’t put block level elements inside an anchor (which is inline), since HTML4.
@Ricardo: In HTML 5, you are explicitly allowed to wrap blocks in anchors (new feature 😉
[…] 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 […]
[…] 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). […]
It’s a good thing mobile devices already support much of the new HTML5 syntax. Hopefully they’ll drive innovation forward.