Videos about the HTML5 Boilerplate

March 28th, 2011

We've published a few videos about the HTML5 Boilerplate recently.

HTML5 Boilerplate overview (60min)

Get an overview of the whole project, and more detail on some of the choices and optimizations within.

Getting Started w/ the HTML5 Boilerplate (15min featuring Divya)

A noob's guide to the project and how you'll get started with your own site.

The Build Script of HTML5 Boilerplate: An Introduction (30min)

The powerful workhorse of deployment gets an overview of what is does and how.

HTML5 Boilerplate went 1.0

March 21st, 2011

The project went 1.0 today. \o/

This project has ruined a few weekends for me and my co-conspirator Divya Manian, but it's worth it. Divya is a dream open source contributor. (Thxthx!) Thanks also to Shi Chuan who became our first major contributor and now leads the Mobile Boilerplate project. He's kickass. But this release is the collaborative work of hundreds of developers, who offered feedback and contributed code. Thanks everyone!

In detail here are some of the people who helped out:

Mickael Daniel, Dave Kirk, Jonathan Verrecchia, nlogax, Rob Larsen, David Murdoch, AD7six, Mathias Bynens, Michael van Laar, Mike West, Mikko Tikkanen, Velir, Stephen Gariepy

Adam J. McIntyre, Adeel Ejaz, akolesnikov, Alex Dunae, Andrew Le, ashnur, Ben Truyman, Bruno Aguirre, Chris Hager, Corey Ward, Craig Barnes, crappish, Daniel Schildt, Dave DeSandro, Dustin Whittle, grigio, Irakli Nadareishvili, Jaime Bueza, Jake Ingman, James A. Rosen, Jeremy Balch, joe bartlett, Joe Sak, John Bacon, Jonathan Fielding, Jonathan Neal, kblomqvist, Kenneth Nordahl, Maarten Verbaarschot, Manuel Strehl, Marcel Turi, Martin Hintzmann, mikealmond , mikkotikkanen, Nic Pottier, Paul Neave, Peter Beverloo, Rick Waldron, Rob Flaherty, S Anand, Sam Sherlock, Michael Cetrulo, simshaun, Sirupsen, Stephen Gariepy, timemachine3030 , Vinay, Weston Ruter, WraithKenny, Yann Mainier, Michael van Laar, Massimo Lombardo, Ivan Nikoli?, Kaelig, Richard Bradshaw, SammyK, alrra, Rizky Syazuli, iszak, aaron peters, Swaroop C H, Mike Po?tyn, Marco d'Itri, Mike Lamb , BIG Folio, Philip von Bargen, Meander, Daniel Harttman, rse, timwillison, ken nordahl, Erik Dahlström, christopherjacob, Chew Choon Keat, benalman, stoyan, Markus, Vladimir Carrer, aristidesfl, Trevor Norris, xonecas, and Anton Kovalyov!

Thanks everyone..

and if you get some time.. Poke at the new 1.0 code. and give the build script a try. You'll be making your sites fast while making them faster. Enjoy.

requestAnimationFrame for smart animating

February 22nd, 2011

If you've never written code to animate inside the browser, you can stop reading :)

What is requestAnimationFrame?

In your animation work, you've used a timer loop to make changes every few milliseconds. Good for us: browser vendors have decided, "hey, why don't we just give you an API for that, because we can probably optimize some things for you." So it's basic API for use with animation, whether that be DOM-based styling changes, canvas or WebGL.

Why should I use it?

The browser can optimize concurrent animations together into a single reflow and repaint cycle, leading to higher fidelity animation. For example, JS-based animations synchronized with CSS transitions or SVG SMIL. Plus, if you're running the animation loop in a tab that's not visible, the browser won't keep it running, which means less CPU, GPU, and memory usage, leading to much longer battery life.

OMG I can brag about having a site with battery-friendly animations?

Yeah bro. Totes McGoats.

How should I use this?

 
    // shim layer with setTimeout fallback
    window.requestAnimFrame = (function(){
      return  window.requestAnimationFrame       || 
              window.webkitRequestAnimationFrame || 
              window.mozRequestAnimationFrame    || 
              window.oRequestAnimationFrame      || 
              window.msRequestAnimationFrame     || 
              function( callback ){
                window.setTimeout(callback, 1000 / 60);
              };
    })();
 
 
    // usage: 
    // instead of setInterval(render, 16) ....
 
    (function animloop(){
      requestAnimFrame(animloop);
      render();
    })();
    // place the rAF *before* the render() to assure as close to 
    // 60fps with the setTimeout fallback.

Note: I am using 'requestAnimFrame` here because since the spec is still in flux, I don't want to make a straight polyfill, yet.

2012.01.07: The spec has gotten some fixes and settled down. We're also seeing ms and o implementations, so we're ready for a polyfill now!

A robust polyfill

Opera engineer Erik Möller wrote about rAF and developed a polyfill that better handles browsers without native support. You can read about it, but basically his code will choose a delay of between 4ms and 16ms in order to more closely match 60fps. Here it is, in case you'd like to use it. Note it uses the standard method name. I have also fixed the cancel* method's name, as it has changed in WebKit.

(function() {
    var lastTime = 0;
    var vendors = ['ms', 'moz', 'webkit', 'o'];
    for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
        window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
        window.cancelAnimationFrame = 
          window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];
    }
 
    if (!window.requestAnimationFrame)
        window.requestAnimationFrame = function(callback, element) {
            var currTime = new Date().getTime();
            var timeToCall = Math.max(0, 16 - (currTime - lastTime));
            var id = window.setTimeout(function() { callback(currTime + timeToCall); }, 
              timeToCall);
            lastTime = currTime + timeToCall;
            return id;
        };
 
    if (!window.cancelAnimationFrame)
        window.cancelAnimationFrame = function(id) {
            clearTimeout(id);
        };
}());

I have this polyfill available as a gist as well.

Let's see that in action

The requestAnimationFrame API

window.requestAnimationFrame(function(/* time */ time){
	// time ~= +new Date // the unix time
});

The callback is passed the current time as the first argument, as you'll likely want that.

You'll also notice the second parameter to requestAnimFrame: the element that visually bounds the entire animation. For canvas and WebGL, this will be the actual <canvas> element. For DOM stuff, you can leave it off or define it for a slightly more optimized experience.It's since been removed from the spec (and WebKit's implementation)

Is it ready?

Right now, the Webkit implementation (available in Nightly Safari and Chrome Dev Channel) and the Mozilla one (available in FF4) differ slightly. Mozilla's has a bug which caps potential framerates at about 30fps.Actually, "It's currently capped at 1000/(16 + N) fps, where N is the number of ms it takes your callback to execute. If your callback takes 1000ms to execute, then it's capped at under 1fps. If your callback takes 1ms to execute, you get about 60fps." (thx, Boris) It'll be fixed though, probably for the next release after FF4 ships. Also Chrome 10 doesn't have the time parameter (added in m11), FF currently ignores the element argument.

We want your feedback!

If you do animation work, WebKit and Gecko hackers would love to hear if this meets your needs or if it could be improved any. Take a look at the draft requestAnimationFrame spec. It's currently modeled like setTimeout; does a setInterval repeating style API make more sense? Does this API have downsides when animating multiple simultaneous elements? Does the element reference work for you? In general, does this solve the common cases of animation?

Resources for hackers

Thx @mrdoob for bringing this up today and spreading the good word.

2011.06.01: Joe Lambert took this idea and provided shims for both setTimeout and setInterval that leverage this. http://blog.joelambert.co.uk/2011/06/01/a-better-settimeoutsetinterval/

2011.10.13: Updated code sample and explained why the rAF call before render makes sense due to the timeout fallback.

2011.12.14: Updated code sample and text. Removed references to element argument, as it was removed from spec and webkit's impl.

2012.01.01: Added polyfill from Erik Moller.
2012.01.05: Addressed polyfill fix from Tino Zijdel of DHTML Lemmings fame. :)

Surefire DOM Element insertion

February 16th, 2011

So you've got an element. You need to add it to the DOM. Somewhere, anywhere, just be sure that it works.

In Modernizr, we need to do this all the time. In order to adequately do our feature detection we need to try out some elements in the DOM. But how exactly to add it? Steve Souders dug into appendChild vs insertBefore and the comments meandered through the sea of possibilities. Here's the best way to add yourElem:

var ref = document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(yourElem, ref);

But you prefer a good old document.body.appendChild(elem); Awww! I know, man. I used to, too.
Well, you can't always trust this.. Especially if you're writing library, widget or third-party code.

Here's why you can trust this insertBefore method, and why all the other techniques are not wise:

  • appendChild can throw Operation Aborted
  • <head> doesn't always exist in old opera, not-so-old safari, and others
  • if your script runs in the <head>, the <body> doesnt exist yet.
  • appending to document.documentElement can lead to an uncertain parentNode.
  • document.documentElement.firstChild (or .childNodes[0]) may be an html comment.
    • and as of FF4, insertBefore doesnt work with an html comment node

Okay okay okay, there is actually one case where the above method poses a problem:

  1. You are inserting a <link>, <script>, or <img> (sumpthin' referencing another asset).
  2. Said asset has a relative URL. (Yours has an absolute URL? You're A-OK, bud)
  3. The page has a <base> element, changing the base URL used to resolve all relative URLs used.
  4. The first <script> element of the page is after said <base> element.
  5. You don't want your element's asset path to be affected by the <base> element.

Wow. So if this scenario is a concern for you.. Then you need a small addition to the earlier code:

var ref = document.getElementsByTagName('base')[0] || document.getElementsByTagName('script')[0];
ref.parentNode.insertBefore(yourElem, ref);

But anyway that's a pretty narrow edge case so most people will be fine with the earlier snippet.

And if you have a hard time remembering the signature for insertBefore like I do, just think that your parent wants you to insert yourself before your younger brother. That's totally parentNode.insertBefore(you, sibling), right? :)

Thx souders, alex sexton, miketaylr, ben alman, jdalton & everyone else who cares about these small details

11 More Things I Learned from the jQuery Source

January 19th, 2011

I recently dove back into the jQuery source code to pull out some more JavaScript goodness. If you haven't seen the original 10 Things I Learned from the jQuery Source video, definitely check that out.

But now.. some newness:


youtube link for flash-less HTML5 player

In this video:

Tune in for 29 minutes and soak it up.

i left this space here for you to play. <3