The Edge of HTML5
Eric Bidelman ·

Legend:

Not quite ready. Keep it on your radar.
Relevant Chrome/WebKit bug.
Bug has been fixed/resolved.
Specification link
( Press 'n' for additional notes on some slides. Most of this presentation requires Chrome Canary 18+. )

Agenda

For 2011: The Latest in HTML5

Stuff you probably missed:

Typed Arrays

Learn them! The building blocks of new HTML5 hotness.

CSS & Beyond

2012 is the year for CSS!

More: "Six CSS Layout Features To Look Forward To"

Scoped styles

Style elements mid-document, confined to immediate parent:

<article>
  <p>This p will have inherited color.</p>
  <section>
    <style scoped>
      p { color: red; }
    </style>
    <p>This p will be red.</p>
  </section>
</article>

Demo

New CSS functions

calc()

width: -webkit-calc(200px - 100);
width: -webkit-calc(2 * 50%);
width: -webkit-calc(200px / 2);
color: hsl(-webkit-calc(120), -webkit-calc(75%), 0.5);
background-position: -webkit-calc(50% + 5px) center;

min()

width: -webkit-min(150px, 100px, 200px);
width: -webkit-min(90px + 50px, 100px);
width: -webkit-min(100px, 100%);  /* where 100% is 200px; */

max()

width: -webkit-max(150px, 100px, 200px);
width: -webkit-max(200px - 50px, 100px);
width: -webkit-max(100px, 100%);  /* where 100% is 200px; */

CSS functions ( cont. )

cross-fade()

background-image: -webkit-cross-fade(url(first.png),
                                       url(second.png), 50%);
@-webkit-keyframes fading {
  0% { background-image: -webkit-cross-fade(
                         url(first.png), url(second.png), 0%); }
  100% { background-image: -webkit-cross-fade(
                           url(first.png), url(second.png), 100%); }
}

Demo

CSS Regions

Flow content into specified regions:

<style>
#content {
  -webkit-flow-into: bodytext;
}
.region {
  width: 200px;
  height: 200px;
  -webkit-flow-from: bodytext;
  -webkit-region-overflow: break;
}
@region #region1 { /* webk.it/71487 */
  p { color: navy; }
}
</style>
<div id="region1" class="region"></div>
<div id="region2" class="region"></div>
<div id="content">
  <p>Lorem ipsum dolor ... or a nunc.</p>
  <div><img src="...">Lorem ipsum dolor ... or a nunc.</div>
</div>

Demo

CSS Regions ( JS API )

Access to the Document's named flows:

var namedFlow = document.getFlowByName('body_text');
namedFlow.overflow // true if flow doesn't fit in all its regions.

// Ordered NodeList of elements that constitute the named flow.
var els = namedFlow.contentNodes;

// NodeList of regions that contain (part of) the target node. 
var regions = namedFlow.getRegionsByContentNode(targetNode);

Determine if content fits in a region:

Element.regionOverflow // 'overflow', 'fit', 'empty', 'undefined'

// Array of Ranges for the content that is positioned in the region.
var ranges = Element.getRegionFlowRanges();

CSS Exclusions

<style>
.exclusion {
  -webkit-wrap-flow: both;
  -webkit-wrap-margin: 10px;
  -webkit-padding-margin: 10px;
  -webkit-shape-outside: circle(50%, 50%, 50%);
  position: absolute;
}
</style>
<div> 
  <div class="region">Donec metus messa, mollis...</div>
  Lorem ipsum dolor sit amet... 
</div>

Demo: Adobe Prototype Build

New Flexbox

Vertically center content:

section {
  display: -webkit-flex;
  -webkit-align-items: center;
  -webkit-justify-content: center;
  -webkit-flex-flow: row no-wrap; /* both default values */
}
section > div:first-child {
  -webkit-flex: 2 0 100px; /* first div will be 2x wider */
}

See Fronteers article for more info.

Demo

CSS Filters

Apply filter effects to any DOM element:

video, img {
  -webkit-filter: grayscale(0.5) blur(10px);
}

Demo Demo2

JavaScript

navigator.connection

// unknown, ethernet, wifi, 2g, 3g, 4g, none
navigator.connection.type

Mutation Observers

Example

<ol contenteditable>
  <li>Press enter</li>
</ol>
<script>
  var ol = document.querySelector('ol');

  var observer = new WebKitMutationObserver(function(mutations, observer) {
    console.log(mutations, observer);
  });

  observer.observe(ol, {
    subtree: true,       // observe the subtree rooted at ol
    childList: true,     // include childNode insertion/removals
    characterData: true, // include textContent changes
    attribute: true      // include changes to attributes within the subtree
  });

  // observer.disconnect() // Cease observations
</script>

Demo

Transferable Objects

See HTML5Rocks Update for more info.

Demo

Transferable Objects: feature detection

var ab = new ArrayBuffer(1);
worker.webkitPostMessage(ab, [ab]);
if (ab.byteLength) {
  alert('Transferables are not supported in your browser!');
} else {
  // Transferables are supported.
}

Binary WebSockets

Stream a File, Blob, or ArrayBuffer:

window.URL = window.webkitURL || window.URL;
window.WebSocket = window.WebSocket || window.MozWebSocket;

var ws = new WebSocket('ws://example.com/sock', ['dumby-protocol']);
ws.binaryType = 'blob'; // or 'arraybuffer'

ws.onopen = function(e) {
  console.log('Connection OPEN');
};

ws.onmessage = function(e) {
  // e.data.__proto__ === Blob.prototype
  document.querySelector('img').src = URL.createObjectURL(e.data);
};

See HTML5Rocks Updates for more info on changes.

Games

Mouse Lock API / Pointer Lock

Example

// Note: webkit and moz vendor prefixes are not shown.

document.body.addEventListener('click', function(e) {
  if (!document.isFullScreen) { // Chrome requires fullscreen to succeed.
    document.body.requestFullScreen();
  } else if (navigator.pointer.isLocked) {
    navigator.pointer.unlock();
  } else {
    document.cancelFullScreen();
  }
}, false);

document.addEventListener('fullscreenchange', function(e) {
  if (document.isFullScreen) {
    navigator.pointer.lock(document.body, function() {
      console.log(e.movementX, e.movementY);
    }, function(e) {
      console.log('Mouse lock unsuccessful', e);
    });
  }
}, false);

document.body.addEventListener('pointerlocklost', function(e) { ... }, false);

Chrome/FF demo

Gamepad API

navigator.gamepads = navigator.webkitGamepads || navigator.MozGamepads;

var requestAnimationFrame = window.webkitRequestAnimationFrame ||
                            window.mozRequestAnimationFrame;
var cancelAnimationFrame = window.webkitCancelAnimationFrame ||
                           window.MozCancelAnimationFrame;

var controllers = {}; // Stash connected controllers.
var reqId = null;

function onConnected(e) {
  controllers[e.gamepad.index] = e.gamepad;
  runAnimation();
}

function onDisconnected(e) {
  delete controllers[e.gamepad.index];
  cancelAnimationFrame(reqId);
}

window.addEventListener('webkitgamepadconnected', onConnected, false);
window.addEventListener('webkitgamepaddisconnected', onDisconnected, false);

window.addEventListener('MozGamepadDisconnected', onDisconnected, false);
window.addEventListener('MozGamepadConnected', onConnected, false);

Gamepad API

function runAnimation() {
  reqId = requestAnimationFrame(runAnimation);

  for (var i in controllers) {
    var pad = navigator.gamepads[i];
    //pad.id // string for brand/style of connected device.
    //pad.index // index of the gamepad in navigator.gamepads.
    //pad.timestamp // last time data for the gamepad was updated.
    //pad.axes // array of all axes values [-1..1, -1..1].
    //pad.buttons // array of all button values [0..1, 0..1, 0..1].
  }
}

Demo

( FF/Chrome )

Multimedia

Check out this amazing deck!

HTML5