Media Fragments URI – Spatial Dimension

Avatar of Fabrice Weinberg
Fabrice Weinberg on (Updated on )

The following is a guest post by Fabrice Weinberg Fabrice is the kind of guy who likes to explore the cutting edge of CSS and web technologies. This post is no exception!

I’d like to take a look at the Media Fragments URI Specification. In particular, the spatial dimension part. The temporal dimension portion was implemented last year in Chrome and Firefox but the spatial dimension isn’t supported in any current browser as of the time of writing.

To be clear: this topic is highly experimental. The only way to use it today would be to use the polyfill I wrote, which only works in Chrome and Firefox. Basically: don’t use it in production!

To give you some idea of what it’s all about, you can think of the temporal dimension as an offset at which the audio/video-tag starts to play it’s content. You can find a working example here.

The spatial dimension is the same concept, but for images. We can describe the exact part of an image we want to display.

How does it work?

The Media Fragments URI is syntax with which it is possible to only select a certain portion of an image. It looks like this:

#xywh=160,120,320,240        # => results in a 320x240 box at x=160 and y=120
#xywh=pixel:160,120,320,240  # => results in a 320x240 box at x=160 and y=120
#xywh=percent:25,25,50,50    # => results in a 50%x50% box at x=25% and y=25%

Essentially, a hash you append to media URLs.

Example

If you append these “fragments” to an image URL like this:

http://placekitten.com/500#xywh=160,120,320,240

The result would look like this:


As the spec states, we get an image 320×240 in size with an offset of 160×120 to the upper left corner.

What is it good for?

An improvement for CSS Sprites

I wouldn’t say it’s “better” to use Media Fragments to replace CSS Sprites. Rather, it extends the possibilities by overcoming a common problem. It’s not possible to create a repeating background that’s repeated on more than one axis with regular image sprites. Even one axis is complicated.

With Media Fragments, we would be able to do a repeating background-image from an image within a sprite.

A demo:


For the image in the demo, I combined this pattern with some Twitter Bootstrap icons. The traditional technique for CSS Sprites is used for icons and a Media Fragment for repeating background.

Image Animations

Another use case is the possibility to build image animations like discussed in the article Animated GIFs the Hard Way by Jon Skinner for the Sublime Text 2 product page. But I don’t think is usable in production because I agree that JavaScript is better suited for this kind of animation. I just like to push CSS to its limit.

Creating the Polyfill

Hunting for a solution to test the Media Fragments URI in current browsers, I looked for a way to simulate its behavior. You can see the complete polyfill on an example Pen.

Firefox

The solution for Firefox was quite simple. A CSS function called -moz-image-rect does exactly what we want and it has been implemented since March 2011 in Firefox (version 4 at that time).

WebKit

For WebKit there is a great thing called CSSCanvas (-webkit-canvas drawing). You can think of it like a background-image that is a canvas and can be accessed with JavaScript. But the bad thing is that there’s no published spec for this feature, so it will be WebKit-only for some time (although Firefox has something similar: -moz-element). There is also a bug in the current Google Chrome release Version (23) Bug 16199 which is fixed in Google Chrome Canary. This bug won’t affect the polyfill as there is only a problem with correctly refreshing the canvas on animated content.

Code sample:

div {
    background: -webkit-canvas(name_of_canvas);
}

Then use this canvas as a drawing context in JavaScript.

var ctx = document.getCSSCanvasContext("2d", "name_of_canvas", 100, 100);

What we have done here is to retrieve the drawing context for the canvas defined in our CSS by its name “name_of_canvas” and defined it’s width and height to be 100px each.

Here is a working sample (WebKit only for obvious reasons):


Conclusions

In the end, I just combined these two core techniques to create the polyfill. If someone knows a way to extend the browser support, I would be glad to hear it.

Why so much work?

I like to play with new things. So new they they aren’t even in the browser yet! I hope you do too. That’s all for now. If you have some questions I’ll be happy to answer in the comments.

Thanks to Tim Pietrusky for comments and corrections on earlier versions of this tutorial.