Styling HTML5 markup in IE without script
The previous post discussed how to enable styling of the new HTML5 elements in IE by using a simple script. However, if the user has scripting disabled, the layout would probably fall apart badly.
So that means if you care about IE users with scripting disabled, you can't use the new elements, right?
Not necessarily.
There are some tricks to work around the broken DOM and limited styling in IE:
- Know what the DOM looks like and target other elements than the new elements for styling.
- Use the universal selector (
*
) to target the right element. - Use
noscript
.
What does this mean?
Target other elements for styling
Consider you have the following markup:
<body>
<article>
...
</article>
<nav>
<ul>
...
</ul>
</nav>
</body>
Instead of doing this:
* { margin:0; padding:0 }
body { background:silver }
article { border:solid; background:white; margin-left:10em }
nav { position:absolute; top:0; left:0; width:10em }
...do this:
* { margin:0; padding:0 }
html { background:silver }
body { border:solid; background:white; margin-left:10em }
ul { position:absolute; top:0; left:0; width:10em }
Now of course you're going to use other ul
elements than the navigation, so how do we get more specific on which element to target? The obvious solution is to set a class or id on the ul
element, but there's another solution which might be more convenient in some cases, which brings me to...
Using the universal selector
Depending on the situation, and whether you care about IE6 or not, you can use the universal selector to target the element you want.
Consider you have the following markup:
<body>
<article>
<header>
<h1>...</h1>
<p>...</p>
</header>
...
...and you want to style the p
that is in header
, you would do this in the normal case:
article header p { font-weight:bold }
But in IE, the article
, header
, h1
and p
elements are all siblings, so the selector wouldn't match.
So then one would expect this to match, but it doesn't (IE doesn't allow selecting unknown elements using type selectors):
article + header + h1 + p { font-weight:bold }
However, this matches:
body > * + * + h1 + p { font-weight:bold }
Using noscript
The above techniques shouldn't mess up other browsers (or IE when scripting is enabled), however if you prefer (or if something would screw up) you can use a separate style sheet for IE when scripting is disabled by just using the following markup:
<head>
<!--[if IE]>
<noscript><link rel="stylesheet" href="ie-noscript.css"></noscript>
<![endif]-->
...
Conclusion
The above techniques might not be very scalable or might well impact maintanence, but the point of this article is to show that it is possible to use the new elements while still supporting IE with scripting disabled.
Thanks for posting these additional approaches; good to keep in mind. If I used the universal selector, however, I would loathe to lose the newfound readability of HTML5’s semantic elements in selectors (as you hinted at). Likewise, if I targeted other elements for styling I’d probably have to add in superfluous markup.
Another option to serving HTML5 would be to do content-negotiation for MSIE so that all HTML5 block elements get replaced with
divs and inline elements with
span
s, inserting the original HTML5 element name into the class name. For example:<article id="foo" class="bar">
would become:
<div id="foo" class="bar html5-article">
And then a stylesheet could have a selector like this:
article.bar, div.html5-article.bar
or, of course
article#foo, div#foo
At Shepherd Interactive, we’ve used such an approach in several projects and have made available a WordPress plugin that does the element-substitution for IE6 visitors: http://shepherd-interactive.googlecode.com/svn/trunk/wp-plugins/xhtml5-support/xhtml5-support.php
[…] Das hier aber angeblich schon: […]
I recently started doing something similar to what Weston suggests on my own blog, except just Firefox 2 and older (so I can continue serving pages as HTML). Wish I’d know about that plug-in though, probably would have saved me hours of work!
For now I’m using the JS trick for IE, though I might switch that at a later point too.
[…] he has a new post that shows us what to do with no script: There are some tricks to work around the broken DOM and limited styling in […]
[…] trage das hier mal der Vollständigkeit halber mal nach: im WHATWG Blog gibt es eine Anleitung, wie man die neuen HTML5-Elemente für den IE stylen kann, wenn Javascript abgeschaltet ist. (Wie es mit JS hatten wir […]
[…] Wie man all das zusammen mit der Javascript-Lösung einsetzt, erklärt das WHATWG-Blog. […]
It hit me that tip #1 applies to Firefox 2 as well, which closes unknown elements when hitting a start tag of a block, so that e.g.
<article><h1>…</h1>
…becomes:
<article></article><h1>…</h1>
[…] have previously talked about how to get Internet Explorer to play ball when using the new HTML5 elements, but today I’m […]
Rather than negotiating
to
Why not set the article element with a class of article, and substitute a div with a class of article for MSIE, and then style for the class? Makes for simpler CSS.
But until I’m sure that Google is going to care, I’m leaving HTML5 well alone, just for maintenance reasons. However we are using the html5 element names (section, nav, article, header, footer, video, audio, menu) as our div id’s to facilitate content negotiation for *newer* browsers…
@Weston
I think the following:
article.bar, div.bar
is safer than:
article.bar, div.html5-article.bar
because the latter creates selectors with different specificity.
@weston & @thierry why not just do .bar instead of article.bar, div.bar ??