Grow your CSS skills. Land your dream job.

Media Fragments URI – Spatial Dimension

Published by Guest Author

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 320x240 in size with an offset of 160x120 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.

Comments

  1. This looks really useful, thanks for sharing. It kind of reminds me of the way WordPress resizes image files and generates a new URL for the resized version.

  2. jordy addison
    Permalink to comment#

    Super cool!! thanks.

  3. Covarr
    Permalink to comment#

    This technique brings about new and innovative ways for websites to waste bandwidth. No longer content to merely squeeze 8-megapixel images into 100×100 square thumbnails (using the browser, of course), they can now crop out things that they’ll never need, without having to open up one of those pesky image editors!

    • I disagree – following your thinking, we should get rid of any sharp tools, because some people will hurt themselves ( or others )… right?

      It’s not about the ‘tool’, it’s how you use it – sure, some people will find a weird and/or bad ways to use it, but that doesn’t render this technique useless.

    • I wonder if servers could help out here. That would be pretty magical if they only served up the part of the image being requested.

    • @Chris
      No, servers can’t do anything here. Everything after the # isn’t sent to the Server and can’t be processed there.

    • Covarr
      Permalink to comment#

      Tomasz, I’m not saying it’ll ONLY be used for stupid or that it should be eliminated… just that it’ll definitely happen.

    • Permalink to comment#

      It would be easy to write a PHP (and I’m sure most any other serverside language) script that served up images based on these params so you aren’t wasting bandwidth. However, on a heavily trafficked site that would add a lot of extra processing on the server.

  4. Permalink to comment#

    Great stuff, thanks for “playing with new things”.

  5. Miss A
    Permalink to comment#

    Very cool, will be useful for displaying responsive images without having to upload a cropped image for smaller screens. Although then there is always the bandwidth issue…

    • Marie
      Permalink to comment#

      On the other hand, uploading several cropped images for smaller screens might lead to more HTTP-calls, which for mobile networks is also a concern (latency making it slower).

      I’m looking forward to experimenting with this, once it’s somewhat more mainstream. For the moment we will have to satisfy ourselves with enjoying the coolness =)

  6. Ralf Hundertmark
    Permalink to comment#

    Very interesting ! Thanks for sharing,

  7. Permalink to comment#

    Thanks! But I wonder – if the browser must to cashing all the big image, and then show me the croped area? I ask because if not – then it may be used for media queries.

  8. Permalink to comment#

    I couldn’t quite tell from the recommendation, but are media fragments also going to allow us to pick a specified frame/frame range from animated gifs/animated pngs? If so, I can think of at least two ways that could be used:

    a) Further enhancing the power of a single image in http call reduction by spriting with gifs and pngs in 4 dimensions
    b) Using a single animated gif or png for both the base (non animated) and hover (animated) states of animated buttons. I guess theoretically, maybe you could somehow even transition back from the current frame at mouseout to a different frame.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".