Sunday, April 29, 2012
RESPONSIVE WEB DEVELOPMENT TUTORIALS (PART 3)
, and suggested that to do this, we need to move away from pixels and instead embrace proportional units like ems and percentages.
This is all well and good when dealing with passages of text; if a column becomes too narrow then text can easily wrap on to a new line. But media assets like images and video have prescribed dimensions set in pixels. We can scale these down of course, but that means downloading larger files than necessary, and bandwidth can be expensive.
High definition (or Retina) displays pose another challenge. These displays pack a considerable number of pixels into a small area, allowing more detail to be shown. This can be a problem for high contrast imagery and iconography, which if not designed to match these native resolutions, can appear fuzzy and lack definition.
Today, I’ll look at these issues and provide insight into how we might tackle them. But it’s worth noting that this is a rapidly developing area, with new approaches emerging almost daily. This can be challenging – but exciting too!Yesterday we created a fluid layout for our thumbnail pattern. Unfortunately, images within each item were not adapting to the changing layout, breaking outside their containers or leaving large areas of white space:
Thanks to some stubbornly unresponsive images, our gallery layout breaks
Fortunately, there’s an easy way to fix this. First (an early pioneer of fluid layouts), it involves adding the following rule to images you wish to scale with the layout:
This rule tells browsers that an image should fill the width of its containing element, up until the point where it reaches 100% of its size. Simple!
There is one small caveat, however. For this CSS declaration to work, you can’t add a height attribute to your images. From a performance point of view, that’s not ideal (the sooner the browser knows what size to render an image, the less time it spends redrawing the page). Continue to include width and height attributes for images that don’t need to scale however.
You’ll note that for these thumbnails, I’m using images that reflect the design of the desktop-orientated layout, and scaling them down for narrower viewports. This seems counter to everything we have described previously – this isn’t mobile first!As with everything, it’s a question of judgement. We need to balance performance against maintainability – and our own sanity! For these thumbnails, the size differential is small enough (138px > 240px) that we can compensate for the file size in other ways. We will use the correct file format (JPEG can typically generate the smallest file size for photos) and apply an appropriate amount of compression. We will cover image optimisation in more detail during the final part of this tutorial.
Large images can appear on the media item page
However, on the media item page, a photo can be anywhere between 288 and 800 pixels wide. Regardless of file format and other optimisations, our largest image could still be anywhere up to 300kb in size, taking several seconds (if not longer) to download over a 3G connection. This is a problem.
Ideally the browser would report the size of image it needs to display and the average amount of bandwidth available and we could serve an appropriately sized image best matching these constraints. Sadly, no browser does this, and there is nothing that hints at how this might work either (well, anyway).
Unfortunately, as browsers increasingly focus on performance – typically using techniques that involve prefetching of assets – this approach has become fragile. It also detects the display width to decide which images to load, yet it is not always true that a larger display warrants larger images.
· A PHP solution developed by and inspired by the work of Scott, this approach is compatible with existing markup and allows for multiple image sizes to be used. Again, it loads images based on screen resolution, which is not always an accurate test, and requires PHP and the GD library for it to work.
· While many approaches have focused on trying to work out which image to download before a page loads, has taken a different approach. Like other solutions, it involves referencing the smallest image in the markup. But rather than detect whether a larger image is required before the page is loaded, here the smallest image is downloaded regardless. Only once this has loaded (and if a larger image is required) does it get replaced with a higher resolution version. In many ways this is a modern take on the attribute that mysteriously disappeared from HTML. Oh, how we long for its return.
and goes into fantastic detail about the pros and cons of some of the above solutions. Meanwhile, , and started to work out the details.
The long and short of it? This isn’t a solved problem. All we can do is decide which of the options mentioned above fits our needs the best. For this tutorial, we’ll choose the responsive enhance technique.
Arriving in Las Vegas
Then on our element we need to add a new attribute that references the source of the larger image:
Finally, we need to override the default styling of images. For the detection to work, we need the smaller image to scale larger than its native size. We can do this as follows:
Again, this is not a perfect solution (especially as we can only reference one additionally sized image), but it’s far better than serving larger images regardless.
Images don’t just exist within markup of course: we can also reference them from CSS. Things are a little easier here, as media queries mean we can choose which images to show in different layouts.
As many of our background images in CSS will be icons, now is a good time to touch on high resolution displays, and in particular, two methods which allow us to use resolution-independent icons:
· On an increasingly pixel-less web, Scalable Vector Graphics (SVG) are enjoying something of a revival after years in the wilderness. With good support in most modern browsers – including IE9 and above – we can use this format in a number of ways. We can reference it from an element, we can embed SVG code directly in our markup, and we can reference it from within CSS. David Bushell has , and it’s well worth a read.
· Another means of including scalable icons is with specially designed web fonts that include icons rather than letters and numbers. This means we can style icons in the same way we do for text, and enjoy vector based iconography, too.
Okay, enough about images – let’s talk about video. Thankfully, making videos responsive is less problematic. Such is their size, approaches to serving videos in a bandwidth-friendly manner are more commonplace, be that via streaming or the many different compression codecs available. And of course, videos should only start downloading once you hit play.
But, we want our videos to scale within the confines of our layout. If we are using native HTML5 video, we can again use the following CSS:
However, embedded objects (, , ) behave differently. If we add the following rule to our embed:
the video may not maintain the correct ratio as it scales, or it could simply refuse to flex at all:
Our video embed refuses to scale with the layout
This is because embedded objects aren’t able to report the ratio of the video they contain. In order to get round this problem, we need to place the embed inside a container that has the correct ratio, and set the embed to be 100% wide and tall (an approach .
First, we need to add a container around our embed:
Then we can then style the wrapper as follows:
The value is what gives this wrapper its ratio. As our embedded videos have been recorded using a 16:9 aspect ratio, their height is 56.25% of the width (9/16=0.5625). You’ll notice that we’ve also given this element relative positioning; this is so we can absolutely position the enclosed and have it ignore this padding:
And there you have it. Our video embeds now respond to the layout just as beautifully as our images:
Video embed now correctly resizesStill, as we examine the fluidity of our pattern portfolio, we can quickly see that although it scales, there are points where we would ideally make the layout a little smarter, adapting it as the width of the browser increases.