Archive for the ‘Elements’ Category

Implementation progress on the HTML5 <ruby> element

Friday, November 13th, 2009

If you don't know what the HTML5 ruby element is, you might want to take a minute to first read the section about the ruby element in the HTML5 specification and/or the Wikipedia article on ruby characters. To quote from the HTML5 description of the ruby element:

The ruby element allows one or more spans of phrasing content to be marked with ruby annotations. Ruby annotations are short runs of text presented alongside base text, primarily used in East Asian typography as a guide for pronunciation or to include other annotations. In Japanese, this form of typography is also known as furigana.

I give a specific example further down, but for now I want to first say that the really great news about the ruby element is that last week, Google Chrome developer Roland Steiner checked in a change (r50495, and see also related bug 28420) that adds ruby support to the trunk of the WebKit source repository, thus making the ruby feature available in WebKit nightlies and Chrome dev-channel releases.

A simple example

The following is a simple example of what you can do with the ruby element; make sure to view it in a recent WebKit nightly or Chrome dev-channel release. Note that the text is an excerpt from the source of a ruby-annotated online copy of the short story Run, Melos, Run by the writer Osamu Dazai, which I came across by way of Piro's info page for his XHTML Ruby add-on for Firefox (and which I mention a bit more about further below).

きのうの豪雨で山の水源地は<ruby>氾濫<rp>(</rp>
<rt>はんらん</rt><rp>)</rp></ruby>し、濁流
<ruby>滔々<rp>(</rp><rt>とうとう</rt><rp>)</rp>
</ruby>と下流に 集り、猛勢一挙に橋を破壊し、どうどうと 
響きをあげる激流が、<ruby>木葉微塵<rp>(</rp>
<rt>こっぱみじん</rt><rp>)</rp></ruby>に<ruby>橋桁
<rp>(</rp><rt>はしげた</rt><rp>)</rp></ruby>
を跳ね飛ばしていた。

If you don't happen to have Japanese fonts installed, here's a screenshot of the source for reference:

ruby source markup

Notice that the actual annotative ruby text (which I've highlighted in yellow in the source just for the sake of emphasis) is marked up using the rt element as a child of the ruby element, and the text being annotated is the node that's a previous sibling to that rt content as a child of the ruby element. The final new element in the mix is the rp element, which is simply a way to mark up the annotative ruby text with parenthesis, for graceful fallback in browsers that don't support ruby.

So here's the rendered view of that same text:

見よ、前方の川を。きのうの豪雨で山の水源地は氾濫はんらんし、濁流滔々とうとうと下流に集り、猛勢一挙に橋を破壊し、どうどうと響きをあげる激流が、木葉微塵こっぱみじん橋桁はしげたを跳ね飛ばしていた。

And here is a screenshot of how it should look in a recent WebKit nightly or Chrome dev-channel release:

ruby rendered view

Notice that the annotative ruby text is displayed above the ruby base it annotates. If you instead view this page in a browser that doesn't support the ruby feature, you'll see that the ruby text is just shown inline, in parenthesis following the ruby base it annotates. So the feature falls back gracefully in older browsers.

Support in other browsers

Current versions of Microsoft Internet Explorer also have native support for ruby, and you can also get ruby support in Firefox by installing Piro's XHTML Ruby add-on (and for more details, see his XHTML ruby add-on info page) — so we are well on the way to seeing the HTML5 ruby feature supported across a range of browsers. If you're not accustomed to reading printed books and magazines and such in Japanese, that might not sound like such a big deal. But for authors and developers and content providers in Japan who want to finally be able to use on the Web this very common feature of Japanese page layout from the print world, getting ruby support into another major browser engine is a huge win, and something to be very excited about.

Posted in Browsers, Elements | 3 Comments »

<section> is not just a “semantic <div>”

Thursday, March 19th, 2009

HTML 5 introduces new elements like <section>, <article> and <footer> for structuring the content in your webpages. They can be employed in many situations where <div> is used today and should help you make more readable, maintainable, HTML source. But if you just go through your document and blindly replace all the <div>s with <section>s you are doing it wrong.

This is not just semantic nit-picking, there is a practical reason to use these elements correctly.

In HTML 5, there is an algorithm for constructing an outline view of documents. This can be used, for example by AT, to help a user navigate through a document. And <section> and friends are an important part of this algorithm. Each time you nest a <section>, you increase the outline depth by 1 (in case you are wondering what the advantages of this model are compared to the traditional <h1>-<h6> model, consider a web based feedreader that wants to integrate the document structure of the syndicated content with that of the surrounding site. In HTML 4 this means parsing all the content and renumbering all the headings. In HTML5 the headings end up at the right depth for free). So a document like the following:


<body>
  <h1>This is the main header</h1>
  <section>
    <h1>This is a subheader</h1>
    <section>
      <h1>This is a subsubheader</h1>
    </section>
  </section>
  <section>
    <h1>This is a second subheader</h1>
  </section>
</body>

has an outline like:

This is the main header
+--This is a subheader
    +--This is a subsubheader
+--This is a second subheader

If you just blindly convert all the <div>s on your pages to <sections> it's pretty unlikely your page will have the outline you expected. And, apart from being a semantic faux-pas, this will confuse the hell out of people who rely on headings for navigation.

Hopefully, in time, we will get tools that make this kind of mistake obvious and CSS support for selecting headings based on depth. Until then remember <section> is not just a semantic <div>

Posted in Elements, Tutorials | 24 Comments »

Supporting New Elements in Firefox 2

Wednesday, March 18th, 2009

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.)

Posted in Browsers, DOM, Elements | 17 Comments »

Styling HTML5 markup in IE without script

Saturday, January 17th, 2009

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:

  1. Know what the DOM looks like and target other elements than the new elements for styling.
  2. Use the universal selector (*) to target the right element.
  3. 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.

Posted in Browsers, DOM, Elements | 11 Comments »

Supporting New Elements in IE

Wednesday, January 7th, 2009

Internet Explorer poses a small challenge when it comes to making use of the new elements introduced in HTML5. Among others, these include elements like section, article, header and footer. The problem is that due to the way parsing works in IE, these elements are not recognised properly and result in an anomalous DOM representation.

To illustrate, consider this simple document fragment:

<body>
  <section>
    <p>This is an example</p>
  </section>
</body>

Strangely, IE 6, 7 and 8 all fail to parse the section element properly and the resulting DOM looks like this.

Notice how IE actually creates 2 empty elements. One named SECTION and the other named /SECTION. Yes, it really is parsing the end tag as a start tag for an unknown empty element.

There is a handy workaround available to address this problem, which was first revealed in a comment by Sjoerd Visscher. The basic concept is that by using document.createElement(tagName) to create each of the unknown elements, the parser in IE then recognises those elements and parses them in a more reasonable and useful way. e.g. By using the following script:

document.createElement("section");

The resulting DOM for the fragment given above looks like this:

This same technique works for all unknown elements in IE 6, 7 and 8. Note that there is a known bug that prevented this from working in IE 8 beta 2, but this has since been resolved in the latest non-public technical preview.

For convenience, Remy Sharp has written and published a simple script that provides this enhancement for all new elements in the current draft of HTML5, which you can download and use.

This script is not needed for other browsers. Opera 9, Firefox 3 and Safari 3 all parse unknown elements in a more reasonable way by default. Note, however, that Firefox 2 does suffer from some related problems, for which there is unfortunately no known solution; but it is hoped that given the faster upgrade cycle for users of Firefox, relatively speaking compared with IE, Firefox 2 won't pose too much of a problem in the future.

Posted in Browsers, DOM, Elements, Events, Syntax | 25 Comments »