Optimizing Responsive Layouts

Posted

Styling for a range of different screen sizes is rather easy in CSS thanks to media queries. But what if you want to deliver slightly different content or markup based on screen size?

WordPress has a wp_is_mobile tag that can be used- but this covers a wide array of devices and doesn’t allow for specific screen size targeting.

Here’s a couple techniques I’ve been using that are a pure front end solution:

Detect Screen Size with Javascript

As soon as document.ready fires, we’re able to detect the screen width with javascript. Here’s a snippet that checks if the screen width is great than 690px, and then does something (like alter markup or append items to the DOM).

jQuery(document).ready( function() {
     if ( document.body.clientWidth > 690 ) {
          // Do Something
     }
});

Load Only Required Scripts

There’s a number of small javascript libraries that will help you load scripts based on screen size (some even use the familiar syntax as CSS media queries). Enquire.js is one to check out.

But I generally just use my own homebrew method. I include this tiny javascript function in my global scripts:

// Post Load Scripts
function lazyScript(check, url, callback) {
	if ( ! check() ) { return; }
	$.ajax({
		url: url,
		dataType: 'script',
		success: callback,
		cache: true
	});
};

And, then, using the method from above to detect screen size, I can load a lightbox script (for instance) when I’ve detected the screen size is above 690px:

$(document).ready( function() {
     if ( document.body.clientWidth > 690 ) {
     // Lightbox script for article image
     lazyScript(
          function() { return $('body').is('.single-post'); },
          '/scripts/jquery.lightbox.js',
           function() { $('img').lightbox(); }
     );
});

Ad Loading

Ads can make a website slow to a crawl. I try to put them in an iFrame whenever possible and post load them on a site. If you use this technique, you can also detect screen size and then load the most appropriate ad size for the screen.

Quick example of appending an iFrame:

// Banner Ad
var banner_ad = $('<iframe id="banner-ad" src="/includes/banner-ad.html" scrolling="no" marginheight="0" marginwidth="0" frameborder="0"></iframe>').css({'height':'90px','width':'720px'});
$('#banner-ad-container').empty().append(banner_ad);

Lazy Load Images

Optimizing image loads is the holy grail of responsive design at the moment. One technique I’ve used is lazy loading. This replaces all image sources with a single transparent pixel (src=”pixel.gif”), or if you’re really going for it, a data uri. Then on window.ready, swap out the src with the real image source that has been saved in a data attribute (‘data-src’).

Here’s what the image tag would look like:

<img src="/pixel.gif" data-src="/my-image.jpg" width="100" height="100">

Here’s the tiny jQuery plugin I use:

// Lazy Load Images
$.fn.lazyImage = function(callback) {
	var imgLen = this.length,
			count = 0;
	return this.each(function() {
		if ($(this).attr('data-src')) {
			var imgTag = this, imgSrc = $(this).attr('data-src'), del;
			i = new Image();
			i.onload = function() {
				$(imgTag).attr('src',imgSrc).fadeTo(400,1,function() {
					(count++ && imgLen == count) && (typeof callback == 'function') && callback.call(this);
				});
			};
			i.src = imgSrc;
		}
	});
};

Here’s the call that loads the image:

$("#content img").lazyImage();

This technique could also easily be adapted to optimize the images for the screen size. Instead of one data attribute, include two. One for the standard (large) size, and one for a small size.

<img src="/pixel.gif" data-src-large="/my-image-large.jpg" data-src-small="/my-image-small.jpg" width="1200" height="600">

add_image_size allows you to easily generate those two different sizes in WordPress. The above jQuery script would just need some small tweaks to then detect screen size and load the appropriate image.

About Devin

I'm a WordPress developer based in Austin, Texas. Follow my projects on GitHub, or more general WordPress ramblings as @devinsays on twitter.

3 thoughts on “Optimizing Responsive Layouts

  1. omid wrote:

    hey devin thanks for awesome tips, however i want to ask how can i generate those data attributes into an image in the back-end ( for theme development purposes)?
    again thanks for great posts :D

  2. Marty wrote:

    Great stuff, Devin, thanks!

    I wonder if you’ve ever tried to address image dimensions with Lazy Load?

    When setting image widths to 100% we’re depending, of course, on the height being calculated automatically. And with Lazy Load, that height doesn’t get determined ’till the user gets down to it. It’s not always an issue, but I’ve found it sometimes can be — when using something like Packery, for instance. Have you seen or used any techniques that attempt to address this?

    • Devin wrote:

      Hi Marty. Are you outputting the height/width dimensions of the image? My thought is that it should be able to scale if it has those set, but I might be incorrect. You could also try triggering a reload event for packery in a lazy load callback.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>