<?xml version="1.0" encoding="iso-8859-1"?><!-- generator="b2evolution/4.1.3" -->
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>boogdesign posts</title>
		<link>http://www.boogdesign.com/b2evo/index.php?blog=2</link>
		<atom:link rel="self" type="application/rss+xml" href="http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2" />
		<description>Web Design, Web Development, Gagdets and Technology</description>
		<language>en-UK</language>
		<docs>http://blogs.law.harvard.edu/tech/rss</docs>
		<admin:generatorAgent rdf:resource="http://b2evolution.net/?v=4.1.3"/>
		<ttl>60</ttl>
				<item>
			<title>Drag and Drop and Delegate</title>
			<link>http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2</link>
			<pubDate>Fri, 03 Jun 2011 13:51:00 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="main">Front End Web Development</category>
<category domain="alt">Blogging and Internet Culture</category>			<guid isPermaLink="false">369@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;HTML5 Drag and Drop has been popular topic recently on web tech blogs, a good example is &lt;a href=&quot;http://blogs.sitepoint.com/a-drag-and-drop-planning-board-with-html5/&quot;&gt;Alexis Goldstein&#039;s post on Sitepoint&lt;/a&gt; which I &lt;a href=&quot;https://github.com/robertc/DragNDrop_PlanningBoard/blob/2843ee68742fd3562c5acdde63da58f764abfea3/dragndrop.html&quot;&gt;converted to work in IE&lt;/a&gt;.  Fortunately for me this all coincided with spending a lot of time working on Drag and Drop for &lt;a href=&quot;http://www.manning.com/crowther/&quot;&gt;chapter 6 of my book&lt;/a&gt; and a project coming up at work where it was a natural fit.  So I&#039;ve been doing a lot of dragging and dropping in recent weeks, to the point where I started to feel like I knew as much about the practical implementation of the Drag and Drop API as any person living.&lt;/p&gt;

&lt;p&gt;Of course, whenever I start getting a bit full of myself something soon happens to make me feel like an idiot again.  In this case it&#039;s my continuing blind spot when it comes to DOM Event Delegation.  If you look again at &lt;a href=&quot;https://github.com/alexisgo/DragNDrop_PlanningBoard&quot;&gt;Alexis&#039; example&lt;/a&gt; you&#039;ll note that all the event handlers are bound directly to the elements where the events are expected to happen.  This is a common pattern in example code - it&#039;s a straightforward relationship for beginners to understand - but it&#039;s not really the best way to do it, and this post is going to explain why.  Let&#039;s review the code for the drop event:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#todo, #inprogress, #done&#039;).bind(&#039;drop&#039;, function(event) {
    var notecard = event.originalEvent.dataTransfer.getData(&quot;text/plain&quot;);
    event.target.appendChild(document.getElementById(notecard));
    event.preventDefault();
});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;What this code does is bind a drop handler to three separate elements specified by the IDs in the selector - &lt;code&gt;#todo, #inprogress, #done&lt;/code&gt;.  Now have a look at this screenshot of the original planning board in action:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/dnd/task-in-task.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/dnd/task-in-task-thumb.png&quot; alt=&quot;A task embedded within another task&quot; title=&quot;Click for full size image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The task &#039;Learn HTML5&#039; as been dropped directly inside the task &#039;Learn CSS3&#039; and the &#039;Learn CSS3&#039; task accepted the drop and ran the drop handler code despite not being mentioned above - why?  The answer is because of event delegation.  While in this particular case it may look like a bug, this is actually a very powerful and useful process.  Here&#039;s what&#039;s happening when the &#039;Learn HTML5&#039; task is dropped:&lt;/p&gt;&lt;ol&gt;
  &lt;li&gt;The drop event is fired on the &#039;Learn CSS3&#039; element&lt;/li&gt;
  &lt;li&gt;Because there is no drop handler, the event is passed up the document tree&amp;lt; to the parent element - in this case &lt;code&gt;#inprogress&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;There &lt;em&gt;is&lt;/em&gt; a drop handler on the &lt;code&gt;#inprogress&lt;/code&gt;, so that handler is run&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;This process is called event bubbling - the events rise up through the DOM tree like bubbles through water, and the consequence of the bubbling here is that the event is fired on the &#039;Learn CSS3&#039; element, which remains the target of the event, but it&#039;s processed by the event handler on the &lt;code&gt;#inprogress&lt;/code&gt; element.  Because the handler just says &#039;append the dragged element as a child of the event target&#039; the &#039;Learn HTML5&#039; element is added as the last child of &#039;Learn CSS3&#039;.&lt;/p&gt;

&lt;p&gt;Initially you might see this as a bug, but really it&#039;s an opportunity.  As long as we deal with this unwanted side effect we&#039;re freed from having to attach event handlers to every single element.  If this doesn&#039;t seem like a huge gain, consider these two scenarios:&lt;/p&gt;&lt;ol&gt;
  &lt;li&gt;You want to scale up to handle have a large number of draggable items and drop targets, into the thousands&lt;/li&gt;
  &lt;li&gt;You want to add and remove draggable items and drop targets dynamically&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;The first scenario was the one I found myself in with my work project - the drop targets were cells in a table, with over fifty columns and possibly hundreds of rows, and 30-50% of those cells had draggable items in.  When I started with the naive approach of binding a handler to each item it took a second or two to run the initialisation code in the good browsers (in IE8 it took nearly 30 seconds...).  Event delegation helps in this scenario because the number of events you have to bind is equal to the number of events you want to capture, not the number of elements you want to capture them on.&lt;/p&gt;

&lt;p&gt;It&#039;s unlikely an agile planning board is going to end up with that many elements though - if it does I suspect there&#039;s a good chance you&#039;re not really being agile, but the second scenario is more likely to come up.  The tasks and the available resources will likely change from sprint to sprint, you may also want to add in some extra statuses.  With the current code, every time you want to add an element you will have to attach all the relevant event handlers to it (even if &lt;a href=&quot;http://api.jquery.com/clone/&quot;&gt;jQuery makes that easy for you&lt;/a&gt;, that could still be a lot of overhead).  If you forget to do that in a particular code path then strange bugs will likely ensue, which is a shame when all you really want is for the new elements to execute the exact same handlers as all the existing ones.  Let&#039;s look at how easy this all becomes if you &lt;em&gt;don&#039;t&lt;/em&gt; try to bind event handlers to every single element.&lt;/p&gt;

&lt;p&gt;First, some adjustments to the markup.  Because there&#039;ll now (potentially) be multiple rows on the board we can&#039;t use &lt;code&gt;id&lt;/code&gt; attributes to distinguish them so they&#039;ll have to be a class.  We&#039;ll also add a &#039;row title&#039; for the developer name, and &lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div id=&amp;quot;board&amp;quot;&amp;gt;
    &amp;lt;div id=&amp;quot;rob&amp;quot;&amp;gt;
        &amp;lt;h1 class=&amp;quot;title&amp;quot;&amp;gt;Rob&amp;lt;/h1&amp;gt;
        &amp;lt;div class=&amp;quot;todo droptarget&amp;quot;&amp;gt;
            &amp;lt;h2 class=&amp;quot;title&amp;quot;&amp;gt;To Do&amp;lt;/h1&amp;gt;
            &amp;lt;a id=&amp;quot;item1&amp;quot; draggable=&amp;quot;true&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
                &amp;lt;div class=&amp;quot;cardTitle&amp;quot;&amp;gt;
                    Learn HTML5
                &amp;lt;/div&amp;gt;
            &amp;lt;/a&amp;gt;
            &amp;lt;a id=&amp;quot;item2&amp;quot; draggable=&amp;quot;true&amp;quot; href=&amp;quot;#&amp;quot;&amp;gt;
                &amp;lt;div class=&amp;quot;cardTitle&amp;quot;&amp;gt;
                    Learn CSS3
                &amp;lt;/div&amp;gt;
            &amp;lt;/a&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;inprogress droptarget&amp;quot;&amp;gt;
            &amp;lt;h2 class=&amp;quot;title&amp;quot;&amp;gt;In Progress&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
        &amp;lt;div class=&amp;quot;done droptarget&amp;quot;&amp;gt;
            &amp;lt;h2 class=&amp;quot;title&amp;quot;&amp;gt;Done&amp;lt;/h1&amp;gt;
        &amp;lt;/div&amp;gt;
    &amp;lt;/div&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;I&#039;ve also added a class &lt;code&gt;droptarget&lt;/code&gt; to make life easier in the event handlers.  Those event handlers will, of course, have to change.  Here&#039;s a before and after of the &lt;code&gt;dragstart&lt;/code&gt; handler:&lt;/p&gt;&lt;div style=&quot;display:table;width:100%;&quot;&gt;
&lt;div style=&quot;display:table-cell;width:50%;&quot;&gt;&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote style=&quot;margin:0;padding:1px;width:98%;&quot;&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#item1, #item2&#039;).bind(&#039;dragstart&#039;,
  function(event) {
    event.originalEvent.dataTransfer.setData(
        &quot;Text&quot;, 
        event.target.getAttribute(&#039;id&#039;)
    );
});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;div style=&quot;display:table-cell;width:50%;&quot;&gt;&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote style=&quot;margin:0;padding:1px;width:98%;&quot;&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#board&#039;).bind(&#039;dragstart&#039;,
  function(event) {
    event.originalEvent.dataTransfer.setData(
        &quot;Text&quot;, 
        $(event.target).closest(&#039;a[id]&#039;).attr(&#039;id&#039;)
    );
});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The first, and most important, change is that the event is now attached to the &lt;code&gt;#board&lt;/code&gt; element instead of to each individual draggable item.  The second change is instead of assuming the event target is the planning item the code now looks for the closest parent element which matches what the draggable element is expected to look like.  The next event to consider is &lt;code&gt;dragover&lt;/code&gt;, here things are slightly more complicated:&lt;/p&gt;&lt;div style=&quot;display:table;width:100%;&quot;&gt;
&lt;div style=&quot;display:table-cell;width:50%;&quot;&gt;&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote style=&quot;margin:0;padding:1px;width:98%;&quot;&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#todo, #inprogress, #done&#039;).bind(&#039;dragover&#039;, 
    function(event) {
        event.preventDefault();
});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;div style=&quot;display:table-cell;width:50%;&quot;&gt;&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote style=&quot;margin:0;padding:1px;width:98%;&quot;&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#board&#039;).bind(&#039;dragover&#039;, function(event) {
    if ($(event.target)
          .closest(&#039;.droptarget&#039;)
          .hasClass(&#039;droptarget&#039;)) {
	      event.preventDefault();
    }
});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Now that the handler is being attached to &lt;code&gt;#board&lt;/code&gt; every element will trigger the &lt;code&gt;dragover&lt;/code&gt;droptarget class added earlier.  Finally let&#039;s consider the &lt;code&gt;drop&lt;/code&gt; event:&lt;/p&gt;&lt;div style=&quot;display:table;width:100%;&quot;&gt;
&lt;div style=&quot;display:table-cell;width:50%;&quot;&gt;&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote style=&quot;margin:0;padding:1px;width:98%;&quot;&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#todo, #inprogress, #done&#039;)
  .bind(&#039;drop&#039;, 
    function(event) {
        var notecard = event
                .originalEvent
                .dataTransfer.getData(&quot;Text&quot;);
        event.target.appendChild(
            document.getElementById(notecard)
        );
        event.preventDefault();
  });&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;div style=&quot;display:table-cell;width:50%;&quot;&gt;&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote style=&quot;margin:0;padding:1px;width:98%;&quot;&gt;&lt;pre&gt;&lt;code&gt;$(&#039;#board&#039;).bind(&#039;drop&#039;, function(event) {
    var notecard = event
            .originalEvent
            .dataTransfer.getData(&quot;Text&quot;);
    var drop = $(event.target).closest(&#039;.droptarget&#039;);
    drop.append($(&#039;#&#039; + notecard));
    event.preventDefault();
});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Although every element which is a descendant of &lt;code&gt;#board&lt;/code&gt; could potentially trigger this event, in practice it&#039;s only ever going to be the ones that triggered the &lt;code&gt;event.preventDefault()&lt;/code&gt; on the &lt;code&gt;dragover&lt;/code&gt; event - anything with class &lt;code&gt;.droptarget&lt;/code&gt; or it&#039;s descendants.  Instead of just assuming the target is where the dropped element has to be attached the closest ancestor with the right class is used, so we never end up with dropped tasks getting appended inside other tasks.&lt;/p&gt;

&lt;p&gt;I think you&#039;ll agree it isn&#039;t really much more difficult to write the event handlers in such a way that they take advantage of event bubbling and so only need to be attached to a single element.  Now that these changes have been made it&#039;s possible to add further developers, statuses or tasks just by generating and appending the appropriate HTML - no need to loop through the new elements and attach all the correct event handlers.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/DragNDrop_PlanningBoard/dragndrop.html&quot;&gt;This example page&lt;/a&gt; adds several buttons for dynamically updating the planning board, just to show how easy it is.  The code is also &lt;a href=&quot;https://github.com/robertc/DragNDrop_PlanningBoard&quot;&gt;available on github&lt;/a&gt;.&lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=drag-n-drop&quot;&gt;drag-n-drop&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=html5&quot;&gt;html5&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=javascript&quot;&gt;javascript&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;Drag and Drop and Delegate&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;amp;title=Drag and Drop and Delegate&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;amp;title=Drag and Drop and Delegate&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;amp;t=Drag and Drop and Delegate&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=Drag and Drop and Delegate&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;amp;t=Drag and Drop and Delegate&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Drag and Drop and Delegate&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;amp;Title=Drag and Drop and Delegate&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=Drag and Drop and Delegate+http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>HTML5 Drag and Drop has been popular topic recently on web tech blogs, a good example is <a href="http://blogs.sitepoint.com/a-drag-and-drop-planning-board-with-html5/">Alexis Goldstein's post on Sitepoint</a> which I <a href="https://github.com/robertc/DragNDrop_PlanningBoard/blob/2843ee68742fd3562c5acdde63da58f764abfea3/dragndrop.html">converted to work in IE</a>.  Fortunately for me this all coincided with spending a lot of time working on Drag and Drop for <a href="http://www.manning.com/crowther/">chapter 6 of my book</a> and a project coming up at work where it was a natural fit.  So I've been doing a lot of dragging and dropping in recent weeks, to the point where I started to feel like I knew as much about the practical implementation of the Drag and Drop API as any person living.</p>

<p>Of course, whenever I start getting a bit full of myself something soon happens to make me feel like an idiot again.  In this case it's my continuing blind spot when it comes to DOM Event Delegation.  If you look again at <a href="https://github.com/alexisgo/DragNDrop_PlanningBoard">Alexis' example</a> you'll note that all the event handlers are bound directly to the elements where the events are expected to happen.  This is a common pattern in example code - it's a straightforward relationship for beginners to understand - but it's not really the best way to do it, and this post is going to explain why.  Let's review the code for the drop event:</p><blockquote><pre><code>$('#todo, #inprogress, #done').bind('drop', function(event) {
    var notecard = event.originalEvent.dataTransfer.getData("text/plain");
    event.target.appendChild(document.getElementById(notecard));
    event.preventDefault();
});</code></pre></blockquote><p>What this code does is bind a drop handler to three separate elements specified by the IDs in the selector - <code>#todo, #inprogress, #done</code>.  Now have a look at this screenshot of the original planning board in action:</p>

<p><a href="http://www.boogdesign.com/images/blog/dnd/task-in-task.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/dnd/task-in-task-thumb.png" alt="A task embedded within another task" title="Click for full size image" /></a></p>

<p>The task 'Learn HTML5' as been dropped directly inside the task 'Learn CSS3' and the 'Learn CSS3' task accepted the drop and ran the drop handler code despite not being mentioned above - why?  The answer is because of event delegation.  While in this particular case it may look like a bug, this is actually a very powerful and useful process.  Here's what's happening when the 'Learn HTML5' task is dropped:</p><ol>
  <li>The drop event is fired on the 'Learn CSS3' element</li>
  <li>Because there is no drop handler, the event is passed up the document tree&lt; to the parent element - in this case <code>#inprogress</code></li>
  <li>There <em>is</em> a drop handler on the <code>#inprogress</code>, so that handler is run</li>
</ol><p>This process is called event bubbling - the events rise up through the DOM tree like bubbles through water, and the consequence of the bubbling here is that the event is fired on the 'Learn CSS3' element, which remains the target of the event, but it's processed by the event handler on the <code>#inprogress</code> element.  Because the handler just says 'append the dragged element as a child of the event target' the 'Learn HTML5' element is added as the last child of 'Learn CSS3'.</p>

<p>Initially you might see this as a bug, but really it's an opportunity.  As long as we deal with this unwanted side effect we're freed from having to attach event handlers to every single element.  If this doesn't seem like a huge gain, consider these two scenarios:</p><ol>
  <li>You want to scale up to handle have a large number of draggable items and drop targets, into the thousands</li>
  <li>You want to add and remove draggable items and drop targets dynamically</li>
</ol><p>The first scenario was the one I found myself in with my work project - the drop targets were cells in a table, with over fifty columns and possibly hundreds of rows, and 30-50% of those cells had draggable items in.  When I started with the naive approach of binding a handler to each item it took a second or two to run the initialisation code in the good browsers (in IE8 it took nearly 30 seconds...).  Event delegation helps in this scenario because the number of events you have to bind is equal to the number of events you want to capture, not the number of elements you want to capture them on.</p>

<p>It's unlikely an agile planning board is going to end up with that many elements though - if it does I suspect there's a good chance you're not really being agile, but the second scenario is more likely to come up.  The tasks and the available resources will likely change from sprint to sprint, you may also want to add in some extra statuses.  With the current code, every time you want to add an element you will have to attach all the relevant event handlers to it (even if <a href="http://api.jquery.com/clone/">jQuery makes that easy for you</a>, that could still be a lot of overhead).  If you forget to do that in a particular code path then strange bugs will likely ensue, which is a shame when all you really want is for the new elements to execute the exact same handlers as all the existing ones.  Let's look at how easy this all becomes if you <em>don't</em> try to bind event handlers to every single element.</p>

<p>First, some adjustments to the markup.  Because there'll now (potentially) be multiple rows on the board we can't use <code>id</code> attributes to distinguish them so they'll have to be a class.  We'll also add a 'row title' for the developer name, and </p><blockquote><pre><code>&lt;div id=&quot;board&quot;&gt;
    &lt;div id=&quot;rob&quot;&gt;
        &lt;h1 class=&quot;title&quot;&gt;Rob&lt;/h1&gt;
        &lt;div class=&quot;todo droptarget&quot;&gt;
            &lt;h2 class=&quot;title&quot;&gt;To Do&lt;/h1&gt;
            &lt;a id=&quot;item1&quot; draggable=&quot;true&quot; href=&quot;#&quot;&gt;
                &lt;div class=&quot;cardTitle&quot;&gt;
                    Learn HTML5
                &lt;/div&gt;
            &lt;/a&gt;
            &lt;a id=&quot;item2&quot; draggable=&quot;true&quot; href=&quot;#&quot;&gt;
                &lt;div class=&quot;cardTitle&quot;&gt;
                    Learn CSS3
                &lt;/div&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class=&quot;inprogress droptarget&quot;&gt;
            &lt;h2 class=&quot;title&quot;&gt;In Progress&lt;/h1&gt;
        &lt;/div&gt;
        &lt;div class=&quot;done droptarget&quot;&gt;
            &lt;h2 class=&quot;title&quot;&gt;Done&lt;/h1&gt;
        &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;</code></pre></blockquote><p>I've also added a class <code>droptarget</code> to make life easier in the event handlers.  Those event handlers will, of course, have to change.  Here's a before and after of the <code>dragstart</code> handler:</p><div style="display:table;width:100%;">
<div style="display:table-cell;width:50%;"><p><strong>Before</strong></p>
<blockquote style="margin:0;padding:1px;width:98%;"><pre><code>$('#item1, #item2').bind('dragstart',
  function(event) {
    event.originalEvent.dataTransfer.setData(
        "Text", 
        event.target.getAttribute('id')
    );
});</code></pre></blockquote></div>
<div style="display:table-cell;width:50%;"><p><strong>After</strong></p>
<blockquote style="margin:0;padding:1px;width:98%;"><pre><code>$('#board').bind('dragstart',
  function(event) {
    event.originalEvent.dataTransfer.setData(
        "Text", 
        $(event.target).closest('a[id]').attr('id')
    );
});</code></pre></blockquote></div>
</div><p>The first, and most important, change is that the event is now attached to the <code>#board</code> element instead of to each individual draggable item.  The second change is instead of assuming the event target is the planning item the code now looks for the closest parent element which matches what the draggable element is expected to look like.  The next event to consider is <code>dragover</code>, here things are slightly more complicated:</p><div style="display:table;width:100%;">
<div style="display:table-cell;width:50%;"><p><strong>Before</strong></p>
<blockquote style="margin:0;padding:1px;width:98%;"><pre><code>$('#todo, #inprogress, #done').bind('dragover', 
    function(event) {
        event.preventDefault();
});</code></pre></blockquote></div>
<div style="display:table-cell;width:50%;"><p><strong>After</strong></p>
<blockquote style="margin:0;padding:1px;width:98%;"><pre><code>$('#board').bind('dragover', function(event) {
    if ($(event.target)
          .closest('.droptarget')
          .hasClass('droptarget')) {
	      event.preventDefault();
    }
});</code></pre></blockquote></div>
</div><p>Now that the handler is being attached to <code>#board</code> every element will trigger the <code>dragover</code>droptarget class added earlier.  Finally let's consider the <code>drop</code> event:</p><div style="display:table;width:100%;">
<div style="display:table-cell;width:50%;"><p><strong>Before</strong></p>
<blockquote style="margin:0;padding:1px;width:98%;"><pre><code>$('#todo, #inprogress, #done')
  .bind('drop', 
    function(event) {
        var notecard = event
                .originalEvent
                .dataTransfer.getData("Text");
        event.target.appendChild(
            document.getElementById(notecard)
        );
        event.preventDefault();
  });</code></pre></blockquote></div>
<div style="display:table-cell;width:50%;"><p><strong>After</strong></p>
<blockquote style="margin:0;padding:1px;width:98%;"><pre><code>$('#board').bind('drop', function(event) {
    var notecard = event
            .originalEvent
            .dataTransfer.getData("Text");
    var drop = $(event.target).closest('.droptarget');
    drop.append($('#' + notecard));
    event.preventDefault();
});</code></pre></blockquote></div>
</div><p>Although every element which is a descendant of <code>#board</code> could potentially trigger this event, in practice it's only ever going to be the ones that triggered the <code>event.preventDefault()</code> on the <code>dragover</code> event - anything with class <code>.droptarget</code> or it's descendants.  Instead of just assuming the target is where the dropped element has to be attached the closest ancestor with the right class is used, so we never end up with dropped tasks getting appended inside other tasks.</p>

<p>I think you'll agree it isn't really much more difficult to write the event handlers in such a way that they take advantage of event bubbling and so only need to be attached to a single element.  Now that these changes have been made it's possible to add further developers, statuses or tasks just by generating and appending the appropriate HTML - no need to loop through the new elements and attach all the correct event handlers.</p>

<p><a href="http://www.boogdesign.com/examples/DragNDrop_PlanningBoard/dragndrop.html">This example page</a> adds several buttons for dynamically updating the planning board, just to show how easy it is.  The code is also <a href="https://github.com/robertc/DragNDrop_PlanningBoard">available on github</a>.</p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=drag-n-drop">drag-n-drop</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=html5">html5</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=javascript">javascript</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2')+'&amp;title='+encodeURIComponent('Drag and Drop and Delegate'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;title=Drag and Drop and Delegate" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;title=Drag and Drop and Delegate&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;t=Drag and Drop and Delegate" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=Drag and Drop and Delegate&amp;url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;t=Drag and Drop and Delegate" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Drag and Drop and Delegate&amp;u=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2&amp;Title=Drag and Drop and Delegate" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=Drag and Drop and Delegate+http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/drag-and-drop-and-delegate?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=369</wfw:commentRss>
		</item>
				<item>
			<title>IE10 and the Future of CSS Layout</title>
			<link>http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2</link>
			<pubDate>Wed, 20 Apr 2011 00:16:00 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="alt">Front End Web Development</category>
<category domain="main">Standards, HTML and CSS</category>
<category domain="alt">Blogging and Internet Culture</category>			<guid isPermaLink="false">367@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;Last week &lt;a href=&quot;http://blogs.msdn.com/b/ie/archive/2011/04/12/native-html5-first-ie10-platform-preview-available-for-download.aspx&quot;&gt;the first developer preview of IE10 was released&lt;/a&gt;.  Among &lt;a href=&quot;http://msdn.microsoft.com/en-us/ie/gg192966&quot;&gt;several experimental features&lt;/a&gt; included were the first Microsoft implementations of &lt;a href=&quot;http://www.w3.org/TR/css3-flexbox/&quot;&gt;CSS3 Flexible Box Layout Module&lt;/a&gt; and &lt;a href=&quot;http://dev.w3.org/csswg/css3-grid-align/&quot;&gt;CSS3 Grid Alignment&lt;/a&gt;.  These are possibly the most exciting things to be added to CSS since drop shadows...&lt;/p&gt;

&lt;p&gt;First up the flexible box layout module, or flexboxes.  This has already been implemented in &lt;a href=&quot;http://hacks.mozilla.org/2010/04/the-css-3-flexible-box-model/&quot;&gt;Firefox and WebKit&lt;/a&gt;, but &lt;a href=&quot;http://lists.w3.org/Archives/Public/www-style/2011Jan/0186.html&quot;&gt;that version of flexboxes isn&#039;t very intuitive&lt;/a&gt;, and the draft has since seen a lot of updates.  Interestingly, IE10PR1 implements the same version of the spec as Firefox and WebKit but with one important addition: &lt;a href=&quot;http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#multiple&quot;&gt;multi-line flexboxes&lt;/a&gt;.  For me the multi-line properties are what make flexboxes worthwhile for layout, otherwise nearly everything you might currently want to achieve can be done just as easily (and with better backwards compatibility) with &lt;code&gt;display: table-cell&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This is the sort of thing that multi-line flexboxes are useful for, it&#039;s a layout typical of shopping and photo gallery sites:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-800.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-800-thumb.png&quot; alt=&quot;A multiline flexbox layout at 800 pixels width&quot; title=&quot;Click for full size image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here&#039;s what my markup looks like, nothing more complex than a list with sixty items in it:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;ul&amp;gt;
    &amp;lt;li&amp;gt;1&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;2&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;3&amp;lt;/li&amp;gt;
    ...
    &amp;lt;li&amp;gt;59&amp;lt;/li&amp;gt;
    &amp;lt;li&amp;gt;60&amp;lt;/li&amp;gt;
&amp;lt;/ul&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;And here&#039;s the CSS, the key things to look out for are the &lt;code&gt;display: -ms-box&lt;/code&gt; and the &lt;code&gt;-ms-box-lines&lt;/code&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;body {
    width: 90%;
    margin: 0 5%;
}
ul {
    display: -ms-box;
    -ms-box-lines: multiple;
    list-style: none;
    width: auto;
    padding: 10px;
    border: 4px dashed #000;
}
li {
    display: block;
    -ms-box-flex: 1;
    padding: 1em;
    margin: 0.5em;
    min-width: 3em;
    border: 4px dashed #000;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;You may be thinking that&#039;s not a hard thing to pull off, so let me show you the same page, in an 800 pixel wide browser above, at 640 and 480 pixels:&lt;/p&gt;
&lt;div&gt;&lt;div style=&quot;display: table-cell;&quot;&gt;
&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-640.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-640-thumb.png&quot; alt=&quot;A multiline flexbox layout at 640 pixels width&quot; title=&quot;Click for full size image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style=&quot;display: table-cell;&quot;&gt;
&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-480.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-480-thumb.png&quot; alt=&quot;A multiline flexbox layout at 480 pixels width&quot; title=&quot;Click for full size image&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The number of cells across adjusts to match the width available, but, because these are flexboxes, the width of the elements themselves also adjust so that they always exactly fit the available width.  This is unique among our current alternatives:&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;If you were using floats or inline blocks then you&#039;d have to set each element to a fixed width, meaning the container would have to be a fixed width so that the elements could fill it exactly.  You&#039;d have to use media queries to assign different fixed widths to the container to change the items per row according to screen resolution.&lt;/li&gt;
&lt;li&gt;If you were using a &lt;a href=&quot;http://blog.whatwg.org/weekly-layout-table&quot;&gt;layout table&lt;/a&gt; or display: table-cell then, although the elements would expand to fit exactly, the number of items per row would be fixed by the markup.&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;However, nothing is perfect.  &lt;a href=&quot;http://www.boogdesign.com/examples/grids/flex-layout-1.html&quot;&gt;My multi-line flexbox example&lt;/a&gt; has a total of 60 elements, and I picked this number because it is an exact multiple of 2, 3, 4, 5 and 6 (it&#039;s the &lt;a href=&quot;http://en.wikipedia.org/wiki/Polynomial_expansion&quot;&gt;expansion&lt;/a&gt; of them if I&#039;ve got my maths terms right&lt;img src=&quot;http://www.boogdesign.com/b2evo/rsc/smilies/icon_question.gif&quot; title=&quot;&amp;amp;amp;#58;&amp;amp;amp;#63;&amp;amp;amp;#58;&quot; alt=&quot;&amp;amp;amp;#58;&amp;amp;amp;#63;&amp;amp;amp;#58;&quot; class=&quot;middle&quot; width=&quot;15&quot; height=&quot;15&quot; /&gt;) - meaning that the number of elements will fill the grid whether there&#039;s 2, 3, 4, 5 or 6 elements per row.  If there&#039;s a less perfect number, say 24, then the grid will look a little strange on the last row:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1a-640.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/flexbox-1a-640-thumb.png&quot; alt=&quot;A multiline flexbox layout at 640 pixels width with only 24 elements&quot; title=&quot;Click for full size image&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think the &lt;a href=&quot;http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#multiple-alignment&quot;&gt;&lt;code&gt;box-align&lt;/code&gt;&lt;/a&gt; property should help with this, but I couldn&#039;t make it work in IE10PR1.&lt;/p&gt;

&lt;p&gt;So, multi-line flexboxes could be a useful addition to the CSS toolbox when everyone gets round to upgrading to IE10, but, cool as they are, that&#039;s not the coolest experimental CSS layout implementation in IE10PR1.  There have been a few grid and template based CSS proposals over the years but, apart from an incomplete JavaScript library for CSS Template Layout, none of them have ever been implemented in a major desktop browser.  That is until last week, when IE10PR1 implemented &lt;a href=&quot;http://www.interoperabilitybridges.com/css3-grid-align/&quot;&gt;Microsoft&#039;s own CSS Grid Align proposal from October 2010&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;I want you to reflect, now, on all the fun you&#039;ve had over the last ten years constructing CSS layouts of three equal height columns, with a header and footer, and making them work in IE6.  Layouts something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-1.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-1-thumb.png&quot; alt=&quot;A three column layout with header and footer&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Are you remembering all the fun you had?  Good, now look at this markup and contemplate how you&#039;d turn it into a three column layout:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;header&amp;gt;Header&amp;lt;/header&amp;gt;
&amp;lt;aside class=&quot;b&quot;&amp;gt;Side bar&amp;lt;/aside&amp;gt;
&amp;lt;article&amp;gt;I never am really satisfied...&amp;lt;/article&amp;gt;
&amp;lt;aside class=&quot;d&quot;&amp;gt;Side bar&amp;lt;/aside&amp;gt;
&amp;lt;footer&amp;gt;Footer&amp;lt;/footer&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now look at this CSS and start wishing the future would arrive soon:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;body {
    width: 90%;
    margin: 0 5%;
    display: -ms-grid;
    -ms-grid-columns: auto minmax(min-content, 1fr) auto;
    -ms-grid-rows: auto minmax(min-content, 1fr) auto;
}
article, aside, header, footer {
    margin: 1em;
    padding: 1em;
    outline: 4px dashed black;
}
header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
aside.b { -ms-grid-column: 1; -ms-grid-row: 2; }
article { -ms-grid-column: 2; -ms-grid-row: 2; }
aside.d { -ms-grid-column: 3; -ms-grid-row: 2; }
footer { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;That&#039;s it, seven declarations is all you need for that three column layout with CSS Grid Align.  For this first example I&#039;m going to step through the key points line by line:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;display: -ms-grid;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;This is the bit which declares we will use the grid layout manager on the children of this element, in the same way that the flexbox layout manager was declared above with &lt;code&gt;display: -ms-box&lt;/code&gt;.&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;-ms-grid-columns: auto minmax(min-content, 1fr) auto;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;This line defines three columns, the first and last will shrink to fit the content - that&#039;s the default behaviour, similar to a table.  The middle column will be a minimum of &lt;code&gt;min-content&lt;/code&gt;, which is basically the same as &lt;code&gt;auto&lt;/code&gt;, and a maximum of &lt;code&gt;1fr&lt;/code&gt; which is a &#039;fraction of available space&#039; - quite similar to a flex unit and, since there&#039;s only one fractional column, basically equivalent to all the available space.&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;-ms-grid-rows: auto minmax(min-content, 1fr) auto;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;We&#039;ll have three rows to go along with our three columns, I won&#039;t go over the individual values again.  Now the fun stuff:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Put the header in the first column of the first row, and make it span three columns.  That&#039;s it.  Really, it&#039;s that simple.  Let&#039;s just do one more:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;article { -ms-grid-column: 2; -ms-grid-row: 2; }&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Put the article in the second column and the second row.  And make me some coffee, white, no sugar.  Actually there isn&#039;t a CSS property for that yet, maybe CSS4...&lt;/p&gt;

&lt;p&gt;But it gets more cool than that.  In the example above the order of the elements in the markup matched up with the order they were placed into the grid, but it doesn&#039;t have to be that way:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-2.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-2-thumb.png&quot; alt=&quot;A three column layout with header and footer, with elements placed in a different order&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This amazing transformation was achieved without any changes in markup, just messing around with CSS:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;header { -ms-grid-column: 1; -ms-grid-row: 2; }
aside.b { -ms-grid-column: 2; -ms-grid-row: 2; }
article { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
aside.d { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }
footer { -ms-grid-column: 3; -ms-grid-row: 2; }&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;In &lt;a href=&quot;http://dev.w3.org/csswg/css3-grid-align/&quot;&gt;the current draft&lt;/a&gt; there&#039;s a &lt;code&gt;grid-cell-stacking&lt;/code&gt; property which will let you flow multiple elements into a single cell, but in the IE10PR1 implementation things just stack on top of each other:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3a.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3a-thumb.png&quot; alt=&quot;Multiple elements in cells not working&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a shame, because the markup is quite straightforward, I won&#039;t post all of it because this is already getting quite long (&lt;a href=&quot;http://www.boogdesign.com/examples/grids/grid-layout-3a.html&quot;&gt;have a look&lt;/a&gt;), but here&#039;s the nice bit:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;article:nth-child(2n+1) { -ms-grid-column: 1; }
article:nth-child(2n) { -ms-grid-column: 2; }&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The article elements are assigned to grid cells alternately, unfortunately it doesn&#039;t work yet.  However you can nest elements set to &lt;code&gt;display: -ms-grid&lt;/code&gt; inside each other:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3-thumb.png&quot; alt=&quot;A three column layout with header and footer&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have a &lt;a href=&quot;http://www.boogdesign.com/examples/grids/grid-layout-3.html&quot;&gt;look at the source code&lt;/a&gt; for that one, it gets pretty hairy, so rather than try and do that sort of thing it&#039;s probably best to use some wrapper elements like this:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-4.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-4-thumb.png&quot; alt=&quot;Grid Align with wrapper elements for cells&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, &lt;a href=&quot;http://www.boogdesign.com/examples/grids/grid-layout-4.html&quot;&gt;view the source code yourself&lt;/a&gt; to see how it&#039;s put together, but I think these things will be worth re-visiting in a later preview release.&lt;/p&gt;

&lt;p&gt;I&#039;m going to finish off with some &lt;a href=&quot;http://www.alistapart.com/articles/responsive-web-design/&quot;&gt;adaptive layout&lt;/a&gt;.  Grid Align is a great fit for this because of the complete independence of layout from source order.  Here&#039;s what I put together based off the previous example at 800 pixel width:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-800.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-800-thumb.png&quot; alt=&quot;An adaptive Grid Align at 800px width&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now here&#039;s the same page at 640 and 480 pixel widths:&lt;/p&gt;
&lt;div&gt;&lt;div style=&quot;display: table-cell;&quot;&gt;
&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-640.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-640-thumb.png&quot; alt=&quot;An adaptive Grid Align at 640px width&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/div&gt;&lt;div style=&quot;display: table-cell;&quot;&gt;
&lt;a href=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-480.png&quot;&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-480-thumb.png&quot; alt=&quot;An adaptive Grid Align at 480px width&quot; /&gt;&lt;/a&gt;
&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The markup is, of course, the same in each case:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;header&amp;gt;Header&amp;lt;/header&amp;gt;
&amp;lt;div id=&quot;sidebar&quot;&amp;gt;
    &amp;lt;aside&amp;gt;Side bar 1&amp;lt;/aside&amp;gt;
    &amp;lt;aside&amp;gt;Side bar 2&amp;lt;/aside&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;content1&quot;&amp;gt;
    &amp;lt;article&amp;gt;Content 1&amp;lt;/article&amp;gt;
    &amp;lt;article&amp;gt;Content 3&amp;lt;/article&amp;gt;
    &amp;lt;article&amp;gt;Content 5&amp;lt;/article&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;div id=&quot;content2&quot;&amp;gt;
    &amp;lt;article&amp;gt;Content 2&amp;lt;/article&amp;gt;
    &amp;lt;article&amp;gt;Content 4&amp;lt;/article&amp;gt;
    &amp;lt;article&amp;gt;Content 6&amp;lt;/article&amp;gt;
&amp;lt;/div&amp;gt;
&amp;lt;footer&amp;gt;Footer&amp;lt;/footer&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;By default I&#039;ve assumed a single column layout:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;body {
    width: 90%;
    height: 90%;
    margin: 0 5%;
    display: -ms-grid;
    -ms-grid-rows: auto;
    -ms-grid-columns: 1fr;
}
article, aside, header, footer {
     margin: 1em;
     padding: 1em;
     outline: 4px dashed black;
}
header { -ms-grid-row: 1; }
#sidebar { -ms-grid-row: 3; }
#content1 { -ms-grid-row: 2; }
#content2 { -ms-grid-row: 4; }
footer {  -ms-grid-row: 5; }&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Moving on to windows of a minimum width of 600 pixels, move up to two columns:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;@media screen and (min-width: 600px) {
    body {
        -ms-grid-columns: auto 1fr;
        -ms-grid-rows: auto 1fr 1fr auto;
    }
    header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 2; }
    #sidebar { -ms-grid-column: 1; -ms-grid-row: 2; -ms-grid-rowspan: 2; }
    #content1 { -ms-grid-column: 2; -ms-grid-row: 2; }
    #content2 { -ms-grid-column: 2; -ms-grid-row: 3; }
    footer { -ms-grid-column: 1; -ms-grid-row: 4; -ms-grid-column-span: 2; }
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;This is nothing you haven&#039;t seen already, but I&#039;ll just point out again how cool it is that you can place the elements wherever you want them.  Finally, for windows of greater than 760 pixels width, switch back to the three column layout:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;@media screen and (min-width: 760px) {
    body {
        -ms-grid-columns: auto 1fr 1fr;
        -ms-grid-rows: auto 1fr auto;
    }
    header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
    #sidebar { -ms-grid-column: 1; -ms-grid-row: 2; }
    #content1 { -ms-grid-column: 2; -ms-grid-row: 2; }
    #content2 { -ms-grid-column: 3; -ms-grid-row: 2; }
    footer { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;If you&#039;ve downloaded the IE10 developer preview &lt;a href=&quot;http://www.boogdesign.com/examples/grids/grid-layout-5.html&quot;&gt;have a play round with it yourself&lt;/a&gt;, and try not to think about how long you&#039;ll have to wait until all this stuff is available in production browsers &lt;img src=&quot;http://www.boogdesign.com/b2evo/rsc/smilies/icon_razz.gif&quot; title=&quot;&amp;amp;amp;#58;&amp;amp;amp;#112;&quot; alt=&quot;&amp;amp;amp;#58;&amp;amp;amp;#112;&quot; class=&quot;middle&quot; width=&quot;15&quot; height=&quot;15&quot; /&gt; &lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=css3&quot;&gt;css3&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=ie10&quot;&gt;ie10&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;IE10 and the Future of CSS Layout&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;amp;title=IE10 and the Future of CSS Layout&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;amp;title=IE10 and the Future of CSS Layout&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;amp;t=IE10 and the Future of CSS Layout&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=IE10 and the Future of CSS Layout&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;amp;t=IE10 and the Future of CSS Layout&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=IE10 and the Future of CSS Layout&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;amp;Title=IE10 and the Future of CSS Layout&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=IE10 and the Future of CSS Layout+http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Last week <a href="http://blogs.msdn.com/b/ie/archive/2011/04/12/native-html5-first-ie10-platform-preview-available-for-download.aspx">the first developer preview of IE10 was released</a>.  Among <a href="http://msdn.microsoft.com/en-us/ie/gg192966">several experimental features</a> included were the first Microsoft implementations of <a href="http://www.w3.org/TR/css3-flexbox/">CSS3 Flexible Box Layout Module</a> and <a href="http://dev.w3.org/csswg/css3-grid-align/">CSS3 Grid Alignment</a>.  These are possibly the most exciting things to be added to CSS since drop shadows...</p>

<p>First up the flexible box layout module, or flexboxes.  This has already been implemented in <a href="http://hacks.mozilla.org/2010/04/the-css-3-flexible-box-model/">Firefox and WebKit</a>, but <a href="http://lists.w3.org/Archives/Public/www-style/2011Jan/0186.html">that version of flexboxes isn't very intuitive</a>, and the draft has since seen a lot of updates.  Interestingly, IE10PR1 implements the same version of the spec as Firefox and WebKit but with one important addition: <a href="http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#multiple">multi-line flexboxes</a>.  For me the multi-line properties are what make flexboxes worthwhile for layout, otherwise nearly everything you might currently want to achieve can be done just as easily (and with better backwards compatibility) with <code>display: table-cell</code>.</p>

<p>This is the sort of thing that multi-line flexboxes are useful for, it's a layout typical of shopping and photo gallery sites:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-800.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-800-thumb.png" alt="A multiline flexbox layout at 800 pixels width" title="Click for full size image" /></a></p>

<p>Here's what my markup looks like, nothing more complex than a list with sixty items in it:</p><blockquote><pre><code>&lt;ul&gt;
    &lt;li&gt;1&lt;/li&gt;
    &lt;li&gt;2&lt;/li&gt;
    &lt;li&gt;3&lt;/li&gt;
    ...
    &lt;li&gt;59&lt;/li&gt;
    &lt;li&gt;60&lt;/li&gt;
&lt;/ul&gt;</code></pre></blockquote><p>And here's the CSS, the key things to look out for are the <code>display: -ms-box</code> and the <code>-ms-box-lines</code>:</p><blockquote><pre><code>body {
    width: 90%;
    margin: 0 5%;
}
ul {
    display: -ms-box;
    -ms-box-lines: multiple;
    list-style: none;
    width: auto;
    padding: 10px;
    border: 4px dashed #000;
}
li {
    display: block;
    -ms-box-flex: 1;
    padding: 1em;
    margin: 0.5em;
    min-width: 3em;
    border: 4px dashed #000;
}</code></pre></blockquote><p>You may be thinking that's not a hard thing to pull off, so let me show you the same page, in an 800 pixel wide browser above, at 640 and 480 pixels:</p>
<div><div style="display: table-cell;">
<p><a href="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-640.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-640-thumb.png" alt="A multiline flexbox layout at 640 pixels width" title="Click for full size image" /></a></p>
</div><div style="display: table-cell;">
<a href="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-480.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1-480-thumb.png" alt="A multiline flexbox layout at 480 pixels width" title="Click for full size image" /></a>
</div></div>
<p>The number of cells across adjusts to match the width available, but, because these are flexboxes, the width of the elements themselves also adjust so that they always exactly fit the available width.  This is unique among our current alternatives:</p><ul>
<li>If you were using floats or inline blocks then you'd have to set each element to a fixed width, meaning the container would have to be a fixed width so that the elements could fill it exactly.  You'd have to use media queries to assign different fixed widths to the container to change the items per row according to screen resolution.</li>
<li>If you were using a <a href="http://blog.whatwg.org/weekly-layout-table">layout table</a> or display: table-cell then, although the elements would expand to fit exactly, the number of items per row would be fixed by the markup.</li>
</ul><p>However, nothing is perfect.  <a href="http://www.boogdesign.com/examples/grids/flex-layout-1.html">My multi-line flexbox example</a> has a total of 60 elements, and I picked this number because it is an exact multiple of 2, 3, 4, 5 and 6 (it's the <a href="http://en.wikipedia.org/wiki/Polynomial_expansion">expansion</a> of them if I've got my maths terms right<img src="http://www.boogdesign.com/b2evo/rsc/smilies/icon_question.gif" title="&amp;amp;#58;&amp;amp;#63;&amp;amp;#58;" alt="&amp;amp;#58;&amp;amp;#63;&amp;amp;#58;" class="middle" width="15" height="15" />) - meaning that the number of elements will fill the grid whether there's 2, 3, 4, 5 or 6 elements per row.  If there's a less perfect number, say 24, then the grid will look a little strange on the last row:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1a-640.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/flexbox-1a-640-thumb.png" alt="A multiline flexbox layout at 640 pixels width with only 24 elements" title="Click for full size image" /></a></p>

<p>I think the <a href="http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#multiple-alignment"><code>box-align</code></a> property should help with this, but I couldn't make it work in IE10PR1.</p>

<p>So, multi-line flexboxes could be a useful addition to the CSS toolbox when everyone gets round to upgrading to IE10, but, cool as they are, that's not the coolest experimental CSS layout implementation in IE10PR1.  There have been a few grid and template based CSS proposals over the years but, apart from an incomplete JavaScript library for CSS Template Layout, none of them have ever been implemented in a major desktop browser.  That is until last week, when IE10PR1 implemented <a href="http://www.interoperabilitybridges.com/css3-grid-align/">Microsoft's own CSS Grid Align proposal from October 2010</a>.</p>

<p>I want you to reflect, now, on all the fun you've had over the last ten years constructing CSS layouts of three equal height columns, with a header and footer, and making them work in IE6.  Layouts something like this:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-1.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-1-thumb.png" alt="A three column layout with header and footer" /></a></p>

<p>Are you remembering all the fun you had?  Good, now look at this markup and contemplate how you'd turn it into a three column layout:</p><blockquote><pre><code>&lt;header&gt;Header&lt;/header&gt;
&lt;aside class="b"&gt;Side bar&lt;/aside&gt;
&lt;article&gt;I never am really satisfied...&lt;/article&gt;
&lt;aside class="d"&gt;Side bar&lt;/aside&gt;
&lt;footer&gt;Footer&lt;/footer&gt;</code></pre></blockquote><p>Now look at this CSS and start wishing the future would arrive soon:</p><blockquote><pre><code>body {
    width: 90%;
    margin: 0 5%;
    display: -ms-grid;
    -ms-grid-columns: auto minmax(min-content, 1fr) auto;
    -ms-grid-rows: auto minmax(min-content, 1fr) auto;
}
article, aside, header, footer {
    margin: 1em;
    padding: 1em;
    outline: 4px dashed black;
}
header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
aside.b { -ms-grid-column: 1; -ms-grid-row: 2; }
article { -ms-grid-column: 2; -ms-grid-row: 2; }
aside.d { -ms-grid-column: 3; -ms-grid-row: 2; }
footer { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }</code></pre></blockquote><p>That's it, seven declarations is all you need for that three column layout with CSS Grid Align.  For this first example I'm going to step through the key points line by line:</p><blockquote><pre><code>display: -ms-grid;</code></pre></blockquote><p>This is the bit which declares we will use the grid layout manager on the children of this element, in the same way that the flexbox layout manager was declared above with <code>display: -ms-box</code>.</p><blockquote><pre><code>-ms-grid-columns: auto minmax(min-content, 1fr) auto;</code></pre></blockquote><p>This line defines three columns, the first and last will shrink to fit the content - that's the default behaviour, similar to a table.  The middle column will be a minimum of <code>min-content</code>, which is basically the same as <code>auto</code>, and a maximum of <code>1fr</code> which is a 'fraction of available space' - quite similar to a flex unit and, since there's only one fractional column, basically equivalent to all the available space.</p><blockquote><pre><code>-ms-grid-rows: auto minmax(min-content, 1fr) auto;</code></pre></blockquote><p>We'll have three rows to go along with our three columns, I won't go over the individual values again.  Now the fun stuff:</p><blockquote><pre><code>header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }</code></pre></blockquote><p>Put the header in the first column of the first row, and make it span three columns.  That's it.  Really, it's that simple.  Let's just do one more:</p><blockquote><pre><code>article { -ms-grid-column: 2; -ms-grid-row: 2; }</code></pre></blockquote><p>Put the article in the second column and the second row.  And make me some coffee, white, no sugar.  Actually there isn't a CSS property for that yet, maybe CSS4...</p>

<p>But it gets more cool than that.  In the example above the order of the elements in the markup matched up with the order they were placed into the grid, but it doesn't have to be that way:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-2.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-2-thumb.png" alt="A three column layout with header and footer, with elements placed in a different order" /></a></p>

<p>This amazing transformation was achieved without any changes in markup, just messing around with CSS:</p><blockquote><pre><code>header { -ms-grid-column: 1; -ms-grid-row: 2; }
aside.b { -ms-grid-column: 2; -ms-grid-row: 2; }
article { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
aside.d { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }
footer { -ms-grid-column: 3; -ms-grid-row: 2; }</code></pre></blockquote><p>In <a href="http://dev.w3.org/csswg/css3-grid-align/">the current draft</a> there's a <code>grid-cell-stacking</code> property which will let you flow multiple elements into a single cell, but in the IE10PR1 implementation things just stack on top of each other:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3a.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3a-thumb.png" alt="Multiple elements in cells not working" /></a></p>

<p>This is a shame, because the markup is quite straightforward, I won't post all of it because this is already getting quite long (<a href="http://www.boogdesign.com/examples/grids/grid-layout-3a.html">have a look</a>), but here's the nice bit:</p><blockquote><pre><code>article:nth-child(2n+1) { -ms-grid-column: 1; }
article:nth-child(2n) { -ms-grid-column: 2; }</code></pre></blockquote><p>The article elements are assigned to grid cells alternately, unfortunately it doesn't work yet.  However you can nest elements set to <code>display: -ms-grid</code> inside each other:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-3-thumb.png" alt="A three column layout with header and footer" /></a></p>

<p>Have a <a href="http://www.boogdesign.com/examples/grids/grid-layout-3.html">look at the source code</a> for that one, it gets pretty hairy, so rather than try and do that sort of thing it's probably best to use some wrapper elements like this:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-4.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-4-thumb.png" alt="Grid Align with wrapper elements for cells" /></a></p>

<p>Again, <a href="http://www.boogdesign.com/examples/grids/grid-layout-4.html">view the source code yourself</a> to see how it's put together, but I think these things will be worth re-visiting in a later preview release.</p>

<p>I'm going to finish off with some <a href="http://www.alistapart.com/articles/responsive-web-design/">adaptive layout</a>.  Grid Align is a great fit for this because of the complete independence of layout from source order.  Here's what I put together based off the previous example at 800 pixel width:</p>

<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-800.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-800-thumb.png" alt="An adaptive Grid Align at 800px width" /></a></p>

<p>Now here's the same page at 640 and 480 pixel widths:</p>
<div><div style="display: table-cell;">
<p><a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-640.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-640-thumb.png" alt="An adaptive Grid Align at 640px width" /></a></p>
</div><div style="display: table-cell;">
<a href="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-480.png"><img class="screenshot" src="http://www.boogdesign.com/images/blog/ie10grids/grid-layout-5-480-thumb.png" alt="An adaptive Grid Align at 480px width" /></a>
</div></div>
<p>The markup is, of course, the same in each case:</p><blockquote><pre><code>&lt;header&gt;Header&lt;/header&gt;
&lt;div id="sidebar"&gt;
    &lt;aside&gt;Side bar 1&lt;/aside&gt;
    &lt;aside&gt;Side bar 2&lt;/aside&gt;
&lt;/div&gt;
&lt;div id="content1"&gt;
    &lt;article&gt;Content 1&lt;/article&gt;
    &lt;article&gt;Content 3&lt;/article&gt;
    &lt;article&gt;Content 5&lt;/article&gt;
&lt;/div&gt;
&lt;div id="content2"&gt;
    &lt;article&gt;Content 2&lt;/article&gt;
    &lt;article&gt;Content 4&lt;/article&gt;
    &lt;article&gt;Content 6&lt;/article&gt;
&lt;/div&gt;
&lt;footer&gt;Footer&lt;/footer&gt;</code></pre></blockquote><p>By default I've assumed a single column layout:</p><blockquote><pre><code>body {
    width: 90%;
    height: 90%;
    margin: 0 5%;
    display: -ms-grid;
    -ms-grid-rows: auto;
    -ms-grid-columns: 1fr;
}
article, aside, header, footer {
     margin: 1em;
     padding: 1em;
     outline: 4px dashed black;
}
header { -ms-grid-row: 1; }
#sidebar { -ms-grid-row: 3; }
#content1 { -ms-grid-row: 2; }
#content2 { -ms-grid-row: 4; }
footer {  -ms-grid-row: 5; }</code></pre></blockquote><p>Moving on to windows of a minimum width of 600 pixels, move up to two columns:</p><blockquote><pre><code>@media screen and (min-width: 600px) {
    body {
        -ms-grid-columns: auto 1fr;
        -ms-grid-rows: auto 1fr 1fr auto;
    }
    header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 2; }
    #sidebar { -ms-grid-column: 1; -ms-grid-row: 2; -ms-grid-rowspan: 2; }
    #content1 { -ms-grid-column: 2; -ms-grid-row: 2; }
    #content2 { -ms-grid-column: 2; -ms-grid-row: 3; }
    footer { -ms-grid-column: 1; -ms-grid-row: 4; -ms-grid-column-span: 2; }
}</code></pre></blockquote><p>This is nothing you haven't seen already, but I'll just point out again how cool it is that you can place the elements wherever you want them.  Finally, for windows of greater than 760 pixels width, switch back to the three column layout:</p><blockquote><pre><code>@media screen and (min-width: 760px) {
    body {
        -ms-grid-columns: auto 1fr 1fr;
        -ms-grid-rows: auto 1fr auto;
    }
    header { -ms-grid-column: 1; -ms-grid-row: 1; -ms-grid-column-span: 3; }
    #sidebar { -ms-grid-column: 1; -ms-grid-row: 2; }
    #content1 { -ms-grid-column: 2; -ms-grid-row: 2; }
    #content2 { -ms-grid-column: 3; -ms-grid-row: 2; }
    footer { -ms-grid-column: 1; -ms-grid-row: 3; -ms-grid-column-span: 3; }
}</code></pre></blockquote><p>If you've downloaded the IE10 developer preview <a href="http://www.boogdesign.com/examples/grids/grid-layout-5.html">have a play round with it yourself</a>, and try not to think about how long you'll have to wait until all this stuff is available in production browsers <img src="http://www.boogdesign.com/b2evo/rsc/smilies/icon_razz.gif" title="&amp;amp;#58;&amp;amp;#112;" alt="&amp;amp;#58;&amp;amp;#112;" class="middle" width="15" height="15" /> </p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=css3">css3</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=ie10">ie10</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2')+'&amp;title='+encodeURIComponent('IE10 and the Future of CSS Layout'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;title=IE10 and the Future of CSS Layout" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;title=IE10 and the Future of CSS Layout&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;t=IE10 and the Future of CSS Layout" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=IE10 and the Future of CSS Layout&amp;url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;t=IE10 and the Future of CSS Layout" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=IE10 and the Future of CSS Layout&amp;u=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2&amp;Title=IE10 and the Future of CSS Layout" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=IE10 and the Future of CSS Layout+http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/ie10-future-of-css-layout?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=367</wfw:commentRss>
		</item>
				<item>
			<title>Client Side Server Side Includes</title>
			<link>http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2</link>
			<pubDate>Mon, 31 Jan 2011 01:32:00 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="alt">Front End Web Development</category>
<category domain="main">Blogging and Internet Culture</category>			<guid isPermaLink="false">362@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;I spent some time over Xmas reflecting on my past web adventures.  My first ever website, a guide to local drinking establishments, was hosted on a cast-off server at Edinburgh University in late 1993, and the particular server and site are now long gone (although the &lt;a href=&quot;http://www.tardis.ed.ac.uk/wiki/Main_Page&quot;&gt;server has been replaced&lt;/a&gt;).  Similarly, my original mid-nineties home page, replete with animated GIFs and ripped off Homer Simpson images has also be consigned to the recycle bin of web history (thankfully).  However, the first website I worked on &#039;professionally&#039; is still online: &lt;a href=&quot;http://www.iwant2bhealthy.com/&quot;&gt;iwant2bhealthy.com&lt;/a&gt; is a thousand page static HTML monolith which we maintained with Dreamweaver 3.&lt;/p&gt;

&lt;p&gt;The site did take advantage of some server processing, it used &lt;a href=&quot;http://en.wikipedia.org/wiki/Server_Side_Includes&quot;&gt;Server Side Includes&lt;/a&gt; (SSI) to embed particular common items such as the main navigation and footer.  SSI isn&#039;t so common these days when nearly every cheap host offers some sort of server side scripting language, so often it isn&#039;t turned on my default.  The result is that the iwant2bhealthy.com website is missing its main navigation and footer on most pages, all that&#039;s left is some markup like this:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!--#include virtual=&quot;/Library/mainmenu.shtml&quot; --&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Or this:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;!--#include virtual=&quot;/Library/footer.shtml&quot; --&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;I had a hankering to experience the website in all its turn of the century glory and it seemed to me that I ought to be able write a bookmarklet to grab jQuery, grab the comments, fetch the includes with AJAX and insert them in place of the comments.&lt;/p&gt;

&lt;p&gt;It turns out that the first tricky thing is grabbing the comment elements.  The jQuery selection engine purposely ignores comments so none of those handy little methods are much use.  There&#039;s not much option but to loop through the document and select based on &lt;a href=&quot;https://developer.mozilla.org/en/nodeType&quot;&gt;&lt;code&gt;nodeType&lt;/code&gt;&lt;/a&gt; (8 for a comment element), fortunately &lt;a href=&quot;http://james.padolsey.com/javascript/introducing-jshtml/&quot;&gt;someone on the web had already done most of the hard work&lt;/a&gt; so I was able to adapt &lt;a href=&quot;http://james.padolsey.com/demos/JSHTML/jshtml.js&quot;&gt;his code&lt;/a&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;parseSSI : function(el) {
    var nodes = el.childNodes;
    var l = nodes.length;
    while (l--) {
        current = nodes[l];
        if (current.nodeType == 8) {
            //do stuff here
        } else if (current.nodeType != 3 &amp;amp;&amp;amp; current.childElementCount &amp;gt; 0) {
            this.parseSSI(current);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The function loops through all the child nodes of a supplied element and, if they&#039;re a comment, does some processing.  If the node isn&#039;t a comment we check that it&#039;s also not a text node and then call the function recursively if there are any child nodes.&lt;/p&gt;

&lt;p&gt;Of course it&#039;s entirely possible that there are comments in the web page that have nothing to do with server side includes, so some sort of check is probably in order.  Following James&#039; example I used a regular expression:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;re : /#include virtual=\&quot;(.*)\&quot;/i&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;My next step was to convert those comment elements into something that could be more easily manipulated by jQuery, so I decided to convert them to links:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var match = this.re.exec(current.data);
if (match != null) {
    var a = document.createElement(&#039;a&#039;);
    a.href = match[1];
    current.parentNode.replaceChild(a, current);&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now we&#039;re back in the nice, succinct land of jQuery - fetch the URL with Ajax and replace the relevant link element in the callback:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;$.ajax({ url: match[1],
         success: function(data, textStatus, XMLHttpRequest){
            $(&#039;[href=&#039; + this.url + &#039;]&#039;).replaceWith(data);
        }});&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Try out &lt;a href=&quot;http://www.boogdesign.com/examples/jsssi/index.html&quot;&gt;the final code here&lt;/a&gt;.&lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=history&quot;&gt;history&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=tools&quot;&gt;tools&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=web&quot;&gt;web&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;Client Side Server Side Includes&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;amp;title=Client Side Server Side Includes&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;amp;title=Client Side Server Side Includes&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;amp;t=Client Side Server Side Includes&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=Client Side Server Side Includes&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;amp;t=Client Side Server Side Includes&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Client Side Server Side Includes&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;amp;Title=Client Side Server Side Includes&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=Client Side Server Side Includes+http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>I spent some time over Xmas reflecting on my past web adventures.  My first ever website, a guide to local drinking establishments, was hosted on a cast-off server at Edinburgh University in late 1993, and the particular server and site are now long gone (although the <a href="http://www.tardis.ed.ac.uk/wiki/Main_Page">server has been replaced</a>).  Similarly, my original mid-nineties home page, replete with animated GIFs and ripped off Homer Simpson images has also be consigned to the recycle bin of web history (thankfully).  However, the first website I worked on 'professionally' is still online: <a href="http://www.iwant2bhealthy.com/">iwant2bhealthy.com</a> is a thousand page static HTML monolith which we maintained with Dreamweaver 3.</p>

<p>The site did take advantage of some server processing, it used <a href="http://en.wikipedia.org/wiki/Server_Side_Includes">Server Side Includes</a> (SSI) to embed particular common items such as the main navigation and footer.  SSI isn't so common these days when nearly every cheap host offers some sort of server side scripting language, so often it isn't turned on my default.  The result is that the iwant2bhealthy.com website is missing its main navigation and footer on most pages, all that's left is some markup like this:</p><blockquote><pre><code>&lt;!--#include virtual="/Library/mainmenu.shtml" --&gt;</code></pre></blockquote><p>Or this:</p><blockquote><pre><code>&lt;!--#include virtual="/Library/footer.shtml" --&gt;</code></pre></blockquote><p>I had a hankering to experience the website in all its turn of the century glory and it seemed to me that I ought to be able write a bookmarklet to grab jQuery, grab the comments, fetch the includes with AJAX and insert them in place of the comments.</p>

<p>It turns out that the first tricky thing is grabbing the comment elements.  The jQuery selection engine purposely ignores comments so none of those handy little methods are much use.  There's not much option but to loop through the document and select based on <a href="https://developer.mozilla.org/en/nodeType"><code>nodeType</code></a> (8 for a comment element), fortunately <a href="http://james.padolsey.com/javascript/introducing-jshtml/">someone on the web had already done most of the hard work</a> so I was able to adapt <a href="http://james.padolsey.com/demos/JSHTML/jshtml.js">his code</a>:</p><blockquote><pre><code>parseSSI : function(el) {
    var nodes = el.childNodes;
    var l = nodes.length;
    while (l--) {
        current = nodes[l];
        if (current.nodeType == 8) {
            //do stuff here
        } else if (current.nodeType != 3 &amp;&amp; current.childElementCount &gt; 0) {
            this.parseSSI(current);
        }
    }
}</code></pre></blockquote><p>The function loops through all the child nodes of a supplied element and, if they're a comment, does some processing.  If the node isn't a comment we check that it's also not a text node and then call the function recursively if there are any child nodes.</p>

<p>Of course it's entirely possible that there are comments in the web page that have nothing to do with server side includes, so some sort of check is probably in order.  Following James' example I used a regular expression:</p><blockquote><pre><code>re : /#include virtual=\"(.*)\"/i</code></pre></blockquote><p>My next step was to convert those comment elements into something that could be more easily manipulated by jQuery, so I decided to convert them to links:</p><blockquote><pre><code>var match = this.re.exec(current.data);
if (match != null) {
    var a = document.createElement('a');
    a.href = match[1];
    current.parentNode.replaceChild(a, current);</code></pre></blockquote><p>Now we're back in the nice, succinct land of jQuery - fetch the URL with Ajax and replace the relevant link element in the callback:</p><blockquote><pre><code>$.ajax({ url: match[1],
         success: function(data, textStatus, XMLHttpRequest){
            $('[href=' + this.url + ']').replaceWith(data);
        }});</code></pre></blockquote><p>Try out <a href="http://www.boogdesign.com/examples/jsssi/index.html">the final code here</a>.</p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=history">history</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=tools">tools</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=web">web</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2')+'&amp;title='+encodeURIComponent('Client Side Server Side Includes'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;title=Client Side Server Side Includes" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;title=Client Side Server Side Includes&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;t=Client Side Server Side Includes" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=Client Side Server Side Includes&amp;url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;t=Client Side Server Side Includes" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Client Side Server Side Includes&amp;u=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2&amp;Title=Client Side Server Side Includes" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=Client Side Server Side Includes+http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/jsssi-client-side-server-side-includes?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=362</wfw:commentRss>
		</item>
				<item>
			<title>HTML5 Comment Forms in b2evolution</title>
			<link>http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2</link>
			<pubDate>Fri, 24 Dec 2010 23:22:20 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="main">Web Develop</category>
<category domain="alt">Blogging and Internet Culture</category>			<guid isPermaLink="false">361@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;Following &lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/2010/12/16/fun-with-html5-forms?blog=2&quot;&gt;my post last week on HTML5 forms&lt;/a&gt; it occurred to me that I should be a little embarrassed devoting all this time to writing about HTML5 when my blog makes use of no HTML5 features.  A quick hack around with the template corrected the DOCTYPE and I was looking for some other quick changes I could make without getting into to a full redesign (currently in process for about 5 months...).  The comments form seemed an obvious target and turns out to be remarkably easy to do in b2evo.&lt;/p&gt;

&lt;p&gt;The file you need to edit is &lt;code&gt;_item_comment_form.inc.php&lt;/code&gt;, which will live inside your skins directory.  If you have a custom skin set up you may also find inside the directory for that skin, these instructions assume you&#039;ll be editing the standard &lt;code&gt;_item_comment_form.inc.php&lt;/code&gt;, whether in the skins directory or in a folder in that directory.&lt;/p&gt;

&lt;p&gt;The parts we need to edit are on lines 142 and 143, the fields for email and website address:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;$Form-&amp;gt;text( &#039;i&#039;, $comment_author_email, 40, T_(&#039;Email&#039;), &#039;&amp;lt;br /&amp;gt;&#039;.T_(&#039;Your email address will &amp;lt;strong&amp;gt;not&amp;lt;/strong&amp;gt; be revealed on this site.&#039;), 100, &#039;bComment&#039; );
$Form-&amp;gt;text( &#039;o&#039;, $comment_author_url, 40, T_(&#039;Website&#039;), &#039;&amp;lt;br /&amp;gt;&#039;.T_(&#039;Your URL will be displayed.&#039;), 100, &#039;bComment&#039; );&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The &lt;code&gt;text&lt;/code&gt; method on the &lt;code&gt;$Form&lt;/code&gt; object can take an optional sixth parameter which determines the input type.  So to create HTML5 &lt;code&gt;email&lt;/code&gt; and &lt;code&gt;url&lt;/code&gt; inputs, simply add that sixth parameter:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;$Form-&amp;gt;text( &#039;i&#039;, $comment_author_email, 40, T_(&#039;Email&#039;), &#039;&amp;lt;br /&amp;gt;&#039;.T_(&#039;Your email address will &amp;lt;strong&amp;gt;not&amp;lt;/strong&amp;gt; be revealed on this site.&#039;), 100, &#039;bComment&#039;, &#039;email&#039; );
$Form-&amp;gt;text( &#039;o&#039;, $comment_author_url, 40, T_(&#039;Website&#039;), &#039;&amp;lt;br /&amp;gt;&#039;.T_(&#039;Your URL will be displayed.&#039;), 100, &#039;bComment&#039;, &#039;url&#039; );&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=b2evolution&quot;&gt;b2evolution&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=html5&quot;&gt;html5&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;HTML5 Comment Forms in b2evolution&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;amp;title=HTML5 Comment Forms in b2evolution&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;amp;title=HTML5 Comment Forms in b2evolution&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;amp;t=HTML5 Comment Forms in b2evolution&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=HTML5 Comment Forms in b2evolution&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;amp;t=HTML5 Comment Forms in b2evolution&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=HTML5 Comment Forms in b2evolution&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;amp;Title=HTML5 Comment Forms in b2evolution&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=HTML5 Comment Forms in b2evolution+http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Following <a href="http://www.boogdesign.com/b2evo/index.php/2010/12/16/fun-with-html5-forms?blog=2">my post last week on HTML5 forms</a> it occurred to me that I should be a little embarrassed devoting all this time to writing about HTML5 when my blog makes use of no HTML5 features.  A quick hack around with the template corrected the DOCTYPE and I was looking for some other quick changes I could make without getting into to a full redesign (currently in process for about 5 months...).  The comments form seemed an obvious target and turns out to be remarkably easy to do in b2evo.</p>

<p>The file you need to edit is <code>_item_comment_form.inc.php</code>, which will live inside your skins directory.  If you have a custom skin set up you may also find inside the directory for that skin, these instructions assume you'll be editing the standard <code>_item_comment_form.inc.php</code>, whether in the skins directory or in a folder in that directory.</p>

<p>The parts we need to edit are on lines 142 and 143, the fields for email and website address:</p><blockquote><pre><code>$Form-&gt;text( 'i', $comment_author_email, 40, T_('Email'), '&lt;br /&gt;'.T_('Your email address will &lt;strong&gt;not&lt;/strong&gt; be revealed on this site.'), 100, 'bComment' );
$Form-&gt;text( 'o', $comment_author_url, 40, T_('Website'), '&lt;br /&gt;'.T_('Your URL will be displayed.'), 100, 'bComment' );</code></pre></blockquote><p>The <code>text</code> method on the <code>$Form</code> object can take an optional sixth parameter which determines the input type.  So to create HTML5 <code>email</code> and <code>url</code> inputs, simply add that sixth parameter:</p><blockquote><pre><code>$Form-&gt;text( 'i', $comment_author_email, 40, T_('Email'), '&lt;br /&gt;'.T_('Your email address will &lt;strong&gt;not&lt;/strong&gt; be revealed on this site.'), 100, 'bComment', 'email' );
$Form-&gt;text( 'o', $comment_author_url, 40, T_('Website'), '&lt;br /&gt;'.T_('Your URL will be displayed.'), 100, 'bComment', 'url' );</code></pre></blockquote>
<div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=b2evolution">b2evolution</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=html5">html5</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2')+'&amp;title='+encodeURIComponent('HTML5 Comment Forms in b2evolution'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;title=HTML5 Comment Forms in b2evolution" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;title=HTML5 Comment Forms in b2evolution&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;t=HTML5 Comment Forms in b2evolution" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=HTML5 Comment Forms in b2evolution&amp;url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;t=HTML5 Comment Forms in b2evolution" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=HTML5 Comment Forms in b2evolution&amp;u=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2&amp;Title=HTML5 Comment Forms in b2evolution" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=HTML5 Comment Forms in b2evolution+http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/html5-comment-forms-in-b2evolution?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=361</wfw:commentRss>
		</item>
				<item>
			<title>Fun with HTML5 Forms</title>
			<link>http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2</link>
			<pubDate>Thu, 16 Dec 2010 01:58:42 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="main">Front End Web Development</category>
<category domain="alt">Standards, HTML and CSS</category>			<guid isPermaLink="false">349@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;There have been many blog posts describing all the new elements and input types HTML5 provides, check out &lt;a href=&quot;http://24ways.org/2009/have-a-field-day-with-html5-forms&quot;&gt;this 24ways post for a good summary&lt;/a&gt;, or you could even &lt;a href=&quot;http://affiliate.manning.com/idevaffiliate.php?id=1155_240&quot;&gt;read chapter 3 of my book&lt;/a&gt;.  In this post I&#039;m going to focus instead on the validation API and some related HTML5 features by building a simple game based on entering an email address.  The goal is to explore some HTML5 features rather than do everything in the most straightforward way, but there should be some practically useful code snippets.&lt;/p&gt;

&lt;p&gt;The form itself is going to be very straightforward:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;form id=&quot;game&quot;&amp;gt;
    &amp;lt;fieldset&amp;gt;
        &amp;lt;legend&amp;gt;Enter a valid email address before the timer runs down&amp;lt;/legend&amp;gt;
        &amp;lt;label for=&quot;email&quot;&amp;gt;Email&amp;lt;/label&amp;gt;
        &amp;lt;input id=&quot;email&quot; type=&quot;email&quot; autofocus required&amp;gt;
    &amp;lt;/fieldset&amp;gt;
    &amp;lt;label for=&quot;countdown&quot;&amp;gt;You have
        &amp;lt;output id=&quot;countdown&quot;&amp;gt;10&amp;lt;/output&amp;gt;
        seconds.
    &amp;lt;/label&amp;gt;
    &amp;lt;label for=&quot;score&quot;&amp;gt;You have
        &amp;lt;output id=&quot;score&quot;&amp;gt;0&amp;lt;/output&amp;gt;
        points.
    &amp;lt;/label&amp;gt;
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;In the initial version we will take advantage of three HTML5 features:&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;The &lt;code&gt;output&lt;/code&gt; element&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;email&lt;/code&gt; input type&lt;/li&gt;
  &lt;li&gt;The &lt;code&gt;checkValidity&lt;/code&gt; method from the the HTML5 Form Validation API&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;In the countdown function we use the value property of the the output element  The output element is something like a &lt;code&gt;span&lt;/code&gt;, it&#039;s a start and end tag with arbitrary content, but you can access the contents using the &lt;code&gt;value&lt;/code&gt; attribute like a form field :&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var counter = function (cd, sc, em) {
    cd.value -= 1;
    sc.value = calcScore(em.value);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;This may not look particularly helpful, but consider what the code would look like without the output element (or in a browser which doesn&#039;t support output):&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var counter = function (cd, sc, em) {
    var count = cd.innerHTML;
	count -= 1;
    cd.innerHTML = count;
	sc.innerHTML = calcScore(em.innerHTML);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The function is now mostly about the details of manipulating the DOM, rather than the more straightforward algebraic style of the original.  Granted, libraries like jQuery have for a long time provided abstractions which allow you to write this code more cleanly but, like design patterns, these are as much an indication of the lack of expressiveness in the underlying platform as they are examples of best practice.&lt;/p&gt;

&lt;p&gt;The game needs a function to calculate a &#039;score&#039; from the email address.  This is, of course, completely arbitrary:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;
function calcScore(email) {
    var s = 0;
    s += email.length;
    s += email.indexOf(&#039;@&#039;)&gt;-1?email.indexOf(&#039;@&#039;):0;
    s += email.lastIndexOf(&#039;.&#039;)&gt;-1?email.lastIndexOf(&#039;.&#039;):0;
    return s;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Now we need to wire up the functions to appropriate events when the game starts. To keep things simple I&#039;m going to store a reference to the interval in a global variable:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var cdInterval;
var gameStart = function () {
    window.clearInterval(cdInterval);
    var em = document.getElementById(&#039;email&#039;);
    var cd = document.getElementById(&#039;countdown&#039;);
    var sc = document.getElementById(&#039;score&#039;);
    cd.value = 10;
    sc.value = 0;
    em.value = &#039;&#039;;
    em.readOnly = false;
    cdInterval = window.setInterval(counter,1000, cd, sc, em);
    window.setTimeout(gameOver,10000, cd, sc, em);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Again, this function takes advantage of the value attribute on the output elements.  The last line calls a &lt;code&gt;gameOver&lt;/code&gt; function after ten seconds, we&#039;ll use that to clear the interval and calculate the score.  The &lt;code&gt;checkValidity&lt;/code&gt; method of the email field will be used to determine if the email address is currently valid:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var gameOver = function (cd, sc, em) {
    window.clearInterval(cdInterval);
    var score = calcScore(em.value);
    if (!em.checkValidity()) {
        score = 0;
        window.alert(&quot;You lose!&quot;);
    }
    cd.value = 0;
    sc.value = score;
    em.readOnly = true;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The &lt;code&gt;checkValidity()&lt;/code&gt; method is part of the HTML5 validation API, it returns &lt;code&gt;true&lt;/code&gt; if the browser understands the contents of the field as a valid email.  Note that we are able to call this method without submitting the form, so it is easy to hook form submission into a custom validation function if we want.  At no point do we have to implement any code to determine what a valid email address would be.  This is a second major saving, have a look at this regular expression example if you thought that code was straightforward:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;(?:[a-z0-9!#$%&amp;amp;&#039;*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;amp;&#039;*+/=?^_`{|}~-]+)*|&quot;(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*&quot;)@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Finally, start the game when the page loads:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;window.addEventListener(&#039;load&#039;, gameStart, false);&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The &lt;a href=&quot;http://www.boogdesign.com/examples/forms2/email-game-1.html&quot;&gt;first version of the game&lt;/a&gt; will work in Opera, and the development versions of Firefox (4 - relevant bugs are &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=345624&quot;&gt;345624&lt;/a&gt; and &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=346485&quot;&gt;346485&lt;/a&gt; ) and Chrome (9 - relevant bugs are &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=27452&quot;&gt;27452&lt;/a&gt; and &lt;a href=&quot;https://bugs.webkit.org/show_bug.cgi?id=29363&quot;&gt;29363&lt;/a&gt;).  If you want it to work on older versions of Chrome and Safari then you&#039;ll need to replace the output based syntax with the &lt;code&gt;innerHTML&lt;/code&gt; approach as per the alternate version of &lt;code&gt;counter&lt;/code&gt; above.&lt;/p&gt;

&lt;p&gt;For the second iteration we&#039;re going to look at these two features:&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;Using the pageshow event from the History API&lt;/li&gt;
  &lt;li&gt;How to reset &lt;code&gt;output&lt;/code&gt; elements&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;If the user visits another page after completing the game and then goes back then the game will sit there inert until you reload the page.  This is because the game logic hangs off the &lt;code&gt;onload&lt;/code&gt; event, and navigating forward and backwards in the browser history doesn&#039;t fire &lt;code&gt;onload&lt;/code&gt;.  The HTML5 History API gives us another option: the &lt;a href=&quot;http://dev.w3.org/html5/spec/Overview.html#event-pageshow&quot;&gt;&lt;code&gt;onpageshow&lt;/code&gt;&lt;/a&gt; event.  This fires whenever a page is displayed rather than when it is loaded.  There is currently support for &lt;code&gt;onpageshow&lt;/code&gt; in Firefox and Chrome, but not in Opera, so we&#039;ll use the &lt;a href=&quot;http://kangax.github.com/iseventsupported/&quot;&gt;iseventsupported&lt;/a&gt; script to detect support and fall back to onload if it&#039;s not available:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;if (isEventSupported(&#039;pageshow&#039;)) {
    window.addEventListener(&#039;pageshow&#039;, gameStart, false);
} else {
    window.addEventListener(&#039;load&#039;, gameStart, false);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;We&#039;ll also do some extra work in the &lt;code&gt;gameStart&lt;/code&gt; function to clear and reinstate the timeout and, since the autofocus attribute gets ignored in &lt;code&gt;onpageshow&lt;/code&gt;, focus the input field:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var gameStart = function () {
    window.clearInterval(cdInterval);
    window.clearTimeout(cdTimeout);
    var em = document.getElementById(&#039;email&#039;);
    var cd = document.getElementById(&#039;countdown&#039;);
    var sc = document.getElementById(&#039;score&#039;);
	cd.value = 10;
	sc.value = 0;
	em.value = &#039;&#039;;
    em.readOnly = false;
    cdInterval = window.setInterval(counter,1000, cd, sc, em);
    cdTimeout = window.setTimeout(gameOver,10000, cd, sc, em);
    em.focus();
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Missing from the first version of the game is any way to restart or replay.  Let&#039;s start off by adding a reset button to the form:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;input id=&quot;restart&quot; type=&quot;reset&quot; value=&quot;New Game&quot;&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;There are some obvious issues with this, not least that the form reset isn&#039;t going to remove the countdown and game over timeouts.  However, rather than deal with that by hooking the event in a sensible way, we&#039;re going to take this opportunity to investigate an interesting feature of the &lt;code&gt;output&lt;/code&gt; element, the &lt;code&gt;defaultValue&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If you try clicking the reset button as it stands, this is what happens to the two output elements:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/emailgame/ff-output-nodefaults.png&quot; alt=&quot;Picture of the two output elements after a form reset&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The output element is something of a hybrid.  Although it can be created, declaratively, in markup, it isn&#039;t really any use without JavaScript.  While not a direct consequence of this state of affairs, it therefore doesn&#039;t matter that there&#039;s no way to set the default value of an output element in the HTML, you have to do it with JavaScript using the defaultValue property in the DOM.  Let&#039;s add a function to set up these fields correctly which will be run onload:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var gameSetup = function() {
    document.getElementById(&#039;countdown&#039;).defaultValue = &quot;10&quot;;
    document.getElementById(&#039;score&#039;).defaultValue = &quot;0&quot;;
    document.getElementById(&#039;restart&#039;).addEventListener(&#039;click&#039;, gameStart, false);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;You&#039;ll note that there&#039;s also an onclick handler added to the button to restart the game.  The reason we don&#039;t want to capture the form reset event itself is that we&#039;re going to use the form reset method within gameStart.  These three lines of code:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;cd.value = 10;
sc.value = 0;
em.value = &#039;&#039;;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Will become this one line of code:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;document.getElementById(&#039;game&#039;).reset();&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;But now resetting the form will restore the output fields to their defaultValue, as can been seen in the &lt;a href=&quot;http://www.boogdesign.com/examples/forms2/email-game-2.html&quot;&gt;second checkpoint&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/emailgame/ff-output-defaults.png&quot; alt=&quot;Picture of the two output elements after a form reset now that they have defaultValue set&quot; /&gt;&lt;/p&gt;

&lt;p&gt;For the third iteration we&#039;re going to concentrate on user feedback.  This is going to involve both HTML5 and CSS3:&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;Using the &lt;code&gt;onforminput&lt;/code&gt; event to update the score immediately&lt;/li&gt;
  &lt;li&gt;Giving instant feedback on the current validity of the email with CSS3&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;So far feedback to the user happens every second, in the counter function.  Instead of updating the the score every second let&#039;s update it every time the input changes.  There are a number of options in HTML4 already for handling this - we could attach an event to the email field and monitor it for changes, however HTML5 (for now) presents us with another option: &lt;code&gt;onforminput&lt;/code&gt;.  Instead of being associated with the input field, the item being updated, &lt;code&gt;onforminput&lt;/code&gt; can be associated with the output element, the item we want to update:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;document.getElementById(&#039;score&#039;).addEventListener(&#039;forminput&#039;, updateScore, false);&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Because the output element is the target, the update score function looks like this:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var updateScore = function(ev) {
    ev.target.value = calcScore(document.getElementById(&#039;email&#039;).value);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Unfortunately it seems that &lt;code&gt;onforminput&lt;/code&gt; may be &lt;a href=&quot;http://www.w3.org/Bugs/Public/show_bug.cgi?id=11129&quot;&gt;dropped from HTML5&lt;/a&gt;, so we&#039;d better check for support and fall back to capturing any &lt;code&gt;oninput&lt;/code&gt; event on the whole form through event bubbling:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;if (isEventSupported(&#039;forminput&#039;)) {
    document.getElementById(&#039;score&#039;).addEventListener(&#039;forminput&#039;, updateScore, false);
} else {
    document.getElementById(&#039;game&#039;).addEventListener(&#039;input&#039;, updateGlobalScore, false);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;This does complicate the function to update the score as the target of the event is no longer the output element, it&#039;s whatever input element has been updated.  At least in our simple case there&#039;s only one input element so we can use the &lt;code&gt;ev.target&lt;/code&gt; shortcut, just on the other side of the assignment:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var updateGlobalScore = function(ev) {
    document.getElementById(&#039;score&#039;).value = calcScore(ev.target.value);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;If you&#039;ve been following along in Firefox you will have seen that both provide some default styling for invalid fields:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/emailgame/ff-invalid.png&quot; alt=&quot;Default invalid field in Firefox&quot; /&gt;&lt;/p&gt;

&lt;p&gt;However Chrome (top) and Opera (bottom) don&#039;t show any indication:&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/emailgame/chrome-invalid.png&quot; alt=&quot;default invalid field in Chrome&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img class=&quot;screenshot&quot; src=&quot;http://www.boogdesign.com/images/blog/emailgame/opera-invalid.png&quot; alt=&quot;Default invalid field in Opera&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Let&#039;s apply some styles explicitly to make everything consistent across browsers:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;input[type=email]:invalid {
    box-shadow: none;
    background-color: rgba(255,0,0,0.5);
}
input[type=email]:valid {
    box-shadow: none;
    background-color: rgba(0,255,0,0.5);
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The &lt;code&gt;box-shadow&lt;/code&gt; overrides the Firefox default, while the &lt;code&gt;background-color&lt;/code&gt; will be applied in all three browsers, as you can see in the &lt;a href=&quot;http://www.boogdesign.com/examples/forms2/email-game-3.html&quot;&gt;third checkpoint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The game is now functionally complete, but before we wrap this up I&#039;d like to use one further iteration to examine the &lt;code&gt;checkValidity&lt;/code&gt; method more closely.  Here&#039;s what the spec says about &lt;code&gt;checkValidity&lt;/code&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Returns true if the element&#039;s value has no validity problems; false otherwise. Fires an invalid event at the element in the latter case.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;We only perform additional work  so, instead of using the boolean return value of the function to guide or logic, we could make the end of the game event driven.  First we&#039;ll simplify the &lt;code&gt;gameOver&lt;/code&gt; function, as all we need to do there now is ensure the event gets triggered if the email is invalid (and, thanks to &lt;code&gt;onforminput&lt;/code&gt;, we know the score will always be up to date):&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var gameOver = function (cd, sc, em) {
    window.clearInterval(cdInterval);
    cd.value = 0;
    em.checkValidity();
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Now we need to declare an function to handle the &lt;code&gt;oninvalidevent&lt;/code&gt;, I&#039;ve chosen to name it in tribute to cheesy European rock:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;var theFinalCountdown = function(e) {
    document.getElementById(&#039;score&#039;).value = 0;
    window.alert(&quot;You lose!&quot;);
    e.target.readOnly = true;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Then we attach it to the &lt;code&gt;oninvalid&lt;/code&gt; of the email field:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;document.getElementById(&#039;email&#039;).addEventListener(&#039;invalid&#039;, theFinalCountdown, false);&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Thus concludes my slightly erratic tour through HTML5 form features with the &lt;a href=&quot;http://www.boogdesign.com/examples/forms2/email-game-4.html&quot;&gt;final checkpoint&lt;/a&gt;.  If you&#039;ve enjoyed this please check out the more extensive &lt;a href=&quot;http://affiliate.manning.com/idevaffiliate.php?id=1155_240&quot;&gt;introduction to HTML5 Forms in Chapter 3 of my book&lt;/a&gt;.&lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=forms&quot;&gt;forms&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=html5&quot;&gt;html5&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=standardsnext&quot;&gt;standardsnext&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;Fun with HTML5 Forms&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;amp;title=Fun with HTML5 Forms&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;amp;title=Fun with HTML5 Forms&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;amp;t=Fun with HTML5 Forms&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=Fun with HTML5 Forms&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;amp;t=Fun with HTML5 Forms&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Fun with HTML5 Forms&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;amp;Title=Fun with HTML5 Forms&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=Fun with HTML5 Forms+http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>There have been many blog posts describing all the new elements and input types HTML5 provides, check out <a href="http://24ways.org/2009/have-a-field-day-with-html5-forms">this 24ways post for a good summary</a>, or you could even <a href="http://affiliate.manning.com/idevaffiliate.php?id=1155_240">read chapter 3 of my book</a>.  In this post I'm going to focus instead on the validation API and some related HTML5 features by building a simple game based on entering an email address.  The goal is to explore some HTML5 features rather than do everything in the most straightforward way, but there should be some practically useful code snippets.</p>

<p>The form itself is going to be very straightforward:</p><blockquote><pre><code>&lt;form id="game"&gt;
    &lt;fieldset&gt;
        &lt;legend&gt;Enter a valid email address before the timer runs down&lt;/legend&gt;
        &lt;label for="email"&gt;Email&lt;/label&gt;
        &lt;input id="email" type="email" autofocus required&gt;
    &lt;/fieldset&gt;
    &lt;label for="countdown"&gt;You have
        &lt;output id="countdown"&gt;10&lt;/output&gt;
        seconds.
    &lt;/label&gt;
    &lt;label for="score"&gt;You have
        &lt;output id="score"&gt;0&lt;/output&gt;
        points.
    &lt;/label&gt;
&lt;/form&gt;</code></pre></blockquote><p>In the initial version we will take advantage of three HTML5 features:</p><ul>
  <li>The <code>output</code> element</li>
  <li>The <code>email</code> input type</li>
  <li>The <code>checkValidity</code> method from the the HTML5 Form Validation API</li></ul><p>In the countdown function we use the value property of the the output element  The output element is something like a <code>span</code>, it's a start and end tag with arbitrary content, but you can access the contents using the <code>value</code> attribute like a form field :</p><blockquote><pre><code>var counter = function (cd, sc, em) {
    cd.value -= 1;
    sc.value = calcScore(em.value);
}</code></pre></blockquote><p>This may not look particularly helpful, but consider what the code would look like without the output element (or in a browser which doesn't support output):</p><blockquote><pre><code>var counter = function (cd, sc, em) {
    var count = cd.innerHTML;
	count -= 1;
    cd.innerHTML = count;
	sc.innerHTML = calcScore(em.innerHTML);
}</code></pre></blockquote><p>The function is now mostly about the details of manipulating the DOM, rather than the more straightforward algebraic style of the original.  Granted, libraries like jQuery have for a long time provided abstractions which allow you to write this code more cleanly but, like design patterns, these are as much an indication of the lack of expressiveness in the underlying platform as they are examples of best practice.</p>

<p>The game needs a function to calculate a 'score' from the email address.  This is, of course, completely arbitrary:</p><blockquote><pre><code>
function calcScore(email) {
    var s = 0;
    s += email.length;
    s += email.indexOf('@')>-1?email.indexOf('@'):0;
    s += email.lastIndexOf('.')>-1?email.lastIndexOf('.'):0;
    return s;
}</code></pre></blockquote>

<p>Now we need to wire up the functions to appropriate events when the game starts. To keep things simple I'm going to store a reference to the interval in a global variable:</p><blockquote><pre><code>var cdInterval;
var gameStart = function () {
    window.clearInterval(cdInterval);
    var em = document.getElementById('email');
    var cd = document.getElementById('countdown');
    var sc = document.getElementById('score');
    cd.value = 10;
    sc.value = 0;
    em.value = '';
    em.readOnly = false;
    cdInterval = window.setInterval(counter,1000, cd, sc, em);
    window.setTimeout(gameOver,10000, cd, sc, em);
}</code></pre></blockquote><p>Again, this function takes advantage of the value attribute on the output elements.  The last line calls a <code>gameOver</code> function after ten seconds, we'll use that to clear the interval and calculate the score.  The <code>checkValidity</code> method of the email field will be used to determine if the email address is currently valid:</p><blockquote><pre><code>var gameOver = function (cd, sc, em) {
    window.clearInterval(cdInterval);
    var score = calcScore(em.value);
    if (!em.checkValidity()) {
        score = 0;
        window.alert("You lose!");
    }
    cd.value = 0;
    sc.value = score;
    em.readOnly = true;
}</code></pre></blockquote><p>The <code>checkValidity()</code> method is part of the HTML5 validation API, it returns <code>true</code> if the browser understands the contents of the field as a valid email.  Note that we are able to call this method without submitting the form, so it is easy to hook form submission into a custom validation function if we want.  At no point do we have to implement any code to determine what a valid email address would be.  This is a second major saving, have a look at this regular expression example if you thought that code was straightforward:</p><blockquote><pre><code>(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])</code></pre></blockquote>

<p>Finally, start the game when the page loads:</p><blockquote><pre><code>window.addEventListener('load', gameStart, false);</code></pre></blockquote><p>The <a href="http://www.boogdesign.com/examples/forms2/email-game-1.html">first version of the game</a> will work in Opera, and the development versions of Firefox (4 - relevant bugs are <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=345624">345624</a> and <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=346485">346485</a> ) and Chrome (9 - relevant bugs are <a href="https://bugs.webkit.org/show_bug.cgi?id=27452">27452</a> and <a href="https://bugs.webkit.org/show_bug.cgi?id=29363">29363</a>).  If you want it to work on older versions of Chrome and Safari then you'll need to replace the output based syntax with the <code>innerHTML</code> approach as per the alternate version of <code>counter</code> above.</p>

<p>For the second iteration we're going to look at these two features:</p><ul>
  <li>Using the pageshow event from the History API</li>
  <li>How to reset <code>output</code> elements</li>
</ul><p>If the user visits another page after completing the game and then goes back then the game will sit there inert until you reload the page.  This is because the game logic hangs off the <code>onload</code> event, and navigating forward and backwards in the browser history doesn't fire <code>onload</code>.  The HTML5 History API gives us another option: the <a href="http://dev.w3.org/html5/spec/Overview.html#event-pageshow"><code>onpageshow</code></a> event.  This fires whenever a page is displayed rather than when it is loaded.  There is currently support for <code>onpageshow</code> in Firefox and Chrome, but not in Opera, so we'll use the <a href="http://kangax.github.com/iseventsupported/">iseventsupported</a> script to detect support and fall back to onload if it's not available:</p><blockquote><pre><code>if (isEventSupported('pageshow')) {
    window.addEventListener('pageshow', gameStart, false);
} else {
    window.addEventListener('load', gameStart, false);
}</code></pre></blockquote><p>We'll also do some extra work in the <code>gameStart</code> function to clear and reinstate the timeout and, since the autofocus attribute gets ignored in <code>onpageshow</code>, focus the input field:</p><blockquote><pre><code>var gameStart = function () {
    window.clearInterval(cdInterval);
    window.clearTimeout(cdTimeout);
    var em = document.getElementById('email');
    var cd = document.getElementById('countdown');
    var sc = document.getElementById('score');
	cd.value = 10;
	sc.value = 0;
	em.value = '';
    em.readOnly = false;
    cdInterval = window.setInterval(counter,1000, cd, sc, em);
    cdTimeout = window.setTimeout(gameOver,10000, cd, sc, em);
    em.focus();
}</code></pre></blockquote><p>Missing from the first version of the game is any way to restart or replay.  Let's start off by adding a reset button to the form:</p><blockquote><pre><code>&lt;input id="restart" type="reset" value="New Game"&gt;</code></pre></blockquote><p>There are some obvious issues with this, not least that the form reset isn't going to remove the countdown and game over timeouts.  However, rather than deal with that by hooking the event in a sensible way, we're going to take this opportunity to investigate an interesting feature of the <code>output</code> element, the <code>defaultValue</code>.</p>

<p>If you try clicking the reset button as it stands, this is what happens to the two output elements:</p>

<p><img class="screenshot" src="http://www.boogdesign.com/images/blog/emailgame/ff-output-nodefaults.png" alt="Picture of the two output elements after a form reset" /></p>

<p>The output element is something of a hybrid.  Although it can be created, declaratively, in markup, it isn't really any use without JavaScript.  While not a direct consequence of this state of affairs, it therefore doesn't matter that there's no way to set the default value of an output element in the HTML, you have to do it with JavaScript using the defaultValue property in the DOM.  Let's add a function to set up these fields correctly which will be run onload:</p><blockquote><pre><code>var gameSetup = function() {
    document.getElementById('countdown').defaultValue = "10";
    document.getElementById('score').defaultValue = "0";
    document.getElementById('restart').addEventListener('click', gameStart, false);
}</code></pre></blockquote><p>You'll note that there's also an onclick handler added to the button to restart the game.  The reason we don't want to capture the form reset event itself is that we're going to use the form reset method within gameStart.  These three lines of code:</p><blockquote><pre><code>cd.value = 10;
sc.value = 0;
em.value = '';</code></pre></blockquote><p>Will become this one line of code:</p><blockquote><pre><code>document.getElementById('game').reset();</code></pre></blockquote><p>But now resetting the form will restore the output fields to their defaultValue, as can been seen in the <a href="http://www.boogdesign.com/examples/forms2/email-game-2.html">second checkpoint</a>:</p>

<p><img class="screenshot" src="http://www.boogdesign.com/images/blog/emailgame/ff-output-defaults.png" alt="Picture of the two output elements after a form reset now that they have defaultValue set" /></p>

<p>For the third iteration we're going to concentrate on user feedback.  This is going to involve both HTML5 and CSS3:</p><ul>
  <li>Using the <code>onforminput</code> event to update the score immediately</li>
  <li>Giving instant feedback on the current validity of the email with CSS3</li>
</ul><p>So far feedback to the user happens every second, in the counter function.  Instead of updating the the score every second let's update it every time the input changes.  There are a number of options in HTML4 already for handling this - we could attach an event to the email field and monitor it for changes, however HTML5 (for now) presents us with another option: <code>onforminput</code>.  Instead of being associated with the input field, the item being updated, <code>onforminput</code> can be associated with the output element, the item we want to update:</p><blockquote><pre><code>document.getElementById('score').addEventListener('forminput', updateScore, false);</code></pre></blockquote><p>Because the output element is the target, the update score function looks like this:</p><blockquote><pre><code>var updateScore = function(ev) {
    ev.target.value = calcScore(document.getElementById('email').value);
}</code></pre></blockquote><p>Unfortunately it seems that <code>onforminput</code> may be <a href="http://www.w3.org/Bugs/Public/show_bug.cgi?id=11129">dropped from HTML5</a>, so we'd better check for support and fall back to capturing any <code>oninput</code> event on the whole form through event bubbling:</p><blockquote><pre><code>if (isEventSupported('forminput')) {
    document.getElementById('score').addEventListener('forminput', updateScore, false);
} else {
    document.getElementById('game').addEventListener('input', updateGlobalScore, false);
}</code></pre></blockquote><p>This does complicate the function to update the score as the target of the event is no longer the output element, it's whatever input element has been updated.  At least in our simple case there's only one input element so we can use the <code>ev.target</code> shortcut, just on the other side of the assignment:</p>
<blockquote><pre><code>var updateGlobalScore = function(ev) {
    document.getElementById('score').value = calcScore(ev.target.value);
}</code></pre></blockquote><p>If you've been following along in Firefox you will have seen that both provide some default styling for invalid fields:</p>

<p><img class="screenshot" src="http://www.boogdesign.com/images/blog/emailgame/ff-invalid.png" alt="Default invalid field in Firefox" /></p>

<p>However Chrome (top) and Opera (bottom) don't show any indication:</p>

<p><img class="screenshot" src="http://www.boogdesign.com/images/blog/emailgame/chrome-invalid.png" alt="default invalid field in Chrome" /></p>

<p><img class="screenshot" src="http://www.boogdesign.com/images/blog/emailgame/opera-invalid.png" alt="Default invalid field in Opera" /></p>

<p>Let's apply some styles explicitly to make everything consistent across browsers:</p><blockquote><pre><code>input[type=email]:invalid {
    box-shadow: none;
    background-color: rgba(255,0,0,0.5);
}
input[type=email]:valid {
    box-shadow: none;
    background-color: rgba(0,255,0,0.5);
}</code></pre></blockquote><p>The <code>box-shadow</code> overrides the Firefox default, while the <code>background-color</code> will be applied in all three browsers, as you can see in the <a href="http://www.boogdesign.com/examples/forms2/email-game-3.html">third checkpoint</a>.</p>

<p>The game is now functionally complete, but before we wrap this up I'd like to use one further iteration to examine the <code>checkValidity</code> method more closely.  Here's what the spec says about <code>checkValidity</code>:</p><blockquote><p>Returns true if the element's value has no validity problems; false otherwise. Fires an invalid event at the element in the latter case.</p></blockquote><p>We only perform additional work  so, instead of using the boolean return value of the function to guide or logic, we could make the end of the game event driven.  First we'll simplify the <code>gameOver</code> function, as all we need to do there now is ensure the event gets triggered if the email is invalid (and, thanks to <code>onforminput</code>, we know the score will always be up to date):</p><blockquote><pre><code>var gameOver = function (cd, sc, em) {
    window.clearInterval(cdInterval);
    cd.value = 0;
    em.checkValidity();
}</code></pre></blockquote><p>Now we need to declare an function to handle the <code>oninvalidevent</code>, I've chosen to name it in tribute to cheesy European rock:</p><blockquote><pre><code>var theFinalCountdown = function(e) {
    document.getElementById('score').value = 0;
    window.alert("You lose!");
    e.target.readOnly = true;
}</code></pre></blockquote><p>Then we attach it to the <code>oninvalid</code> of the email field:</p><blockquote><pre><code>document.getElementById('email').addEventListener('invalid', theFinalCountdown, false);</code></pre></blockquote><p>Thus concludes my slightly erratic tour through HTML5 form features with the <a href="http://www.boogdesign.com/examples/forms2/email-game-4.html">final checkpoint</a>.  If you've enjoyed this please check out the more extensive <a href="http://affiliate.manning.com/idevaffiliate.php?id=1155_240">introduction to HTML5 Forms in Chapter 3 of my book</a>.</p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=forms">forms</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=html5">html5</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=standardsnext">standardsnext</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2')+'&amp;title='+encodeURIComponent('Fun with HTML5 Forms'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;title=Fun with HTML5 Forms" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;title=Fun with HTML5 Forms&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;t=Fun with HTML5 Forms" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=Fun with HTML5 Forms&amp;url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;t=Fun with HTML5 Forms" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Fun with HTML5 Forms&amp;u=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2&amp;Title=Fun with HTML5 Forms" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=Fun with HTML5 Forms+http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/fun-with-html5-forms?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=349</wfw:commentRss>
		</item>
				<item>
			<title>Hello! HTML5 and CSS3 - 50% Off Until 16th December</title>
			<link>http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2</link>
			<pubDate>Mon, 15 Nov 2010 23:22:02 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="alt">Front End Web Development</category>
<category domain="main">Standards, HTML and CSS</category>			<guid isPermaLink="false">358@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;Buy early access to my book &lt;a href=&quot;http://affiliate.manning.com/idevaffiliate.php?id=1155_240&quot;&gt;Hello! HTML5 and CSS3&lt;/a&gt; and get a 50% discount for the next month with the code &lt;strong&gt;html550&lt;/strong&gt;.  Coming soon will be the chapter on HTML5 Forms, which should be pretty useful for getting up to speed in time for the release of &lt;a href=&quot;https://developer.mozilla.org/en/HTML/HTML5/Forms_in_HTML5&quot;&gt;Firefox 4&lt;/a&gt;.&lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=books&quot;&gt;books&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=css3&quot;&gt;css3&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=html5&quot;&gt;html5&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;Hello! HTML5 and CSS3 - 50% Off Until 16th December&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;amp;title=Hello! HTML5 and CSS3 - 50% Off Until 16th December&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;amp;title=Hello! HTML5 and CSS3 - 50% Off Until 16th December&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;amp;t=Hello! HTML5 and CSS3 - 50% Off Until 16th December&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=Hello! HTML5 and CSS3 - 50% Off Until 16th December&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;amp;t=Hello! HTML5 and CSS3 - 50% Off Until 16th December&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Hello! HTML5 and CSS3 - 50% Off Until 16th December&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;amp;Title=Hello! HTML5 and CSS3 - 50% Off Until 16th December&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=Hello! HTML5 and CSS3 - 50% Off Until 16th December+http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>Buy early access to my book <a href="http://affiliate.manning.com/idevaffiliate.php?id=1155_240">Hello! HTML5 and CSS3</a> and get a 50% discount for the next month with the code <strong>html550</strong>.  Coming soon will be the chapter on HTML5 Forms, which should be pretty useful for getting up to speed in time for the release of <a href="https://developer.mozilla.org/en/HTML/HTML5/Forms_in_HTML5">Firefox 4</a>.</p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=books">books</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=css3">css3</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=html5">html5</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2')+'&amp;title='+encodeURIComponent('Hello! HTML5 and CSS3 - 50% Off Until 16th December'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;title=Hello! HTML5 and CSS3 - 50% Off Until 16th December" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;title=Hello! HTML5 and CSS3 - 50% Off Until 16th December&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;t=Hello! HTML5 and CSS3 - 50% Off Until 16th December" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=Hello! HTML5 and CSS3 - 50% Off Until 16th December&amp;url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;t=Hello! HTML5 and CSS3 - 50% Off Until 16th December" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Hello! HTML5 and CSS3 - 50% Off Until 16th December&amp;u=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2&amp;Title=Hello! HTML5 and CSS3 - 50% Off Until 16th December" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=Hello! HTML5 and CSS3 - 50% Off Until 16th December+http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/hello-html5-and-css3-50-off-until-16th-december?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=358</wfw:commentRss>
		</item>
				<item>
			<title>Firefox 4.0 Features for Font Fanatics</title>
			<link>http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2</link>
			<pubDate>Tue, 20 Jul 2010 14:17:50 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="main">Standards, HTML and CSS</category>			<guid isPermaLink="false">342@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;If you&#039;re following the development of CSS3 you may have seen, last June, a proposal from John Daggett of Mozilla to bring &lt;a href=&quot;http://lists.w3.org/Archives/Public/www-style/2009Jun/0506.html&quot;&gt;advanced typography control to the web&lt;/a&gt;.  A few months later we saw some &lt;a href=&quot;http://hacks.mozilla.org/2009/10/font-control-for-designers/&quot;&gt;experimental Firefox builds&lt;/a&gt; which demonstrated the features.  The &lt;a href=&quot;http://dev.w3.org/csswg/css3-fonts/#font-feature-settings-prop&quot;&gt;terminology has been through a slight update since then&lt;/a&gt;, from &lt;code&gt;font-feature-opentype&lt;/code&gt; to &lt;code&gt;font-feature-settings&lt;/code&gt;, but &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=511339&quot;&gt;last week these experiments&lt;/a&gt; finally made their way into the &lt;a href=&quot;http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/&quot;&gt;trunk builds of Firefox 4.0&lt;/a&gt; on Windows and Mac.&lt;/p&gt;

&lt;p&gt;Even though it &lt;a href=&quot;https://bugzilla.mozilla.org/show_bug.cgi?id=569770&quot;&gt;doesn&#039;t yet work under Linux&lt;/a&gt;, I thought it was time to start investigating.  In this post I&#039;m going to have a look at what these features can look like, mostly following the examples from the October Mozilla Hacks blog post put using the &lt;a href=&quot;http://www.josbuivenga.demon.nl/calluna.html&quot;&gt;Calluna Regular&lt;/a&gt; font.  Then I&#039;ll show how to turn them on and off in Firefox with CSS, and find the various features using a font editor.&lt;/p&gt;

&lt;h4&gt;Open Type Font Features&lt;/h4&gt;

&lt;p&gt;A font is a collection of glyphs, graphical representations of letters, which are associated with characters.  Font features are a scheme for getting alternative glyphs for a given character or sequence of characters.  The full &lt;a href=&quot;http://www.microsoft.com/typography/otspec/featurelist.htm&quot;&gt;list of open type features is available in the spec&lt;/a&gt;.  Each feature is associated with a four character identifier and can be set to on (1) or off (0), here&#039;s an example CSS rule:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.example {
    font-feature-settings: &quot;dlig=1,tnum=1,ss01=1&quot;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;In the current Firefox 4.0 nightly builds you can enable support for the features below by setting the gfx.font_rendering.harfbuzz.level preference to 1 in about:config.&lt;/p&gt;

&lt;h4&gt;Ligatures&lt;/h4&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/liga-fb.png&quot; alt=&quot;the characters fb with and without standard ligatures&quot; class=&quot;screenshot&quot; style=&quot;float: right;&quot; /&gt;Ligatures are special glyphs which replace runs of commonly occurring characters.  There are two levels of ligatures, the standard ligatures are turned on by default in Firefox 4.0.  To the left is an example in Calluna.  The image on the left is from Firefox 3.6, on the right is Firefox 4.0, you can see the slight different where the two characters connect at the top.  the combined glyph is also slightly narrower but that&#039;s quite hard to stop.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/liga-ffb.png&quot; alt=&quot;the characters ffb with and without standard ligatures&quot; class=&quot;screenshot&quot; style=&quot;clear: right; float: right; margin-top: 1em;&quot; /&gt;  The second example is slightly more obviously different, though with Calluna being a refined font they&#039;re still quite subtle.  Again it&#039;s Firefox 3.6 on the right and 4.0 on the left, the first &#039;f&#039; is noticeably smaller than the standard one and there&#039;s a single bar across both &#039;f&#039; characters.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/liga-arrows.png&quot; alt=&quot;the characters - /&gt; and -&gt;&gt; with and without standard ligatures&quot; class=&quot;screenshot&quot; style=&quot;clear: right; float: right; margin-top: 1em;&quot; /&gt;There are some ligatures which don&#039;t map to commonly occurring sequences of characters (I know fb might not strike you as particularly common, &lt;a href=&quot;http://www.morewords.com/pair/fb/&quot;&gt;but there are at least 26 just in English&lt;/a&gt;).  Calluna has two whole sets of arrow glyphs which replace sequences like &#039;--&gt;&gt;&#039; and &#039;--&gt;&#039;, more examples to the right.&lt;/p&gt;

&lt;p&gt;So in Firefox 4.0, if the font being used supports standard ligatures, you&#039;ll see them.  If you want to give directions to Firefox users which will appear like random sequences of dashes and greater thans to everyone else you now can.  But that&#039;s not all!  There&#039;s also a more decorative set of combinations called discretionary ligatures.  Here&#039;s some examples, normal on the left, discretionary ligatures on the right:&lt;/p&gt;&lt;ul style=&quot;list-style: none; margin: 0; padding: 0;&quot;&gt;
  &lt;li style=&quot;display: inline-block;&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/dlig-ct.png&quot; alt=&quot;ct with and without discretionary ligatures&quot; class=&quot;screenshot&quot; style=&quot;float: left;&quot; /&gt;&lt;/li&gt;
  &lt;li style=&quot;display: inline-block;&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/dlig-qu.png&quot; alt=&quot;qu with and without discretionary ligatures&quot; class=&quot;screenshot&quot; style=&quot;float: left;&quot; /&gt;&lt;/li&gt;
  &lt;li style=&quot;display: inline-block;&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/dlig-sh.png&quot; alt=&quot;sh with and without discretionary ligatures&quot; class=&quot;screenshot&quot; style=&quot;float: left;&quot; /&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;The point of all this is, of course, that it can all be controlled through CSS.  I&#039;ve constructed an example sentence which could easily occur in conversation at any time and just so happens to contain plenty of words which show off our ligatures.  First, let&#039;s see what it looks like with everything disabled:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-alloff.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-alloff-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;A sample sentence in Calluna with all ligature features turned off&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here&#039;s the code to disable the standard ligatures in Firefox 4.0 using &lt;code&gt;-moz-font-feature-settings&lt;/code&gt;:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.alloff {
    -moz-font-feature-settings: &quot;liga=0&quot;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;The ligature feature is called &lt;code&gt;liga&lt;/code&gt;.  As I mentioned above, we can set it to &lt;code&gt;1&lt;/code&gt; to enable (which is the default in Firefox 4.0) and &lt;code&gt;0&lt;/code&gt; to disable.  For comparison let&#039;s have a look at the standard Firefox 4.0 rendering:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-normal.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-normal-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;A sample sentence in Calluna with default ligature features&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CSS for this is straightforward as, of course, there isn&#039;t any:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.normal {
    /* it&#039;s normal, no setting required...*/
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Now let&#039;s turn on the discretionary ligatures:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-allon.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-allon-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;A sample sentence in Calluna with all ligature features turned on&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The discretionary ligature feature is called &lt;code&gt;dlig&lt;/code&gt;, again it&#039;s &lt;code&gt;1&lt;/code&gt; to enable and &lt;code&gt;0&lt;/code&gt; to disable:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.allon {
    -moz-font-feature-settings: &quot;dlig=1&quot;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;It could be that, for some reason, you want the discretionary ligatures but not the standard ones:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-discretionary.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-discretionary-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;A sample sentence in Calluna with just discretionary ligature features turned on&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Probably not much point with Calluna, but perhaps with a more decorative typeface this would be useful.  You can pass several features to &lt;code&gt;-moz-font-feature-settings&lt;/code&gt; in a comma separated list:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.discretionary {
    -moz-font-feature-settings: &quot;liga=0,dlig=1&quot;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;How do you go about finding all these ligatures, standard or discretionary?  I used &lt;a href=&quot;http://fontforge.sourceforge.net/&quot;&gt;FontForge&lt;/a&gt; because it was easily installable on my laptop using &lt;a href=&quot;http://yum.baseurl.org/&quot;&gt;yum&lt;/a&gt;, the interface is a bit archaic but it seems perfectly functional.  Here&#039;s what it looks like after I&#039;ve opened up the Calluna font:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna in FontForge&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On the view menu there&#039;s a combinations sub-menu upon which the ligatures option lives:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-menu-ligatures.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-menu-ligatures-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;FontForge selecting ligatures from the Combinations sub-menu of the View menu&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have a list of ligatures to choose from:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligatures.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligatures-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;FontForge ligatures window&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I opened up the &#039;ffb&#039; ligature:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligature-ffb.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligature-ffb-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna f_f_b glyph in FontForge&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now go to the view menu again and look up the Glyph Info option:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;FontForge selecting Glyph Info from the Element menu&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the resulting dialogue you can see that &#039;ffb&#039; is part of the set of standard ligatures:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-subtable.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-subtable-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna in FontForge, Glyph Info for f_f_b&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If instead I open up the &#039;sk&#039; glyph you can see this is part of the discretionary ligature set:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-sk-dlig.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-sk-dlig-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna in FontForge, Glyph Info for s_k&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;Numerals&lt;/h4&gt;

&lt;p&gt;Now that we&#039;ve had some fun with ligatures you may be wondering what other cool tricks are hidden inside open type fonts.  One very practical feature is different styles of numbers.  Quick pop quiz time, which is the highest number in the screenshot below?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-default.png&quot; class=&quot;screenshot&quot; alt=&quot;Numbers in Calluna, default settings&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Did you guess it was the second one, or did you have to count carefully?  Numbers by default are proportionally spaced, which looks nice when they appear in text but can be misleading when looking at tables of figures.  But now, thanks to &lt;code&gt;-moz-font-feature-settings&lt;/code&gt;, we have some other options:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-tabular.png&quot; class=&quot;screenshot&quot; alt=&quot;Numbers in Calluna, tabular figures&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The numbers are now using tabular alignment - each number glyph is an equal width.  Tabular numerals use the &lt;code&gt;tnum&lt;/code&gt; feature:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.tabular {
    -moz-font-feature-settings: &quot;tnum=1&quot;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;There are a few other number features.  The default numbers in Calluna are &#039;old style&#039; (&lt;code&gt;onum&lt;/code&gt;), you can see there&#039;s quite a lot of variance caused by the descenders and ascenders going above and below the line.  The alternative to that is &#039;lining figures&#039; (&lt;code&gt;lnum&lt;/code&gt;):&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-lining.png&quot; class=&quot;screenshot&quot; alt=&quot;Numbers in Calluna, lining figures&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As you can see, they give a much more consistent line shape.  And you can also have tabular, lining numerals:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-tabular-lining.png&quot; class=&quot;screenshot&quot; alt=&quot;Numbers in Calluna, tabular lining figures&quot; /&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.tabular-lining {
    -moz-font-feature-settings: &quot;lnum=1,tnum=1&quot;;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Once again you can find all these alternatives in FontForge in the Glyph Info window:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-glyphinfo-one.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-glyphinfo-one-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna in FontForge, Glyph info window for 1&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before we finish up with numbers, two more features are worth mentioning.  You can control whether or not the zero is &#039;slashed&#039; with the &lt;code&gt;zero&lt;/code&gt; feature:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-zero.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna in FontForge&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The bottom number has &lt;code&gt;-moz-font-feature-settings: &quot;zero=1&quot;;&lt;/code&gt; applied.  You can also enable fractions with the &lt;code&gt;frac&lt;/code&gt; feature setting:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-frac.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna in FontForge&quot; /&gt;&lt;/p&gt;

&lt;h4&gt;Stylistic Alternatives&lt;/h4&gt;

&lt;p&gt;There&#039;s plenty more stuff in the open type spec, there are 134 different features listed in the spec I linked to in the introduction.  The really fancy bits of fonts are often in the twenty &#039;stylistic sets&#039; &lt;code&gt;ss01&lt;/code&gt; to &lt;code&gt;ss20&lt;/code&gt;.  You can find what options you may have in FontForge for a particular font by looking for the display substitutions option on the view menu:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-displaysubstitutions.png&quot; class=&quot;screenshot&quot; alt=&quot;Selecting the view menu in FontForge&quot; /&gt;&lt;/p&gt;

&lt;p&gt;You then get a dialogue with a list of the options:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-substitutions.png&quot; class=&quot;screenshot&quot; alt=&quot;FontForge substitutions dialogoue&quot; /&gt;&lt;/p&gt;

&lt;p&gt;From which you can see that Calluna only has glyphs for one of the stylistic sets, and when you select &lt;code&gt;ss01&lt;/code&gt; you&#039;ll see that there&#039;s not a lot of (regular) characters in that:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ss01.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ss01-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Calluna stylstic set 01 in FontForge&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;And there&#039;s more...&lt;/h4&gt;

&lt;p&gt;There&#039;s plenty of other interesting stuff wrapped up in open type font feature settings, we haven&#039;t yet discussed &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms745109.aspx#swashes&quot;&gt;swashes&lt;/a&gt;, &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms745109.aspx#CodeSnippetContainerCode12&quot;&gt;contextual alternates&lt;/a&gt; or &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms745109.aspx#CodeSnippetContainerCode13&quot;&gt;historical forms&lt;/a&gt; for just three examples, but I&#039;ll leave exploring those as an exercise for the reader.&lt;/p&gt;

&lt;h4&gt;Practical Considerations&lt;/h4&gt;

&lt;p&gt;It may seem slightly superfluous for me to mention this about a CSS feature which, so far, has only an experimental implementation in just one browser, but it would be unwise to build a site which depended on &lt;code&gt;font-feature-opentype&lt;/code&gt;, for example by relying on certain ligatures or stylistic sets to convey information.  However, for making your typography look a bit nicer for a subset of your users, this stuff will be usable on real web pages from the day of Firefox 4.0&#039;s release.&lt;/p&gt;

&lt;h4&gt;The Future&lt;/h4&gt;

&lt;p&gt;Now you&#039;re salivating for a future where all web browsers support &lt;code&gt;font-feature-settings&lt;/code&gt; this is probably a good time to point out that, once that support exists, you&#039;ll hardly ever use it &lt;img src=&quot;http://www.boogdesign.com/b2evo/rsc/smilies/icon_smile.gif&quot; title=&quot;&amp;amp;amp;#58;&amp;amp;amp;#41;&quot; alt=&quot;&amp;amp;amp;#58;&amp;amp;amp;#41;&quot; class=&quot;middle&quot; width=&quot;15&quot; height=&quot;15&quot; /&gt;  No, this is not a trick, &lt;code&gt;font-feature-settings&lt;/code&gt; itself is only intended to be used for obscure and little used options in the open font features list, the common stuff will be accessible through new values on the &lt;code&gt;font-variant&lt;/code&gt; property as well as several &lt;code&gt;font-variant-*&lt;/code&gt; properties.  The current level of support in Firefox is really only to see how things will look once all that gets implemented.&lt;/p&gt;

&lt;p&gt;Let&#039;s have a look at how a future you will be recreating my examples with the proposed &lt;code&gt;font-variant&lt;/code&gt; property extensions. First, discretionary ligatures:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.discretionary {
    font-variant: additional-ligatures;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Alternatively we cold use the specific ligatures property:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.discretionary {
    font-variant-ligatures: additional-ligatures;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Each value has a corresponding &lt;code&gt;no-*&lt;/code&gt; version, so you could specify &lt;code&gt;no-common-ligatures&lt;/code&gt; to turn off the common ones, or &lt;code&gt;no-additional-ligatures&lt;/code&gt; in order to override the above rule further down the inheritance chain.  What about lining, tabular numerals?&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;.tabular-lining {
    font-variant-numeric: lining-nums tabular-nums;
}&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;None of this is implemented yet, so I can&#039;t test I&#039;ve got it right, and all this syntax is still subject to change as the fonts module is still a working draft, so I&#039;ll stop there.  Hopefully this has given you some ideas for fancy typography to give Firefox 4.0 users a special treat and will set you off on your own investigations.&lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=css&quot;&gt;css&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=standardsnext&quot;&gt;standardsnext&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=typography&quot;&gt;typography&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;Firefox 4.0 Features for Font Fanatics&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;amp;title=Firefox 4.0 Features for Font Fanatics&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;amp;title=Firefox 4.0 Features for Font Fanatics&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;amp;t=Firefox 4.0 Features for Font Fanatics&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=Firefox 4.0 Features for Font Fanatics&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;amp;t=Firefox 4.0 Features for Font Fanatics&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Firefox 4.0 Features for Font Fanatics&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;amp;Title=Firefox 4.0 Features for Font Fanatics&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=Firefox 4.0 Features for Font Fanatics+http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>If you're following the development of CSS3 you may have seen, last June, a proposal from John Daggett of Mozilla to bring <a href="http://lists.w3.org/Archives/Public/www-style/2009Jun/0506.html">advanced typography control to the web</a>.  A few months later we saw some <a href="http://hacks.mozilla.org/2009/10/font-control-for-designers/">experimental Firefox builds</a> which demonstrated the features.  The <a href="http://dev.w3.org/csswg/css3-fonts/#font-feature-settings-prop">terminology has been through a slight update since then</a>, from <code>font-feature-opentype</code> to <code>font-feature-settings</code>, but <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=511339">last week these experiments</a> finally made their way into the <a href="http://ftp.mozilla.org/pub/mozilla.org/firefox/nightly/latest-trunk/">trunk builds of Firefox 4.0</a> on Windows and Mac.</p>

<p>Even though it <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=569770">doesn't yet work under Linux</a>, I thought it was time to start investigating.  In this post I'm going to have a look at what these features can look like, mostly following the examples from the October Mozilla Hacks blog post put using the <a href="http://www.josbuivenga.demon.nl/calluna.html">Calluna Regular</a> font.  Then I'll show how to turn them on and off in Firefox with CSS, and find the various features using a font editor.</p>

<h4>Open Type Font Features</h4>

<p>A font is a collection of glyphs, graphical representations of letters, which are associated with characters.  Font features are a scheme for getting alternative glyphs for a given character or sequence of characters.  The full <a href="http://www.microsoft.com/typography/otspec/featurelist.htm">list of open type features is available in the spec</a>.  Each feature is associated with a four character identifier and can be set to on (1) or off (0), here's an example CSS rule:</p><blockquote><pre><code>.example {
    font-feature-settings: "dlig=1,tnum=1,ss01=1";
}</code></pre></blockquote><p>In the current Firefox 4.0 nightly builds you can enable support for the features below by setting the gfx.font_rendering.harfbuzz.level preference to 1 in about:config.</p>

<h4>Ligatures</h4>

<p><img src="http://www.boogdesign.com/images/blog/fonts/liga-fb.png" alt="the characters fb with and without standard ligatures" class="screenshot" style="float: right;" />Ligatures are special glyphs which replace runs of commonly occurring characters.  There are two levels of ligatures, the standard ligatures are turned on by default in Firefox 4.0.  To the left is an example in Calluna.  The image on the left is from Firefox 3.6, on the right is Firefox 4.0, you can see the slight different where the two characters connect at the top.  the combined glyph is also slightly narrower but that's quite hard to stop.</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/liga-ffb.png" alt="the characters ffb with and without standard ligatures" class="screenshot" style="clear: right; float: right; margin-top: 1em;" />  The second example is slightly more obviously different, though with Calluna being a refined font they're still quite subtle.  Again it's Firefox 3.6 on the right and 4.0 on the left, the first 'f' is noticeably smaller than the standard one and there's a single bar across both 'f' characters.</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/liga-arrows.png" alt="the characters - /> and ->> with and without standard ligatures" class="screenshot" style="clear: right; float: right; margin-top: 1em;" />There are some ligatures which don't map to commonly occurring sequences of characters (I know fb might not strike you as particularly common, <a href="http://www.morewords.com/pair/fb/">but there are at least 26 just in English</a>).  Calluna has two whole sets of arrow glyphs which replace sequences like '-->>' and '-->', more examples to the right.</p>

<p>So in Firefox 4.0, if the font being used supports standard ligatures, you'll see them.  If you want to give directions to Firefox users which will appear like random sequences of dashes and greater thans to everyone else you now can.  But that's not all!  There's also a more decorative set of combinations called discretionary ligatures.  Here's some examples, normal on the left, discretionary ligatures on the right:</p><ul style="list-style: none; margin: 0; padding: 0;">
  <li style="display: inline-block;"><img src="http://www.boogdesign.com/images/blog/fonts/dlig-ct.png" alt="ct with and without discretionary ligatures" class="screenshot" style="float: left;" /></li>
  <li style="display: inline-block;"><img src="http://www.boogdesign.com/images/blog/fonts/dlig-qu.png" alt="qu with and without discretionary ligatures" class="screenshot" style="float: left;" /></li>
  <li style="display: inline-block;"><img src="http://www.boogdesign.com/images/blog/fonts/dlig-sh.png" alt="sh with and without discretionary ligatures" class="screenshot" style="float: left;" /></li>
</ul><p>The point of all this is, of course, that it can all be controlled through CSS.  I've constructed an example sentence which could easily occur in conversation at any time and just so happens to contain plenty of words which show off our ligatures.  First, let's see what it looks like with everything disabled:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-alloff.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-alloff-thumb.png" class="screenshot" alt="A sample sentence in Calluna with all ligature features turned off" /></a></p>

<p>Here's the code to disable the standard ligatures in Firefox 4.0 using <code>-moz-font-feature-settings</code>:</p><blockquote><pre><code>.alloff {
    -moz-font-feature-settings: "liga=0";
}</code></pre></blockquote>

<p>The ligature feature is called <code>liga</code>.  As I mentioned above, we can set it to <code>1</code> to enable (which is the default in Firefox 4.0) and <code>0</code> to disable.  For comparison let's have a look at the standard Firefox 4.0 rendering:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-normal.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-normal-thumb.png" class="screenshot" alt="A sample sentence in Calluna with default ligature features" /></a></p>

<p>The CSS for this is straightforward as, of course, there isn't any:</p><blockquote><pre><code>.normal {
    /* it's normal, no setting required...*/
}</code></pre></blockquote>

<p>Now let's turn on the discretionary ligatures:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-allon.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-allon-thumb.png" class="screenshot" alt="A sample sentence in Calluna with all ligature features turned on" /></a></p>

<p>The discretionary ligature feature is called <code>dlig</code>, again it's <code>1</code> to enable and <code>0</code> to disable:</p><blockquote><pre><code>.allon {
    -moz-font-feature-settings: "dlig=1";
}</code></pre></blockquote>

<p>It could be that, for some reason, you want the discretionary ligatures but not the standard ones:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-discretionary.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/ligatures-fontfeaturesettings-discretionary-thumb.png" class="screenshot" alt="A sample sentence in Calluna with just discretionary ligature features turned on" /></a></p>

<p>Probably not much point with Calluna, but perhaps with a more decorative typeface this would be useful.  You can pass several features to <code>-moz-font-feature-settings</code> in a comma separated list:</p><blockquote><pre><code>.discretionary {
    -moz-font-feature-settings: "liga=0,dlig=1";
}</code></pre></blockquote>

<p>How do you go about finding all these ligatures, standard or discretionary?  I used <a href="http://fontforge.sourceforge.net/">FontForge</a> because it was easily installable on my laptop using <a href="http://yum.baseurl.org/">yum</a>, the interface is a bit archaic but it seems perfectly functional.  Here's what it looks like after I've opened up the Calluna font:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-thumb.png" class="screenshot" alt="Calluna in FontForge" /></a></p>

<p>On the view menu there's a combinations sub-menu upon which the ligatures option lives:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-menu-ligatures.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-menu-ligatures-thumb.png" class="screenshot" alt="FontForge selecting ligatures from the Combinations sub-menu of the View menu" /></a></p>

<p>Now you have a list of ligatures to choose from:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligatures.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligatures-thumb.png" class="screenshot" alt="FontForge ligatures window" /></a></p>

<p>I opened up the 'ffb' ligature:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligature-ffb.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ligature-ffb-thumb.png" class="screenshot" alt="Calluna f_f_b glyph in FontForge" /></a></p>

<p>Now go to the view menu again and look up the Glyph Info option:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-thumb.png" class="screenshot" alt="FontForge selecting Glyph Info from the Element menu" /></a></p>

<p>In the resulting dialogue you can see that 'ffb' is part of the set of standard ligatures:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-subtable.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-subtable-thumb.png" class="screenshot" alt="Calluna in FontForge, Glyph Info for f_f_b" /></a></p>

<p>If instead I open up the 'sk' glyph you can see this is part of the discretionary ligature set:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-sk-dlig.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-glyphinfo-sk-dlig-thumb.png" class="screenshot" alt="Calluna in FontForge, Glyph Info for s_k" /></a></p>

<h4>Numerals</h4>

<p>Now that we've had some fun with ligatures you may be wondering what other cool tricks are hidden inside open type fonts.  One very practical feature is different styles of numbers.  Quick pop quiz time, which is the highest number in the screenshot below?</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-default.png" class="screenshot" alt="Numbers in Calluna, default settings" /></p>

<p>Did you guess it was the second one, or did you have to count carefully?  Numbers by default are proportionally spaced, which looks nice when they appear in text but can be misleading when looking at tables of figures.  But now, thanks to <code>-moz-font-feature-settings</code>, we have some other options:</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-tabular.png" class="screenshot" alt="Numbers in Calluna, tabular figures" /></p>

<p>The numbers are now using tabular alignment - each number glyph is an equal width.  Tabular numerals use the <code>tnum</code> feature:</p><blockquote><pre><code>.tabular {
    -moz-font-feature-settings: "tnum=1";
}</code></pre></blockquote><p>There are a few other number features.  The default numbers in Calluna are 'old style' (<code>onum</code>), you can see there's quite a lot of variance caused by the descenders and ascenders going above and below the line.  The alternative to that is 'lining figures' (<code>lnum</code>):</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-lining.png" class="screenshot" alt="Numbers in Calluna, lining figures" /></p>

<p>As you can see, they give a much more consistent line shape.  And you can also have tabular, lining numerals:</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-tabular-lining.png" class="screenshot" alt="Numbers in Calluna, tabular lining figures" /></p>

<blockquote><pre><code>.tabular-lining {
    -moz-font-feature-settings: "lnum=1,tnum=1";
}</code></pre></blockquote><p>Once again you can find all these alternatives in FontForge in the Glyph Info window:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-glyphinfo-one.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-glyphinfo-one-thumb.png" class="screenshot" alt="Calluna in FontForge, Glyph info window for 1" /></a></p>

<p>Before we finish up with numbers, two more features are worth mentioning.  You can control whether or not the zero is 'slashed' with the <code>zero</code> feature:</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-zero.png" class="screenshot" alt="Calluna in FontForge" /></p>

<p>The bottom number has <code>-moz-font-feature-settings: "zero=1";</code> applied.  You can also enable fractions with the <code>frac</code> feature setting:</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/numbers-fontfeaturesettings-frac.png" class="screenshot" alt="Calluna in FontForge" /></p>

<h4>Stylistic Alternatives</h4>

<p>There's plenty more stuff in the open type spec, there are 134 different features listed in the spec I linked to in the introduction.  The really fancy bits of fonts are often in the twenty 'stylistic sets' <code>ss01</code> to <code>ss20</code>.  You can find what options you may have in FontForge for a particular font by looking for the display substitutions option on the view menu:</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-displaysubstitutions.png" class="screenshot" alt="Selecting the view menu in FontForge" /></p>

<p>You then get a dialogue with a list of the options:</p>

<p><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-substitutions.png" class="screenshot" alt="FontForge substitutions dialogoue" /></p>

<p>From which you can see that Calluna only has glyphs for one of the stylistic sets, and when you select <code>ss01</code> you'll see that there's not a lot of (regular) characters in that:</p>

<p><a href="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ss01.png" title="Click for larger image"><img src="http://www.boogdesign.com/images/blog/fonts/fontforge-calluna-ss01-thumb.png" class="screenshot" alt="Calluna stylstic set 01 in FontForge" /></a></p>

<h4>And there's more...</h4>

<p>There's plenty of other interesting stuff wrapped up in open type font feature settings, we haven't yet discussed <a href="http://msdn.microsoft.com/en-us/library/ms745109.aspx#swashes">swashes</a>, <a href="http://msdn.microsoft.com/en-us/library/ms745109.aspx#CodeSnippetContainerCode12">contextual alternates</a> or <a href="http://msdn.microsoft.com/en-us/library/ms745109.aspx#CodeSnippetContainerCode13">historical forms</a> for just three examples, but I'll leave exploring those as an exercise for the reader.</p>

<h4>Practical Considerations</h4>

<p>It may seem slightly superfluous for me to mention this about a CSS feature which, so far, has only an experimental implementation in just one browser, but it would be unwise to build a site which depended on <code>font-feature-opentype</code>, for example by relying on certain ligatures or stylistic sets to convey information.  However, for making your typography look a bit nicer for a subset of your users, this stuff will be usable on real web pages from the day of Firefox 4.0's release.</p>

<h4>The Future</h4>

<p>Now you're salivating for a future where all web browsers support <code>font-feature-settings</code> this is probably a good time to point out that, once that support exists, you'll hardly ever use it <img src="http://www.boogdesign.com/b2evo/rsc/smilies/icon_smile.gif" title="&amp;amp;#58;&amp;amp;#41;" alt="&amp;amp;#58;&amp;amp;#41;" class="middle" width="15" height="15" />  No, this is not a trick, <code>font-feature-settings</code> itself is only intended to be used for obscure and little used options in the open font features list, the common stuff will be accessible through new values on the <code>font-variant</code> property as well as several <code>font-variant-*</code> properties.  The current level of support in Firefox is really only to see how things will look once all that gets implemented.</p>

<p>Let's have a look at how a future you will be recreating my examples with the proposed <code>font-variant</code> property extensions. First, discretionary ligatures:</p><blockquote><pre><code>.discretionary {
    font-variant: additional-ligatures;
}</code></pre></blockquote><p>Alternatively we cold use the specific ligatures property:</p><blockquote><pre><code>.discretionary {
    font-variant-ligatures: additional-ligatures;
}</code></pre></blockquote><p>Each value has a corresponding <code>no-*</code> version, so you could specify <code>no-common-ligatures</code> to turn off the common ones, or <code>no-additional-ligatures</code> in order to override the above rule further down the inheritance chain.  What about lining, tabular numerals?</p><blockquote><pre><code>.tabular-lining {
    font-variant-numeric: lining-nums tabular-nums;
}</code></pre></blockquote><p>None of this is implemented yet, so I can't test I've got it right, and all this syntax is still subject to change as the fonts module is still a working draft, so I'll stop there.  Hopefully this has given you some ideas for fancy typography to give Firefox 4.0 users a special treat and will set you off on your own investigations.</p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=css">css</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=standardsnext">standardsnext</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=typography">typography</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2')+'&amp;title='+encodeURIComponent('Firefox 4.0 Features for Font Fanatics'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;title=Firefox 4.0 Features for Font Fanatics" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;title=Firefox 4.0 Features for Font Fanatics&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;t=Firefox 4.0 Features for Font Fanatics" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=Firefox 4.0 Features for Font Fanatics&amp;url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;t=Firefox 4.0 Features for Font Fanatics" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Firefox 4.0 Features for Font Fanatics&amp;u=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2&amp;Title=Firefox 4.0 Features for Font Fanatics" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=Firefox 4.0 Features for Font Fanatics+http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/firefox-4-features-for-font-fanatics?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=342</wfw:commentRss>
		</item>
				<item>
			<title>Attempting Better Drop Shadows in IE8 - Filters Revisited</title>
			<link>http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2</link>
			<pubDate>Wed, 30 Jun 2010 22:21:02 +0000</pubDate>			<dc:creator>robertc</dc:creator>
			<category domain="main">Front End Web Development</category>			<guid isPermaLink="false">329@http://www.boogdesign.com/b2evo/</guid>
						<description>&lt;p&gt;I was reading about &lt;a href=&quot;http://www.useragentman.com/blog/csssandpaper-a-css3-javascript-library/&quot;&gt;cssSandpaper&lt;/a&gt; today and my curiosity was sparked by this line:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;Note that in IE, the blur-radius is not currently not supported, due to a lack of support in IE&amp;#8217;s DropShadow  filter.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;This is true, &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms532985%28VS.85%29.aspx&quot;&gt;DropShadow&lt;/a&gt; doesn&#039;t support blur radius.  The alternative &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms533086%28VS.85%29.aspx&quot;&gt;Shadow&lt;/a&gt; filter does have a blur radius like property, &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms532937%28VS.85%29.aspx&quot;&gt;Strength&lt;/a&gt;, which &quot;Sets or retrieves the distance, in pixels, that a filter effect extends.&quot;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/no-blur-example.png&quot; class=&quot;screenshot&quot; style=&quot;float:right; margin: 10px;&quot; alt=&quot;Example of both the DropShadow and Shadow filter in action&quot; /&gt;&lt;/p&gt;

&lt;p&gt;So there are two basic options, both with their own advantages and disadvantages:&lt;/p&gt;&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;DropShadow&lt;/strong&gt; - you can use alpha transparent colours and specify separate offsets, but the colour remains solid and sharp edged&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Shadow&lt;/strong&gt; - you can specify a blur radius type property but you cannot set separate x and y offsets, the colour will fade to transparent but you have no control over it, and the results also remain solid and sharp edged&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;Basically, drop shadows in IE look like they were designed by developers rather than graphic designers, see for yourself in the example to the right - top is DropShadow, bottom is Shadow, hard edges in both cases.&lt;/p&gt;

&lt;p&gt;Many, like myself, have taken the position that this can&#039;t be helped, we should be grateful to be able to do drop shadows at all in CSS for IE, and just picked one of the two options and got on with things.  However, at least in IE8, there may be some further options which are worth investigating.  The following text is on every MSDN filter page:&lt;/p&gt;&lt;blockquote&gt;&lt;p&gt;You can assign multiple filters or transitions to an object by declaring each in the filter  property of the object.&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;And guess what?  There is a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms532979%28VS.85%29.aspx&quot;&gt;Blur&lt;/a&gt; filter and, if that turns out to be no good, there&#039;s also a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms532978%28VS.85%29.aspx&quot;&gt;MotionBlur&lt;/a&gt; and a &lt;a href=&quot;http://msdn.microsoft.com/en-us/library/ms532995%28VS.85%29.aspx&quot;&gt;Glow&lt;/a&gt; which we may be able to do something with.  So my strategy in this post is to apply some of these in combination with DropShadow and Shadow to see if we can get slightly more natural looking CSS drop shadows in Internet Explorer.  First, lets remind ourselves what an IE drop shadow looks like:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow by itself&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And here&#039;s the code:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    &quot;&amp;gt;Straight drop shadow example&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Let&#039;s try adding a blur to that and see what happens:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-0.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-0-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow and blur in combination&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the blur effect applies to the shadow but it also applies to the contents.&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)&quot;&amp;gt;
        0 Example text, should not have shadow or be blurred.&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;I wondered if I could wrap the contents in another element and protect it somehow from the filter.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-1.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-1-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow and blur in combination, text in a child element&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A shadow on an element with a transparent background will produce a text shadow, while a background colour will cause the shadow to apply to the box.  So I thought it was worth a try, and I thought I&#039;d trigger hasLayout to be on the safe side:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)&quot;&amp;gt;
        &amp;lt;span style=&quot;height: 30px; zoom:1; background-color: #fff;&quot;&amp;gt;
            1 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Not much joy there, but I did have a bit better luck with the next attempt:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-2.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-2-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow and blur in combination, text in absolutely positioned element&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By making the child element absolutely positioned the filters were now ignored on the containing element, of course the containing element is now empty so needs an explicit height to keep it open:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; height: 30px; zoom:1; background-color: #fff;&quot;&amp;gt;
            2 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;The problem is that the span now pokes out of the containing div, so I tried fitting it more exactly:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-3.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-3-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow and Blur in combination, text in offset absolutely positioned element&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quite a lot of additional markup is now getting tacked on, for really not much aesthetic benefit.  Having the absolutely positioned child match the dimensions of the containing div does mean that you can cover up the blurry top and left edges, but the tradeoff is the elements need to have known dimensions.:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; top: 2px; left: 2px; height: 30px; width: 100%; display: inline-block; background-color: #fff;&quot;&amp;gt;
            3 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;p&gt;Since the shadow still looks crappy I thought I&#039;d try a few different combinations.  Motion blur:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-4.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-4-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow and Motion Blur in combination, text in absolutely positioned element&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And the code:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.MotionBlur(direction=135,strength=8,add=true)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; height: 30px; width: 100%; display: inline-block; background-color: #fff;&quot;&amp;gt;
            4 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Glow:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-5.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-5-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;DropShadow and Glow in combination, text in absolutely positioned element&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;More code:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=6, OffY=4, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.Glow(strength=2,Color=&#039;gray&#039;)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; top: 1px; left: 1px; height: 30px; width: 100%; display: inline-block; background-color: #fff;&quot;&amp;gt;
            5 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;What about just applying multiple drop shadows?&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-6.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-6-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Multiple alpha transparent DropShadows&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above image combines four:&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#cc999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#99999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#66999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#33999999)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; height: 30px; width: 100%; display: inline-block; background-color: #fff;&quot;&amp;gt;
            6 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Getting a bit far out now, multiple drop shadows and blur:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/dropshadow-7.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/dropshadow-7-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Multiple DropShadows with Blur&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#cc999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#99999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#66999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#33999999)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; height: 30px; width: 100%; display: inline-block; background-color: #fff;&quot;&amp;gt;
            7 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Enough of that, I thought I&#039;d try a few examples with shadow instead of drop shadow:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/shadow.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/shadow-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Shadow by itself&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The basic shadow fades out but, as I mentioned, is sharp edged.&lt;/p&gt;&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Shadow(Direction=135, Strength=5, Color=&#039;gray&#039;)&quot;&amp;gt;
        Straight shadow example&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;Now a shadow with a blur:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/shadow-3.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/shadow-3-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Shadow by itself&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;div style=&quot;position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Shadow(Direction=135, Strength=5, Color=&#039;gray&#039;)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)&quot;&amp;gt;
        &amp;lt;span style=&quot;position: absolute; top: 2px; left: 2px; height: 30px; width: 100%; display: inline-block; background-color: #fff;&quot;&amp;gt;
            3 Example text, should not have shadow or be blurred.&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;

&lt;p&gt;A shadow with motion blur:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/shadow-4.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/shadow-4-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Shadow with Motion Blur&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with glow:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://www.boogdesign.com/examples/filters/shadow-5.png&quot; title=&quot;Click for larger image&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/examples/filters/shadow-5-thumb.png&quot; class=&quot;screenshot&quot; alt=&quot;Shadow with Glow&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Yes, they all still look a bit pants.&lt;/p&gt;

&lt;p&gt;So it seems like Shadow and Blur in combination may be the best of a bad bunch, and they don&#039;t really give you too many advantages: you have to know the dimensions of the element in advance for it to be useful in CSS; you might be able to work a jQuery plugin out of it, but if you&#039;re going to rely on scripting you might as well make use of once the image based solutions which result in nicer looking shadows; and finally, all of the above only works in IE8 - IE7 applies all the filters to the contained element whether it&#039;s positioned or not.  So, wasted effort?  Possibly, at least now I know for sure, here&#039;s hoping IE9 adds support for &lt;code&gt;box-shadow&lt;/code&gt; &lt;img src=&quot;http://www.boogdesign.com/b2evo/rsc/smilies/icon_smile.gif&quot; title=&quot;&amp;amp;amp;#58;&amp;amp;amp;#41;&quot; alt=&quot;&amp;amp;amp;#58;&amp;amp;amp;#41;&quot; class=&quot;middle&quot; width=&quot;15&quot; height=&quot;15&quot; /&gt;&lt;/p&gt;&lt;div class=&quot;tags twitter_tags&quot;&gt;&lt;strong&gt;Twitter tags for this post&amp;nbsp;:&lt;/strong&gt; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=css&quot;&gt;css&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=ie&quot;&gt;ie&lt;/a&gt; &amp;bull; &lt;a rel=&quot;tag&quot; href=&quot;http://search.twitter.com/search?tag=shadows&quot;&gt;shadows&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;!-- Paste from here... --&gt;
&lt;a href=&quot;http://del.icio.us/post&quot; onclick=&quot;window.open(&#039;http://del.icio.us/post?v=4&amp;amp;noui&amp;amp;jump=close&amp;amp;url=&#039;+encodeURIComponent(&#039;http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&#039;)+&#039;&amp;amp;title=&#039;+encodeURIComponent(&#039;Attempting Better Drop Shadows in IE8 - Filters Revisited&#039;),&#039;delicious&#039;, &#039;toolbar=no,width=700,height=400&#039;); return false;&quot; title=&quot;del.icio.us&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/delicious.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;amp;title=Attempting Better Drop Shadows in IE8 - Filters Revisited&quot; target=&quot;blank&quot; title=&quot;Reddit&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/reddit.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Stumble It&quot; target=&quot;_blank&quot; href=&quot;http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;amp;title=BAE%20Social%20Bookmarks&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/stumbleupon.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&quot; target=&quot;blank&quot; title=&quot;Technorati&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/technorati.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;amp;title=Attempting Better Drop Shadows in IE8 - Filters Revisited&amp;amp;bodytext=&amp;amp;media=news&amp;amp;topic=programming&quot; title=&quot;Digg This&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/digg.png&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;amp;t=Attempting Better Drop Shadows in IE8 - Filters Revisited&quot; target=&quot;_blank&quot; title=&quot;Share on Facebook&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/facebook.gif&quot; border=&quot;0&quot; height=&quot;16&quot; width=&quot;16&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.spurl.net/spurl.php?title=Attempting Better Drop Shadows in IE8 - Filters Revisited&amp;amp;url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&quot; target=&quot;blank&quot; title=&quot;Submit to Spurl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/spurl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;


&lt;a href=&quot;http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;amp;t=Attempting Better Drop Shadows in IE8 - Filters Revisited&quot; target=&quot;blank&quot; title=&quot;Submit to Furl&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/furl.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Attempting Better Drop Shadows in IE8 - Filters Revisited&amp;amp;u=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&quot; target=&quot;blank&quot; title=&quot;Yahoo&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/yahoo.jpg&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a href=&quot;http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;amp;Url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;amp;Title=Attempting Better Drop Shadows in IE8 - Filters Revisited&quot; target=&quot;blank&quot; title=&quot;Blinklist&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/blinklist.gif&quot; alt=&quot;&quot; border=&quot;0&quot; width=&quot;16&quot; height=&quot;16&quot; /&gt;&lt;/a&gt;

&lt;a title=&quot;Add To Google&quot; href=&quot;http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/google.gif&quot; style=&quot;border: 0px none ; width: 16px; height: 16px;&quot; alt=&quot;&quot; /&gt;&lt;/a&gt;

&lt;a rel=&quot;nofollow&quot; href=&quot;http://twitter.com/home?status=Attempting Better Drop Shadows in IE8 - Filters Revisited+http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&quot; title=&quot;Tweet this&quot;&gt;&lt;img src=&quot;http://www.boogdesign.com/images/twitter-icon.png&quot; style=&quot;width:16px; height:16px;border:0px;&quot; alt=&quot;Tweet this!&quot; /&gt;&lt;/a&gt;
&lt;!-- ...to here --&gt;&lt;div class=&quot;item_footer&quot;&gt;&lt;p&gt;&lt;small&gt;&lt;a href=&quot;http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&quot;&gt;Original post&lt;/a&gt; blogged on &lt;a href=&quot;http://b2evolution.net/&quot;&gt;b2evolution&lt;/a&gt;.&lt;/small&gt;&lt;/p&gt;&lt;/div&gt;</description>
			<content:encoded><![CDATA[<p>I was reading about <a href="http://www.useragentman.com/blog/csssandpaper-a-css3-javascript-library/">cssSandpaper</a> today and my curiosity was sparked by this line:</p><blockquote><p>Note that in IE, the blur-radius is not currently not supported, due to a lack of support in IE&#8217;s DropShadow  filter.</p></blockquote><p>This is true, <a href="http://msdn.microsoft.com/en-us/library/ms532985%28VS.85%29.aspx">DropShadow</a> doesn't support blur radius.  The alternative <a href="http://msdn.microsoft.com/en-us/library/ms533086%28VS.85%29.aspx">Shadow</a> filter does have a blur radius like property, <a href="http://msdn.microsoft.com/en-us/library/ms532937%28VS.85%29.aspx">Strength</a>, which "Sets or retrieves the distance, in pixels, that a filter effect extends."</p>

<p><img src="http://www.boogdesign.com/examples/filters/no-blur-example.png" class="screenshot" style="float:right; margin: 10px;" alt="Example of both the DropShadow and Shadow filter in action" /></p>

<p>So there are two basic options, both with their own advantages and disadvantages:</p><ul>
  <li><strong>DropShadow</strong> - you can use alpha transparent colours and specify separate offsets, but the colour remains solid and sharp edged</li>
  <li><strong>Shadow</strong> - you can specify a blur radius type property but you cannot set separate x and y offsets, the colour will fade to transparent but you have no control over it, and the results also remain solid and sharp edged</li>
</ul><p>Basically, drop shadows in IE look like they were designed by developers rather than graphic designers, see for yourself in the example to the right - top is DropShadow, bottom is Shadow, hard edges in both cases.</p>

<p>Many, like myself, have taken the position that this can't be helped, we should be grateful to be able to do drop shadows at all in CSS for IE, and just picked one of the two options and got on with things.  However, at least in IE8, there may be some further options which are worth investigating.  The following text is on every MSDN filter page:</p><blockquote><p>You can assign multiple filters or transitions to an object by declaring each in the filter  property of the object.</p></blockquote><p>And guess what?  There is a <a href="http://msdn.microsoft.com/en-us/library/ms532979%28VS.85%29.aspx">Blur</a> filter and, if that turns out to be no good, there's also a <a href="http://msdn.microsoft.com/en-us/library/ms532978%28VS.85%29.aspx">MotionBlur</a> and a <a href="http://msdn.microsoft.com/en-us/library/ms532995%28VS.85%29.aspx">Glow</a> which we may be able to do something with.  So my strategy in this post is to apply some of these in combination with DropShadow and Shadow to see if we can get slightly more natural looking CSS drop shadows in Internet Explorer.  First, lets remind ourselves what an IE drop shadow looks like:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-thumb.png" class="screenshot" alt="DropShadow by itself" /></a></p>

<p>And here's the code:</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color='gray')
    "&gt;Straight drop shadow example&lt;/div&gt;</code></pre></blockquote><p>Let's try adding a blur to that and see what happens:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-0.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-0-thumb.png" class="screenshot" alt="DropShadow and blur in combination" /></a></p>

<p>As you can see, the blur effect applies to the shadow but it also applies to the contents.</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color='gray')
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)"&gt;
        0 Example text, should not have shadow or be blurred.&lt;/div&gt;</code></pre></blockquote><p>I wondered if I could wrap the contents in another element and protect it somehow from the filter.</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-1.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-1-thumb.png" class="screenshot" alt="DropShadow and blur in combination, text in a child element" /></a></p>

<p>A shadow on an element with a transparent background will produce a text shadow, while a background colour will cause the shadow to apply to the box.  So I thought it was worth a try, and I thought I'd trigger hasLayout to be on the safe side:</p><blockquote><pre><code>&lt;div style="height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color='gray')
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)"&gt;
        &lt;span style="height: 30px; zoom:1; background-color: #fff;"&gt;
            1 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote><p>Not much joy there, but I did have a bit better luck with the next attempt:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-2.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-2-thumb.png" class="screenshot" alt="DropShadow and blur in combination, text in absolutely positioned element" /></a></p>

<p>By making the child element absolutely positioned the filters were now ignored on the containing element, of course the containing element is now empty so needs an explicit height to keep it open:</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color='gray')
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)"&gt;
        &lt;span style="position: absolute; height: 30px; zoom:1; background-color: #fff;"&gt;
            2 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote><p>The problem is that the span now pokes out of the containing div, so I tried fitting it more exactly:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-3.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-3-thumb.png" class="screenshot" alt="DropShadow and Blur in combination, text in offset absolutely positioned element" /></a></p>

<p>Quite a lot of additional markup is now getting tacked on, for really not much aesthetic benefit.  Having the absolutely positioned child match the dimensions of the containing div does mean that you can cover up the blurry top and left edges, but the tradeoff is the elements need to have known dimensions.:</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.DropShadow(OffX=6, OffY=4, Color='gray')
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)"&gt;
        &lt;span style="position: absolute; top: 2px; left: 2px; height: 30px; width: 100%; display: inline-block; background-color: #fff;"&gt;
            3 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote><p>Since the shadow still looks crappy I thought I'd try a few different combinations.  Motion blur:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-4.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-4-thumb.png" class="screenshot" alt="DropShadow and Motion Blur in combination, text in absolutely positioned element" /></a></p>

<p>And the code:</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=6, OffY=4, Color='gray')
    progid:DXImageTransform.Microsoft.MotionBlur(direction=135,strength=8,add=true)"&gt;
        &lt;span style="position: absolute; height: 30px; width: 100%; display: inline-block; background-color: #fff;"&gt;
            4 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote>

<p>Glow:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-5.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-5-thumb.png" class="screenshot" alt="DropShadow and Glow in combination, text in absolutely positioned element" /></a></p>

<p>More code:</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=6, OffY=4, Color='gray')
    progid:DXImageTransform.Microsoft.Glow(strength=2,Color='gray')"&gt;
        &lt;span style="position: absolute; top: 1px; left: 1px; height: 30px; width: 100%; display: inline-block; background-color: #fff;"&gt;
            5 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote>

<p>What about just applying multiple drop shadows?</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-6.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-6-thumb.png" class="screenshot" alt="Multiple alpha transparent DropShadows" /></a></p>

<p>The above image combines four:</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#cc999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#99999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#66999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#33999999)"&gt;
        &lt;span style="position: absolute; height: 30px; width: 100%; display: inline-block; background-color: #fff;"&gt;
            6 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote>

<p>Getting a bit far out now, multiple drop shadows and blur:</p>

<p><a href="http://www.boogdesign.com/examples/filters/dropshadow-7.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/dropshadow-7-thumb.png" class="screenshot" alt="Multiple DropShadows with Blur" /></a></p>

<blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#cc999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#99999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#66999999)
    progid:DXImageTransform.Microsoft.Dropshadow(OffX=4, OffY=4, Color=#33999999)
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)"&gt;
        &lt;span style="position: absolute; height: 30px; width: 100%; display: inline-block; background-color: #fff;"&gt;
            7 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote>

<p>Enough of that, I thought I'd try a few examples with shadow instead of drop shadow:</p>

<p><a href="http://www.boogdesign.com/examples/filters/shadow.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/shadow-thumb.png" class="screenshot" alt="Shadow by itself" /></a></p>

<p>The basic shadow fades out but, as I mentioned, is sharp edged.</p><blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Shadow(Direction=135, Strength=5, Color='gray')"&gt;
        Straight shadow example&lt;/div&gt;</code></pre></blockquote>

<p>Now a shadow with a blur:</p>

<p><a href="http://www.boogdesign.com/examples/filters/shadow-3.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/shadow-3-thumb.png" class="screenshot" alt="Shadow by itself" /></a></p>

<blockquote><pre><code>&lt;div style="position: relative; height: 30px; filter:
    progid:DXImageTransform.Microsoft.Shadow(Direction=135, Strength=5, Color='gray')
    progid:DXImageTransform.Microsoft.Blur(pixelradius=2)"&gt;
        &lt;span style="position: absolute; top: 2px; left: 2px; height: 30px; width: 100%; display: inline-block; background-color: #fff;"&gt;
            3 Example text, should not have shadow or be blurred.&lt;/span&gt;&lt;/div&gt;</code></pre></blockquote>

<p>A shadow with motion blur:</p>

<p><a href="http://www.boogdesign.com/examples/filters/shadow-4.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/shadow-4-thumb.png" class="screenshot" alt="Shadow with Motion Blur" /></a></p>

<p>And with glow:</p>

<p><a href="http://www.boogdesign.com/examples/filters/shadow-5.png" title="Click for larger image"><img src="http://www.boogdesign.com/examples/filters/shadow-5-thumb.png" class="screenshot" alt="Shadow with Glow" /></a></p>

<p>Yes, they all still look a bit pants.</p>

<p>So it seems like Shadow and Blur in combination may be the best of a bad bunch, and they don't really give you too many advantages: you have to know the dimensions of the element in advance for it to be useful in CSS; you might be able to work a jQuery plugin out of it, but if you're going to rely on scripting you might as well make use of once the image based solutions which result in nicer looking shadows; and finally, all of the above only works in IE8 - IE7 applies all the filters to the contained element whether it's positioned or not.  So, wasted effort?  Possibly, at least now I know for sure, here's hoping IE9 adds support for <code>box-shadow</code> <img src="http://www.boogdesign.com/b2evo/rsc/smilies/icon_smile.gif" title="&amp;amp;#58;&amp;amp;#41;" alt="&amp;amp;#58;&amp;amp;#41;" class="middle" width="15" height="15" /></p><div class="tags twitter_tags"><strong>Twitter tags for this post&nbsp;:</strong> <a rel="tag" href="http://search.twitter.com/search?tag=css">css</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=ie">ie</a> &bull; <a rel="tag" href="http://search.twitter.com/search?tag=shadows">shadows</a></div><br /><!-- Paste from here... -->
<a href="http://del.icio.us/post" onclick="window.open('http://del.icio.us/post?v=4&amp;noui&amp;jump=close&amp;url='+encodeURIComponent('http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2')+'&amp;title='+encodeURIComponent('Attempting Better Drop Shadows in IE8 - Filters Revisited'),'delicious', 'toolbar=no,width=700,height=400'); return false;" title="del.icio.us"><img src="http://www.boogdesign.com/images/delicious.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://reddit.com/submit?url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;title=Attempting Better Drop Shadows in IE8 - Filters Revisited" target="blank" title="Reddit"><img src="http://www.boogdesign.com/images/reddit.png" alt="" border="0" width="16" height="16" /></a>

<a title="Stumble It" target="_blank" href="http://www.stumbleupon.com/submit?url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;title=BAE%20Social%20Bookmarks"><img src="http://www.boogdesign.com/images/stumbleupon.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://technorati.com/faves?add=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2" target="blank" title="Technorati"><img src="http://www.boogdesign.com/images/technorati.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://digg.com/submit?url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;title=Attempting Better Drop Shadows in IE8 - Filters Revisited&amp;bodytext=&amp;media=news&amp;topic=programming" title="Digg This"><img src="http://www.boogdesign.com/images/digg.png" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.facebook.com/share.php?u=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;t=Attempting Better Drop Shadows in IE8 - Filters Revisited" target="_blank" title="Share on Facebook"><img src="http://www.boogdesign.com/images/facebook.gif" border="0" height="16" width="16" alt="" /></a>

<a href="http://www.spurl.net/spurl.php?title=Attempting Better Drop Shadows in IE8 - Filters Revisited&amp;url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2" target="blank" title="Submit to Spurl"><img src="http://www.boogdesign.com/images/spurl.gif" alt="" border="0" width="16" height="16" /></a>


<a href="http://www.furl.net/storeIt.jsp?u=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;t=Attempting Better Drop Shadows in IE8 - Filters Revisited" target="blank" title="Submit to Furl"><img src="http://www.boogdesign.com/images/furl.gif" alt="" border="0" width="16" height="16" /></a>

<a href="http://myweb2.search.yahoo.com/myresults/bookmarklet?t=Attempting Better Drop Shadows in IE8 - Filters Revisited&amp;u=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2" target="blank" title="Yahoo"><img src="http://www.boogdesign.com/images/yahoo.jpg" alt="" border="0" width="16" height="16" /></a>

<a href="http://www.blinklist.com/index.php?Action=Blink/addblink.php&amp;Url=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2&amp;Title=Attempting Better Drop Shadows in IE8 - Filters Revisited" target="blank" title="Blinklist"><img src="http://www.boogdesign.com/images/blinklist.gif" alt="" border="0" width="16" height="16" /></a>

<a title="Add To Google" href="http://www.google.com/ig/adde?moduleurl=http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2"><img src="http://www.boogdesign.com/images/google.gif" style="border: 0px none ; width: 16px; height: 16px;" alt="" /></a>

<a rel="nofollow" href="http://twitter.com/home?status=Attempting Better Drop Shadows in IE8 - Filters Revisited+http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2" title="Tweet this"><img src="http://www.boogdesign.com/images/twitter-icon.png" style="width:16px; height:16px;border:0px;" alt="Tweet this!" /></a>
<!-- ...to here --><div class="item_footer"><p><small><a href="http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2">Original post</a> blogged on <a href="http://b2evolution.net/">b2evolution</a>.</small></p></div>]]></content:encoded>
								<comments>http://www.boogdesign.com/b2evo/index.php/attempt-better-drop-shadows-in-ie8?blog=2#comments</comments>
			<wfw:commentRss>http://www.boogdesign.com/b2evo/index.php?blog=2&#38;tempskin=_rss2&#38;disp=comments&#38;p=329</wfw:commentRss>
		</item>
			</channel>
</rss>

