Responsive images

The <img> tag all started with this message and has been with us since HTML 2.0. In that time it hasn’t changed much at all, just put a path to an image in the src attribute and you have an image on the screen.

That all worked very well until the need to provide content to people in many different situations with a wide range of screen sizes presented itself. This need brought with it problems that seemed insurmountable at times and were dismissed as temporary by some, but have now been solved by the extraordinary people and work of the Responsive Images Community Group. I didn’t follow progress closely but I had a passing interest and saw that they sailed many a stormy sea and were slapped by a few broadsides before getting to this point.

The process was sensible; they started with use cases and solved each one. To understand the solutions properly it’s important to understand these use cases, so read them if you’re not sure.

It’s insanely clever how it works and I’m excited about getting it into production sites. It will be used in the next project I start.

A small point of order before going on: I’m using Picturefill 2.0.0 for all the demos as browser support isn’t quite there yet. In order to prevent a double download I’ve left off the src attribute in some of the demos. That is non-standard and is just to make it easier to see what is downloading in your favourite inspector.

Resolution switching with srcset

srcset is a new attribute for use in <img>. Its value is a comma separated list of images for the browser to choose from.

Most new phones and tablets are high resolution i.e. they have more than one physical device pixel for every CSS pixel. If we have an image that isn’t going to vary too much or at all in width we can give hi-res screens a hi-res image, and low-res screens a low-res image.

Demo 1 shows an example of this and uses the following markup:

<img srcset="images/low-res.jpg 1x, images/hi-res.jpg 2x" width="320" height="240" alt="In Our Image by Joseph Hiller">

What we’re telling the browser here is that there’s an image to be rendered at 320 CSS pixels wide and 240 CSS pixels high. If it’s a 1x screen use the low resolution image, and if it has a device pixel ratio of 2 or more use the high resolution version.

The browser then requests the correct image from the server. No double download, no media queries, no hacks, just the most appropriate image.

If you don’t have a pair of lo-res/hi-res devices to test on here’s how it looks on an iPhone 3GS and an iPhone 4:

Screenshots from an iPhone 3GS and an iPhone 4 side by side, showing that a higer resolution image was loaded on the iPhone 4

You don’t have to stop at 2x, you can go on as far as you like, future proofing 4x screens for example.

This functionality is supported in Opera since version 21 and Chrome since version 34, so go ahead and use it if you need to. Browsers that don’t support it will fallback to whatever the value of src is, so no change from what we’re already doing for them.

srcset and sizes

sizes is another new attribute that we use to tell the browser what sizes an image is intended be rendered at. I’ll run through a basic example first.

100% wide banner

Demo 2 is a simple example that uses the new srcset attribute to display different images at different viewport widths. The markup I’ve used is:

srcset="images/small.png 320w, images/medium.png 640w, images/large.png 1024w, images/very-large.png 2000w"

Instead of density we’re listing the images with their pixel widths. Now we can sit back and let the browser figure out which images to load.

Viewport range Image loaded
0 – 320 pixels small.png
321 – 640 pixels medium.png
641 – 1024 pixels large.png
1025+ pixels very-large.png

Table showing which images are loaded in various viewport widths on a 1x screen

When I first saw this in action I thought it was perfect for art direction and couldn’t figure out why everyone was saying you need to use <picture> for that use case. After all I’m swapping out completely different images in the demo.

Here’s another clever bit though, the browser picks the right image, not just for the CSS pixels, but for the device pixels too, so higher resolution screens get a sharper image.

Here’s how demo 2 looks on an iPad 2 on the left and an iPad Air on the right:

Screenshots from an iPad 2 and an iPad Air side by side showing that the lower resolution screen doesn't get an image bigger than it needs

The Air has a retina screen so very-large.png is loaded on it. There’s no need on the older iPad so it downloads the smaller image.

It gets even cleverer than that too (in the spec at least). If the browser detects unfavourable network conditions it can ignore the resolution of the screen, prioritise bandwidth over visual quality, and download the smaller image.

Clarification

As Tab Atkins Jr pointed out in the comments, what we have here is an assumption on the part of the browser that all the images in the srcset are the same photo with the same aspect ratio and cropping. It’s up to the browser which one is displayed, authors have zero control over that.

srcset alone is no good for art direction.

No need for the Network Information API and the calculations, assumptions and guesswork that would come with having to cater for bandwidth ourselves. Very useful indeed and great news for users and developers if/when browsers implement it.

Getting back to the example in the demo, I’ve included the sizes attribute:

sizes="100vw"

This tells the browser that the image will be displayed at 100% of the width of the viewport at all times. 100vw is in fact the default so it’s not necessary in this case.

Worth pointing out that you can’t use % in sizes, but you can use ems which is in the next example.

An image in an article

A common place to see images is at the top of a blog post or page taking up the full width of the main column.

Demo 3 has an image like that in a simple main column/right sidebar layout above 50em (most commonly 800 pixels), all inside a 95% wide wrapper with a maximum width of 75em (most commonly 1200 pixels).

The sizes attribute is more complex here, but hopefully it illustrates how it applies to images that aren’t always a fixed percentage of the viewport.

The value of srcset is the same as in the previous demo:

srcset="images/small.png 320w, images/medium.png 640w, images/large.png 1024w, images/very-large.png 2000w"

but we get a bit funky in sizes.

sizes="(min-width:78.94736842105263em) 48.75em, (min-width:50em) 61.75vw, 95vw"

I’ll take it step by step, starting from the end with the 95vw.

To be precise what we have is a comma separated list of media query/length pairs. Any value without a media query—in this case 95vw—is taken as a default and is used when none of the other media queries match. Here, that’s everything below 50em.

We are telling the browser that in viewports between 0 and 50em wide that this image will take up 95% of the viewport. The browser can then select the most appropriate image source from the list in srcset.

If you start small and resize your browser up you’ll see that it switches from small.png to medium.png to large.png up to 50em, pretty much the way it worked in demo 2.

When the viewport is 50em wide something interesting happens. The container holding the image is sized to 65% of the 95% wide wrapper. We need to tell the browser what that is as a percentage of the viewport, and it works out as 61.75% (95*65/100).

Therefore our media query/length pair is (min-width:50em) 61.75vw.

In a 1x screen with 1em equal to 16 pixels that makes the image render at 494 pixels, so the most suitable image to load is medium.png. It’s a bit like element queries for images right inside in the <img> tag!

The final item in sizes takes care of what happens when the viewport is wide enough for the wrapper to be at is maximum width.

(min-width:78.94736842105263em) 48.75em

There’s probably no harm in rounding that to 78.95em, I don’t know, but here’s what’s happening anyhow.

We know that the wrapper div is 95% of the width of the viewport until it is 75em wide, therefore at the point it is exactly 75em wide the viewport is 78.94736842105263em wide.

We also know that the image will be exactly 65% of 75em at this point, which is 48.75em (most commonly 780 pixels) wide, and it won’t get any wider. The very-large.png image will never get loaded.

A width relative to the viewport is no good from here on up so we use an em value instead.

In simple terms all we’ve done is given the browser a list of possible sources, told it their widths, and told it what size the image is to be rendered at different design breakpoints.

It’s useful to play around with the values in sizes to see how it affects which image is displayed. For example if the largest media query/length pair is removed the browser doesn’t know that the image is 48.75em wide from there on up. It thinks (because we haven’t told it otherwise) that the image is taking up 61.75% of the viewport and will load very-large.png when the window is resized large enough.

The picture element

The new img attributes will probably be enough for most scenarios, but there are two use cases where extra functionality and a more conditional approach are needed, and that’s where the <picture> element comes in.

<picture> is at first glance like <video> in that it has nested <source> elements. Unlike <video> they’re used because they work well to satisfy a use case, not because people couldn’t agree on codecs.

srcset and sizes can also be used in <source> elements.

Art direction

If a photo needs cropped so that its subject is discernible in smaller viewports the picture element is your friend.

Demo 4 is a picture of Bo Diddley. When viewed in a wide viewport you can see quite a bit of the audience. In slightly narrower viewports it would be harder to recognise him so it changes to an image that has Bo taking up most of the frame, and in the smallest viewports it’s just his head.

The markup is:

<source media="(min-width:50em)" srcset="images/bo-and-audience.jpg">
<source media="(min-width:25em)" srcset="images/mainly-just-bo.jpg">
<source srcset="images/just-bos-face.jpg">
<img class="art-directed" src="images/just-bos-face.jpg" alt="Bo Diddley playing live in a small crowded room">

One thing to note is that the order of the sources matters. If you put them the other way round Bo Diddley’s face is all you can see in wider viewports.

Also note that it’s the <img> that is styled. The <picture> is only there to provide a src for the <img>.

Type switching

WebP can save up to half the bytes of a JPEG or PNG, but it’s only supported in Blink powered browsers for now. Using <picture> it’s easy to serve WebP to supporting browsers and a fallback to the rest.

<source srcset="image.webp" type="image/webp">
<source srcset="image.png" type="image/png">

Combining <picture> and srcset

A more practical example of type switching is in demo 5, which is basically the same as demo 2 but uses WebP with PNG fallbacks. I’ve just popped the srcset and sizes into each <source> with an <img> fallback. The WebP one is:

<source srcset="images/small.webp 320w, images/medium.webp 640w, images/large.webp 1024w, images/very-large.webp 2000w" sizes="100vw" type="image/webp">

Demo 6 is the blog article from demo 3 with type switching.

Another situation where <picture> and srcset are useful together is when you want to give the browser the option to display a high resolution image and still use art direction:

<source media="(min-width:29em)" srcset="small.jpg, small.jpg 2x" sizes="95vw">

So <picture> is a power up for images that covers use cases srcset and sizes alone can’t deal with.

Client hints

Standards solutions to responsive images are amazing, but they still leave us having to create the images at appropriate sizes, resolutions and types.

Client hints are a way to get rid of that manual work and offload it to the server. They are HTTP headers that give the server some information about the device and the requested resource.

The current draft specifies CH-DPR for device pixel ratio and CH-RW for resource width (the CSS pixel width of the rendered image).

A server-side script will then generate the best image for the requesting device and send it back.

It’s early days, but client hints are behind a flag in Chrome Canary if you want to play with them, and there’s an extension by Andy Davies for changing the CH-RW and CH-DPR values.

Ilya Grigorik has written a good introduction with some demos and seems to be leading the efforts to make something useful.

Summary

The three technologies do different things.

srcset and sizes are saying to the browser, “Here are some images I’ve made and some ideas you’ll find useful, go and figure out what’s best.”

<picture> on the other hand is saying, “Here’s a list of images I’ve made with the circumstances under which you must use them.”

Client hints say, “Here’s some information, make me the best image to fit in here.”

srcset and sizes on an <img> may be made redundant by client hints, but art direction is subjective and at this point in history necessarily dependant on humans. The <picture> element will be around for a while yet.

There is one issue with <picture>, srcset and sizes that is kind of concerning, and that is media queries (presentation) in our markup (content), which isn’t separation of concerns by any means. There’s already thought being applied to that problem however, with custom media queries an early candidate for a solution.

So there are drawbacks, minor in my opinion, and I think they have to be viewed in light of two things: the situation before we had proper responsive images, and the megabytes we’re going to save on ordinary websites every hour.

The value of these standards cannot in my view be understated. They are pragmatic, widely applicable and well specified. The problems they solved were really tough ones and they were solved by developers, a point that should not be lost on anyone.

Not only have the RICG made the web better, they have got us, developers, a seat at the standards table. Let’s not waste that, let’s keep working.

Progressively enhanced accessible tab UI

There’s a demo and code on github, but I wanted to do a quick post writing it up.

I consider Marco Zehe’s Advanced ARIA tip #1: Tabs in web apps the canonical blog post on accessible tabs and used it as my guide. Heydon Pickering also has an excellent example of a tabbed UI as part of his Practical ARIA Examples post.

The main difference between my version and theirs is that mine doesn’t have a list of skip links in the source that are enhanced to tabs. The tabs in my code are generated by JavaScript using the titles of the sections that become tab panels as tab names.

I’ve also used a tiny piece of JS in the <head> to add a class of js-tabs to the <html> element. This prevents a FOUC between page load and the relevant JavaScript running. The only noticeable UI change is the tabs appearing after everything else.

To make it really useful I will need to use a config object. It will also need to be able to create more than one set of tabs on the same page, which it can’t do now. I hope to get on to that soon.

As it stands however, it creates a working tabbed UI in IE8+ and Android 2.1+, falling back to a page with title sections in browsers where the JavaScript I used isn’t supported.

I would love some feedback, pull requests and comments, so fill your boots!

Adventures in font loading

More and more of the sites I’m building recently are using webfonts, and some of these fonts are very heavy. I care about load time and page weight, so I set about finding ways to ensure I could use webfonts while minimising some of the associated problems, viz. FOUT and missing content.

I’m making some assumptions here that you may or may not agree with, so you have an early opportunity to get to the comments to tell me I’m wrong without having to read the whole post. Firstly, webfonts are a good thing. I like what they say and do. Secondly, consideration for people on low bandwidth is of vital importance. This is the web and it’s for everyone. Thirdly, content should be available as soon as possible. Fourthly, FOUT is a feature, not a bug.

Before I go on I just want to mention one thing. I work in a busy agency, so there isn’t a lot of time for experimentation. What this effectively means is that I have been trying different things out on each new website rather than trying out lots of things on one website or a standalone demo. My method for font loading is still evolving, I’m still learning and I’m sure there are plenty of things I haven’t thought of and plenty of mistakes in what I’m doing. Please let me know in the comments.

Do nothing

Before I started thinking too hard about webfonts I just used a plain @font-face declaration and included the font in the font stack of various selectors throughout my CSS.

For high bandwidth scenarios this is great. Nothing gets in the way of the fonts and they are usually on screen with no noticeable delay. However this approach really falls apart when you throttle bandwidth. The screen stays blank for a very long time. The type of sites I build have text in them so this is unacceptable.

Keep webfonts out of smaller viewports

The first thing I went for was to use a media query on a link element to keep the fonts out of small viewports.

<link rel="stylesheet" href="fonts.css" media="(min-width:20em)">

This however is an approach that shows I wasn’t thinking too hard about the problem and should have known better. There is absolutely no relationship between viewport size and bandwidth—sometimes people with laptops struggle to get a signal with a mifi, sometimes people with phones use fast wifi. There is no logic behind this approach.

Use Webfont Loader

WebFont Loader is a Google/Typekit collaboration that adds different classes to the html element depending on when fonts are available. It works with a range of font services and can be configured to work with self-hosted fonts, which is what I did.

There are two basic ways to use. Firstly it can be a broad on/off, where the fallback font is loaded while the fonts are loading, and when the .wf-active class is added all the fonts update at once.

The second way to use it is to be more granular with individual font weights. The website I tried WebFont Loader on uses the Avenir family, and I could swap out the default for Avenir Light as soon as it was available, then if Avenir Book became available a few moments later, load it in. The script adds classes like wf-avenirbook-n4-active to give you this control.

The idea behind this is to get each font showing in the browser as soon as possible, without having to wait for the last one and having one big flash of restyled text. It does seem smoother, less snappy.

I still wasn’t happy though. WebFont Loader is a right lump of JavaScript and glancing at it there is a lot of UA detection going on which I’m not comfortable with, especially when I don’t know exactly what it’s doing. In testing a plain page with just a heading and a couple of paragraphs I was getting load times in the 150-170ms range over the wired connection at work.

Another big problem was that when throttled there was a double FOUT. Perhaps I was doing it wrong, but it was really janky below 256kb/s.

Finally, and specific to the website I was working on, Avenir is a system font on iOS6 and above. It shouldn’t have to wait for class names to be added to the document.

Cut the mustard, stylesheet injection, Network Information API

That brings us up to now, and the website I’m working on at the minute. I’m using a combination of the BBC’s cutting the mustard, a modified version of Scott Jehl’s fonts.js, and the Network Information API as an enhancement for supporting browsers.

First of all I get rid of less capable browsers by testing for 'addEventListener' in win && 'localStorage' in win && 'querySelector' in doc. I, and more importantly the owner of the site I’m doing this on, am ok with this. YMMV.

If the browser cuts the mustard I have a function that injects a stylesheet link element with any specified href into the document head.

The next thing is to test bandwidth using the Network Information API. Currently only older versions of Android have a useful version of the API, and it has always been non-standard. Nonetheless it allows me to not load the fonts over 2g and 3g. Again, this is a judgement call, but in my opinion the loading spinner goes on for too long over those connections and I’m happy to keep webfonts out of any older Androids that slip through the mustard cutting.

The code I’m using is in this gist.

I’m loading the page with content in the fallback system font, checking to see we’re in a decent browser, if we can detect 2g or 3g declare a variable, load the font CSS.

This is the best way I’ve found so far to ensure that content is there from the earliest possible point, if FOUT is perceptible it’s as soon as possible, and where possible bandwidth is directly taken into account.

In an earlier version of the loading script I also estimated bandwidth for browsers that don’t support the Network Information API by calculating the length of time it takes an image to download. It was probably worth a try just to see how bad an idea it is, but it definitely won’t make it into production. Calculating bandwidth is not a problem designers and developers should concern themselves with in my opinion.

On a more practical level, without the image download page load was usually between 70ms and 100ms. The image download added about 50ms on to that. Another problem is that accuracy increases with image size, indeed small images produce wildly inaccurate results. Waiting for an image to download before deciding on bandwidth creates a paradox.

Summary

There are two main opinions I have formed around font loading. The first is that the weight of fonts should be considered as part of the overall weight of a page. Jeremy Keith, Chris Coyier, Tim Kadlec and Brad Frost have all talked about performance budgets, where you set targets for page weight and HTTP requests, balancing the different components against each other. I think this is a good idea, it gives us well defined and measurable constraints to design against.

The other main point is that I think bandwidth is a problem for browsers to solve. Looking back now I realise piddling about with image downloads had me on a hiding to nothing. I hope we have a reliable way to measure bandwidth soon, although I appreciate it’s a very difficult problem to solve.

Please do chip in with a comment here or on twitter. I’m nowhere near the end of this adventure so I’m really keen to hear from other people how they’re tackling this.

How callback functions in JavaScript work

I’m building a thing that’s not quite finished yet, and it uses the geolocation API to get latitude and longitude. I wanted to put them into an object and use it for calculations.

My first attempt was:


var loc = {
    get_latlong: function() {
        var self = this,
            update_loc = function(position) {
                self.latitude = position.coords.latitude;
                self.longitude = position.coords.longitude;
            };

        win.navigator.geolocation.getCurrentPosition(update_loc);
    }
};

What I thought this would do was add two properties — latitude and longitude — to the loc object that I could pick up and run with straight away.

It seemed to work because console.log(loc) gave me the object with the two properties added (and their values), but console.log(loc.latitude) was undefined.

I explained my problem on Stack Overflow and got a good answer from Oleg that got me on the road to solving my problem.

It was CBroe’s comment on my question that led me to understand how things were working though.

The getCurrentPosition method is asynchronous, and for good reason. Looking up a location can take some time, so we don’t want to hold everything up while that happens. I was asking a question that geolocation hadn’t answered yet, which is why it always came back undefined.

What I needed was some way to say “get the location then do the calculations,” and that is a callback function.

Here’s a basic use of a callback function:


// define the function
var some_function = function(arg, callback) {
    // do something here e.g.
    var square = arg * arg;

    callback(square);
};

// call the function
some_function(5, function(param) {
    // do what it says in some_function definition, then do this
    console.log(param);
});

Running that will log 25 to the console.

The easiest way to think of it is to see it in two steps. First of all some_function is called to do it’s thing on the number 5, in this case square it.

Next up is the callback function. some_function is expecting a second argument, and it’s expecting it to be a function with one parameter — callback(square).

All we need to do is say what the callback does, in this case log the argument it received, square, to the console.

Another way of putting it: the function call is saying “run some_function and do what you have to do, then when you’re finished run the anonymous function that has been passed as the second argument, with square as an argument.”

In my example I need to wait for the location information to be returned by the geolocation API then pass the loc object to the callback function to perform calculations on the latitude and longitude.

It’s subject to change, but right now it looks like:


var loc = {
    get_latlong: function(callback) {
        var self = this,
            update_loc = function(position) {
                self.latitude = position.coords.latitude;
                self.longitude = position.coords.longitude;

                callback(self);
        };

        win.navigator.geolocation.getCurrentPosition(update_loc);
    }
};

loc.get_latlong(function(loc) {
    // loc.latitude and loc.longitude are now available
}

Here are a couple of articles I found useful when trying to get my head round this:

Review of jQuery Hotshot by Dan Wellman

JavaScript is something I have been trying to get better at for a couple of years now, and I’ve been concentrating on writing vanilla JS while paying very little attention to libraries such as jQuery. However I realise jQuery isn’t going to go away. I will have to deal with it in other people’s code and I still use it to cover my ass for things like AJAX, where I wouldn’t be confident that I could write good cross browser vanilla JS.

When Dan Wellman asked on twitter if anyone would like to review his latest book on jQuery I took the opportunity for selfish reasons as much as anything else. If I could take a brief interlude from vanilla JS to brush up on jQuery, why not.

jQuery Hotshot is nothing like what I was expecting, and in a good way. There is only the briefest of introductions to how jQuery works then straight into a tour de force of some pretty impressive real world examples of what can be done with jQuery. From a simple game, through UI enhancements, advanced Google Maps API developments, jQuery Mobile, the HTML5 file API and plenty more.

I really like Dan’s writing style. To me it seems relaxed and comfortable and I was able to follow along with the code and explanations without any bother.

It’s obvious Dan knows what he’s talking about and the first few pages of the first chapter will convince you if you have your doubts about his expertise. Absolutely top drawer.

The thing that impressed me most about the book was the constant refrain of best practices in the background, and not just with regard to jQuery. Yes, there was a chapter dedicated to the best way to write a jQuery plugin — and if you write a lot of jQuery plugins this chapter might just be worth the price of the book in itself — but Dan also talks about good practice when writing CSS (with a nod to CSS Lint), he points to articles on general JavaScript development, and gives a nod to accessibility.

One thing I wasn’t so keen on was the spy astronaut headings in each chapter. I thought they went just that little bit too far past fun and quirky into annoying and distracting, but they’re only headings so didn’t get in my way too much and may well make the book more readable for other people.

Another thing that wasn’t so hot was that the download to accompany the book didn’t work for me at all. I tried a few times over a couple of weeks in different browsers, but not dice unfortunately. Hopefully the publishers will have that sorted soon.

Overall I would definitely recommend this book for anyone looking to use jQuery. It’s a real eye-opener and I’d be surprised if you didn’t learn plenty about the library and its capabilities, and indeed plenty about web development in general.

If you would like to buy jQuery Hotshot you can get it on Amazon at http://www.amazon.co.uk/jQuery-Hotshot-ebook/dp/B00BFQ61GU/ or the publisher Packt at http://www.packtpub.com/jquery-hotshot/book (those aren’t affiliate links).

Finally I’d like to point out that apart from a free copy of the book as an ebook I didn’t get paid for this review. It’s my honest opinion of the book and my only connection to Dan is the very occasional conversation in the public timeline on twitter.

Using AJAX with WordPress for conditional loading

AJAX has become a big part of responsive design for me. I use it to load secondary content into larger viewports to make it easier to find/view than if it is behind a small link in the footer or somewhere like that.

In WordPress it’s really easy to do, but this is one of those situations where I couldn’t find a definitive guide to how it’s done, so I’ve written this that will hopefully fix that.

Two steps:

  1. Build a PHP function that creates whatever it is you need.
  2. Build an AJAX request that goes and gets it.

WordPress handles everything else using /wp-admin/admin-ajax.php

As an example let’s say we want the titles of the latest five posts to show up in a sidebar on each single post. It’s not vital content and can easily be accessed by going to the top level page that shows the latest five, but it might be nice to have for some people and we have the room.

The first thing to do is create a PHP function in our theme’s functions.php with a WordPress loop that creates the list.


function get_latest() {
	$args = array(
		'posts_per_page'  => 5,
		'category'        => 1,
	);

	$posts_array = get_posts($args);

	echo '<nav role="navigation">';

	echo '<h2>Latest News</h2>';

	echo '<ul>';

	foreach ($posts_array as $post):
		setup_postdata($post);
		echo '<li><a class="' . esc_attr("side-section__link") . '" href="' . esc_attr(get_page_link($post->ID)) . '">' . $post->post_title . '</a>';
	endforeach;

	echo '</ul>';

	echo '</nav>';

	die();
}
// creating Ajax call for WordPress
add_action( 'wp_ajax_nopriv_get_latest', 'get_latest' );
add_action( 'wp_ajax_get_latest', 'get_latest' );

It’s a straightforward WordPress function — it could be anything at all, even something as simple as echo '<a href="https://twitter.com/intent/user?user_id=123456789">follow me on twitter</a>. There are two things worth noting however.

The die() is necessary at the end to stop any further PHP processing in /wp-admin/admin-ajax.php which outputs 0. If we don’t use die() at the end of our function a 0 will appear after our list.

The other thing to note is the block of two add_action() functions. This will not work without them.

Now to the front end. We need to create a JavaScript function that calls /wp-admin/admin-ajax.php and tells it which PHP function to run.


jQuery.ajax({
	type: 'POST',
	url: '/wp-admin/admin-ajax.php',
	data: {
		action: 'get_latest', // the PHP function to run
	},
	success: function(data, textStatus, XMLHttpRequest) {
		jQuery('#latest-news').html(''); // empty an element
		jQuery('#latest-news').append(data); // put our list of links into it
	},
	error: function(XMLHttpRequest, textStatus, errorThrown) {
		if(typeof console === "undefined") {
			console = {
				log: function() { },
				debug: function() { },
			};
		}
		if (XMLHttpRequest.status == 404) {
			console.log('Element not found.');
		} else {
			console.log('Error: ' + errorThrown);
		}
	}
});

All we need to do in here is tell the function which PHP function to run and where to put the output, in this case in a container element with id latest-news.

You can wrap the jQuery function in a matchMedia test or use a technique that uses JavaScript to test a CSS property value that only applies to larger viewports.

That’s all there is to it. It’s quick and easy but a reliance on jQuery might not be your bag. However AJAX is one thing jQuery is very good at getting working cross browser painlessly.

Flexbox vertical ordering

The only times I’ve had cause to use flexbox in anger is for content re-ordering, or as Jordan Moore more eloquently puts it, content choreography. Even at that I’ve only ever used vertical re-ordering and that’s all I’ll be talking about in this post. Other more comprehensive resources are listed at the end.

A project I am currently working on is a large content site with gazillions of pages and sub pages. We decided to keep the main navigation simple (6 or so items) and display a list of sub pages in each category.

In smaller viewports the list is in a block just before the page footer and on larger viewports we decided to move it under the main navigation at the top of the page and visually tie it to its parent menu item using colour.

Demo one is a page with the basic markup and style that roughly reflects the project before flexbox is used, and for clarity I’ve left out the page header and footer.

From top to bottom it’s:

  1. a div containing the main content block and a secondary block
  2. another secondary block
  3. the block containing the list of sub pages.

It’s these three blocks that we’ll be reordering using flexbox.

The web designer’s web designer Chris Coyier recently wrote about the best way to get flexbox working in as many browsers as possible so we’ll use that as the baseline for our vertical ordering.

The boxes that are to be re-ordered need to be wrapped in a container with the display set to flex.


.l-flex {
	display: -moz-box;
	display: -webkit-box;
	display: -webkit-flex;
	display: -ms-flexbox;
	display: flex;
}

The default display is horizontal so to change that we’ll add the declarations to make it vertical.


.l-flex {
	display: -moz-box;
	display: -webkit-box;
	display: -webkit-flex;
	display: -ms-flexbox;
	display: flex;
	-moz-box-orient: vertical;
	-webkit-box-orient: vertical;
	-webkit-flex-flow: column;
	-ms-flex-direction: column;
	flex-flow: column;
}

Now to reorder the boxes we just need to add a declaration for the order of each box.


.l-flex-1 {
	-moz-box-ordinal-group: 1;
	-webkit-box-ordinal-group: 1;
	-webkit-order: 1;
	-ms-flex-order: 1;
	order: 1;
}

.l-flex-2 {
	-moz-box-ordinal-group: 2;
	-webkit-box-ordinal-group: 2;
	-webkit-order: 2;
	-ms-flex-order: 2;
	order: 2;
}

.l-flex-3 {
	-moz-box-ordinal-group: 3;
	-webkit-box-ordinal-group: 2;
	-webkit-order: 3;
	-ms-flex-order: 3;
	order: 3;
}

Demo two has the flexbox included and uses media queries so it only happens above 50em. Now the list of sub pages is displayed at the top of the document.

One thing to note at this point is that Firefox doesn’t support percentage widths on the ordered boxes. Demo three has 50% width declared on all the boxes and it has no effect in Firefox (screenshot). Your options are either add an extra element inside the box and give it a percentage width, or remove the -moz- prefixes and use the less enhanced layout. This is a 3 year old bug which could means it’s not high priority or could mean it’s close to the top of the fix me pile. I have no idea how these things work.

Demo four has the main content floated to the left and the first aside floated to the right, a pattern I use in this project.

This is fine in all browsers except Chrome, which goes completely buck mad with disappearing content, overlapping content and huge spaces (screenshot). Somehow the floats in one box throw grenades all over the rest of the page.

Fortunately there are two ways to prevent this.

The easiest method is to clear the floats using overflow:auto or overflow:hidden as in demo five. The clearfix method currently in HTML5 Boilerplate doesn’t help.

The second way is to replace the floats with inline-block elements, as shown in demo six.

Opera, IE10 and Safari display things as intended with no surprises, Opera being the only one that works without prefixes. That makes flexbox one area of web standards that will take a step back if WebKit don’t squash the bugs and un-prefix before Opera switches rendering engine.

For me, a side effect of this brief foray into flexbox is an extra bit of weight for the argument against vendor prefixes. I’m thankful flexbox is prefixed in Gecko and WebKit as it is buggy. That pretty much explains the purpose of vendor prefixes–they’re experimental and need to be thoroughly tested before the prefix comes off.

I am ambivalent though. I use vendor prefixes occasionally and there are plenty that apparently don’t have any bugs but remain prefixed.

When I was working on the project that spurred me to write this I initially chose to only use flexbox in Opera and IE10. Firefox and Chrome were broken, time was short, the prototype needed to be sent to the client, and I didn’t figure out the fix for Chrome until writing this post and creating the stripped back demos. After giving it some thought I settled for changing display:flex to display:table;caption-side:top and changing order:3 to display:table-caption which works all the way back to IE8. If you don’t know what I’m talking about Jeremy Keith explains it better than I ever could in his Re-tabulate post.

This is only a few things I have encountered in a narrow use case of a small aspect of flexbox. My favourite comprehensive article on the subject is Chris Mill‘s opus Flexbox — fast track to layout nirvana? in which he smashes Betteridge’s Law into tiny pieces and I recommend you read it. When flexbox is widely supported and bug free it will revolutionize web layout.

All the demos are on Github.

Resources

Notes on the classList API

For me the classList API is one of the most useful parts of HTML5. Manipulating classes is an everyday part of JavaScript on the web, but is a cowpath that required a sure foot to tread before before getting the full treatment from the pavers in the form of classList.

The basic syntax is element.classList.method where method can be one of the following:

  • add
  • remove
  • toggle
  • contains
  • item
  • length
  • toString

classList.add()

If all you need to do is add a class to an element use classList.add(). Let’s say you have a div with an id of box and you want to add a class of “highlight” it would work like so:


var box = document.getElementById('box');
box.classList.add('highlight');

The class is now added in the DOM and declarations in CSS for .highlight will be applied to the element.

More classes can be added the same way, so you can go ahead with box.classList.add('highlight--sidebar') or box.classList.add('l-wide') or any other classes you like.

You can only add one class at a time, so box.classList.add('class-1','class-2') doesn’t work.

classList.remove()

If we want to remove a class from the list it’s just as simple:

box.classList.remove('highlight');

The class has been removed in the DOM and any side effects of that will be applied.

classList.toggle()

The toggle method is useful for things like show/hide interfaces where the same action has opposite effects.

If there’s a button in our markup we can listen for clicks on it and use it to switch the highlight class on and off.


button = document.querySelector('button');
toggleBox = function() { box.classList.toggle('highlight'); };
button.addEventListener('click',toggleBox,false);

classList.contains()

If we need to check whether or not a particular class name is in the list we can use classList.contains() to return true or false.

It could be used to check if an image in a gallery has the class that makes it bigger than the rest or to check if a div has the class that makes it visually hidden for example.


if(box.classList.contains('highlight') {
    // do something
} else {
    // do something else
}

classList.item()

This method returns a string of the value of the item in the list at the index passed as an argument. That probably doesn’t make sense so I’ll it illustrate by using an example. If the HTML is <div class="highlight highlight--sidebar l-wide"> the following are all true:


box.classList.item(0) === 'highlight';
box.classList.item(1) === 'highlight--sidebar';
box.classlist.item(2) === 'l-wide';

The number passed represents the position of the class name in the list, starting to count from 0.

Again it’s dead simple, although I have caught myself using square brackets as if it’s a normal array.

classList.length

This method does what it says on the tin and will be familiar to you if you have done any JavaScript before. It counts and returns how many classes are in the list.

In the example above console.log(box.classList.length) returns 3 as we currently have 3 class names on the element, highlight, highlight--sidebar and l-wide.

classList.toString()

If you ever need to turn the list of classes to a string use this method. console.log(typeof box.classList.toString()) will return “highlight highlight–sidebar l-wide” as a string.

Personally I find I’m using the classList API on pretty much every project now. If you’re not too familiar or comfortable with JavaScript APIs its simplicity makes it a great place to start learning and its usefulness means you’ll probably find a real world application on your current project.

Browser support is good and there are a couple of excellent polyfills I know of if you need to support older browsers. Bear in mind that JavaScript should be an enhancement in web pages so you should have a fallback in HTML and CSS that suffices for older browsers. Ask yourself do you need a polyfill before doing a copy/paste.

Resources

Quick git tip: stash and stash pop

I’ll be moving these quick tips into their own section of the site when I get the time/can be bothered, but until then they’ll be showing up here.

Here’s the scenario: you work on a branch called something like offline, commit the work, then spot an issue that can be fixed with CSS. Acting like you’re a magpie who’s seen something shiny you forget you’re on the offline branch and save a bunch of work.

Now when you go to commit you’re in a branch that doesn’t make sense for the work you’re doing, and if you try to checkout a different branch you can’t.

Here’s what to do:

  1. git stash
  2. git checkout dev
  3. git checkout -b css-fix
  4. git stash pop

And you’re in a more appropriate branch with your CSS changes unstaged.

What the stash command does is get rid of your changes since the last commit and keep them safe until you ask for them back again with stash pop. Simple and very useful.

git –help stash has much more information if you want a closer look.

Why I think we shouldn’t use CSS viewport in IE10 for now

Together with my colleague Toby I’ve been looking at the problems discovered and highlighted by Matt Stow regarding IE10 and responsive design.

The story goes back to Tim Kadlec’s post on IE10 snap mode, a feature of desktop (tablet as well, anyone?) IE10 that allows you to drag the browser window to the left or right of the screen and it snaps to 320px wide.

From our point of view as designers and developers it was a bit of a bummer because websites are scaled when snap mode is activated, whether they are responsive or not. Basically they look like non-responsive sites do on a phone or iPod.

What Tim discovered was that you can add @-ms-viewport{width:device-width} to your CSS and that fixes it. For some reason <meta name="viewport" content="width=device-width"> doesn’t work, but the CSS viewport does.

So anyway, everything was fine until Matt noticed that sites using @-ms-viewport{width:device} width look terrible on Windows Phone 8.

What is happening is that the CSS viewport rule is causing Mobile IE10 to set the viewport to device pixels instead of CSS pixels and everything is a lot smaller than it should be. On the Nokia Lumia 920 this sets the viewport to 768 pixels but with the meta viewport only it’s 320 pixels.

Some screenshots would best illustrate the problem. I don’t have IE10 desktop but I do have a Nokia Lumia 920 running Windows Phone 8 so we can look at it, and you’ll have to take my word for it on the desktop browser.

The BBC news site uses @-ms-viewport{width:device-width} in http://static.bbci.co.uk/news/1.4.3-440/stylesheets/core.css (you’ll need to do Cmd/Ctrl + F as it’s minified CSS) and that fixes the desktop snap mode problem. However on the phone it looks pretty rough as you can see.

Screenshot of BBC News on a Lumia 920
The BBC news site on a Lumia 920. Fiddly.

The BBC home page and sport site on the other hand don’t use the CSS viewport so they look good and are easy to read like they are on any other small device.

Screenshot of BBC Sport on a Lumia 920
The BBC Sport site on a Lumia 920

Screenshot of the BBC home page on a Lumia 920
The BBC home page on a Lumia 920

Another site that is affected by this is Northern Ireland animal charity the USPCA (full disclosure: I did a lot of work on this site in my last job, including adding @-ms-viewport to the CSS). As you can see it looks less than optimal on the 920.

Screenshot of the USPCA home page on a Lumia 920
The USPCA home page on a Lumia 920

So what to do about all this?

Should we be thinking mobile first and figuring out a way of adding the CSS viewport on desktop only? I think we probably should, but not because of blind adherence to “mobile first”.

There may already be more desktop IE10 users than Windows Phone 8 users so it’s not because of numbers. The thing is, the vast majority of sites out there aren’t responsive, and the vast majority of responsive sites in all likelihood don’t have @-ms-viewport, so chances are most times IE10 users use snap mode they’ll wonder why they bothered. Mobile IE10 users on the other hand don’t have the choice. We can either give them an optimal layout or we can make everything look half the size it’s supposed to.

The solution Microsoft recommend is to wrap the viewport in a media query like so:


@media (max-width:25em) {
    @-ms-viewport {
        width: 320px;
    }
}

I don’t think that’s sustainable for two reasons. Firstly, how to we pick our breakpoint? It doesn’t matter if it’s in pixels or ems, if a device comes out that is outside the max-width we’re back to square one.

The second reason is the other side of the same coin. Device sizes are a sliding scale now, not a few fixed sizes from 320 and up, so when a device with a screen size around 6 inches with more than 320 CSS pixels is released we’re changing the media query to match and creating a new @viewport rule. It’s a bit like keeping a database of UA strings up to date – always playing catch up and potentially missing some devices.

For those reasons my preference is to leave out @-ms-viewport altogether. By all means use @-o-viewport as it behaves like we would expect, but until someone figures out a way to detect the features of IE10 desktop that will enable us to identify its capability to support CSS viewport I will be omitting the IE version.

If you’re really stuck use a UA sniff, but be aware it’s not a good long term solution. A small script in your language of choice that checks the UA string for MSIE while making sure IEMobile isn’t in there then adds the CSS is the general idea.

Perhaps the wider lesson is that we should avoid using vendor prefixes, but that’s a whole other bag of mad snakes.

I’d love to hear what you think about all that, so please leave a comment or ping me on twitter.

Credits

Toby Osbourn for saying things that make me thinky.