Best practices for full width browser images?


What are the best practices people follow in respect to images on larger viewports?

What size browser should we design for? Meaning how do we deal with high resolution monitors and what % of users have large screens?

How can we best deal with the height of hero images, as we really need to decide which screen resolution to go with?

Of course, all of this is while keeping to the 12 column grid philosophy ;)

11/8/2014 9:14:00 AM

Accepted Answer


While above comments make very good technical points, I suggest tailoring your work to particular client, which starts by looking at their current site's Google Analytics - Reporting / Technology / Browser & OS / Screen Resolution. This way, you will be spending your time and your client's budget wisely by addressing your client's specific needs as opposed to implementing general guidelines. We actually had to advise our clients on occasion against doing fully responsive design simply because their non-desktop traffic would not justify the expense.

11/9/2014 2:05:00 PM

There are several things to keep in mind when serving images to viewers.

  1. Keep the image ratio the same as the original dimensions

We do this to prevent the image from getting skewed and to prevent images from being blurry. We can either keep the dimension ratio the same or clip off parts that don't fit.

When using an <img> element or something similar, this is fairly straight forward, it just requires using a set width or height OR set max-width or max-height.

However in the case of a full viewport width image this is a little more complex. There are several CSS ways to do it, the best of which is background-size:cover like the first linked example in the article and Talkingrock' answer show.

In addition, we now have the ability to use the features found in the responsive images specification including srcset and the <picture> element, which are quite useful. I talk about this more later on in this answer.

  1. Give viewers only the image(s) they need

In order to have a quicker page load and prevent users from needing to transfer more data, it is vitally important to serve the end user only the image(s) that they need, when they need them. This means we serve them an image the same size or just a little larger than the one the viewport they're using and waiting to load images that will not be seen immediately until after the initial page load.

We can serve a more appropriately sized image using CSS by using @media queries when we're using background images. The images not in the media query being used are not loaded. I'd recommend using at least three photo sizes (which means at least 3 media queries), but having a couple more could be heplful performance wise. The following is an example, but it should usually coincide with some general breakpoints for your site's layout.

@media (max-width: 320px) { /* For phones (this breakpoint is the one I'm least sure about) */
    ... background-image(imageURLforPhones.png); ...
@media (min-width:501px) and (max-width: 1024px) { /* For tablets and such */
    ... background-image(imageURLforTablets.png); ...
@media (min-width: 1025px) { /* For large screens */
    ... background-image(imageURLforLargeScreens.png); ...

But, let's face it: we're not good at choosing breakpoints nor are we perfect at choosing image dimensions given a certain screen size. Wouldn't it be great if we could let the have something do this 'magically' for us?

The great news is that now we can!

With the responsive images specification, we can let the browser decide all of this for us, provided we help it out a little. The ever so useful srcset property can be used with an <img> or a <picture> element. For resolution switching like we're doing here, we should use an <img> element.

The following is an example of the HTML needed to allow srcset to do its job. For more, you can read Yoav Weiss' great article on the subject. The example is pulled from it.

<img src="cat_500px.jpg"
     srcset="cat_750px.jpg 1.5x, cat_1000px.jpg 2x"
     width="500" alt="lolcat">

Side note: If you need to serve the same image with different dimensions at certain viewport sizes, you can using the sizes attribute.

I'm not saying that using srcset is necessarily better than using a CSS background image, I haven't done enough work with it myself to say so for sure, but it is potentially a better way.

Also, to help with performance we can "lazy load" images that won't be visible initially. This means that we prevent them from loading initially but start loading them as soon as the initial page is done loading. That way we can get the viewer to see the page as soon as possible and fill in some details later. Here's a way to do that, I won't go into much detail right now.

  1. Make sure that the content in the image you want to show is shown

If we have the correct dimensions and great performance that's awesome, but if the viewer doesn't see what we want them to see there is no point. If we are showing the image completely all of the time this is not a problem, but if we have to crop the image this can be a problem.

We can crop background-images using CSS by using background-size and background-position (and sort of using clip, but that's usually used for more artsy, complex shapes). The exact details of this will vary from image to image depending on how it is being implemented.

The second option is to use the <picture> element. We use this when we only want part of the image to show, as seen here, but here's a simple example of it in practice (pulled from Jason Grigsby's great article on this subject).

    <source media="(min-width: 45em)" srcset="large.jpg">
    <source media="(min-width: 32em)" srcset="med.jpg">
    <img src="small.jpg" alt="The president giving an award.">

I want to reiterate, if you only need to do resolution switching don't use the <picture> element, just use the <img> element with srcset. The only time we need the <picture> element is for this art direction, meaning clipping, etc.

There's also the possibility of doing some cropping server side, using an SVG mask, or doing some stuff with Canvas, but that's a bit outside of the scope of this answer.

Some other notes

Specific breakpoints are not that important. As with all responsive design, it's important to do the best as we can for all viewports, but there are no media queries that will be perfect for all sites.

Page load time is very important, and images can slow down the initial load time by a lot. Make sure you load images that will be immediately seen first, then others. Try to prevent images (like JPEGs) from showing part of the image while it loads the rest. Also optimize all of your images so that they are the smallest file size possible while still having the amount of quality you require.

It's important to remember that images, in most cases, should be an accessory, not a necessity. I recommend to always test how a webpage looks like without images to make sure it's usable.

Note: We can use a polyfill called Picturefill to serve older browsers that don't support the responsive images specification.