Perfect responsive images: HTML5 <picture> and Bootstrap 4
Bootstrap 4 is in alpha release and has a brand new set of media queries and breakpoints. Where Bootstrap 3 had them in pixels, the new release of the popular responsive framework boasts breakpoints in ems. Let's harness the power of these new media queries to serve an image of the right size based on the device a user views our site on. We're going to save a lot of bandwidth for the small devices, and serve a beautiful large image for larger ones. We'll do that by using the HTML5 picture
element and its powerful source
tag and media
and srcset
attributes. Are you ready to start serving perfect responsive images?
Bootstrap 4 Media Queries
First, let's have a look at the brand new media queries and breakpoints that Boostrap 4 offers. They are tailored to match the newest devices, including iPhone 6s and iPhone 6s Plus:
// Extra small devices (portrait phones, less than ???px)
// No media query since this is the default in Bootstrap
// Small devices (landscape phones, 34em and up)
@media (min-width: 34em) { ... }
// Medium devices (tablets, 48em and up)
@media (min-width: 48em) { ... }
// Large devices (desktops, 62em and up)
@media (min-width: 62em) { ... }
// Extra large devices (large desktops, 75em and up)
@media (min-width: 75em) { ... }
As you can see, the queries use ems - instead of pixels - to tell devices apart, and break them into categories:
- portrait phones
- landscape phones
- tablets
- desktops
- and large desktops
Let's make a mental - or written if your prefer - note of the four em sizes that Bootstrap 4 uses natively, as we're going to need them at the end of this guide. And let's head over to the next piece of the puzzle we're putting together.
HTML5 <picture> element
The picture
element is one of the many smart elements available in the HTML5 specification, and allows us to serve a different image depending on the size of the browser viewport. The approach is much smarter than using a single image and resizing it in a CSS file or a style
tag. We're not only making an image fit. We are serving a different image for each viewport size. A standard code example looks like this:
<picture>
<source
media="(min-width: 800px)"
srcset="picture-large.jpg, picture-large-2x.jpg 2x">
<source
media="(min-width: 450px)"
srcset="picture-small.jpg, picture-small-2x.jpg 2x">
<img
src="picture-tiny.jpg"
srcset="picture-tiny-2x.jpg 2x" >
</picture>
If you're new to the picture
element, maybe that's too much information to take in in one go. So let's break everything down and analyze each element separately.
picture
That's the wrapper tag that tells an HTML5-enabled browser that we are going to serve different image sizes depending on the viewport. All you have to do is put it around your source
and img
tags. As is, no attributes needed.
source
We need a source
tag for each screen size we decide to serve. Each source
will contain a media
and a srcset
attribute.
media
The min-width
of our media query goes here. My guess is you are familiar with media queries. If you aren't, read more about media queries and responsive layouts. The min-width
will trigger based on the viewport size and load the image source from our next attribute, srcset
.
srcset
Our image source goes here. We're going to serve an image whose size is tailored exactly for the viewport that triggered our media query. For the more advanced users - and as you see in the code example above - this attribute can also be populated by a comma separated set of sources. Each of them will load a different image based on pixel density of the device. For instance iPhone 6s has pixel density 2x, where iPhone 6s Plus has 3x. That's it! Now we know everything we're going to need to use the picture
element. Are you ready to continue our journey and adapt this knowledge to serve perfect sized images on Bootstrap 4?
Putting it all together: HTML5 responsive images for Bootstrap 4
What we're going to do now is simple: we'll take that standard example of the picture
element we just examined and adapt it to harness the power offered by our Bootstrap 4 media queries. We'll need 5 different images, and for our final step we're going to use these example image names: extralarge.jpeg, large.jpeg, medium.jpeg, small.jpeg and extrasmall.jpeg:
<picture>
<!-- Extra Large Desktops -->
<source
media="(min-width: 75em)"
srcset="extralarge.jpeg">
<!-- Desktops -->
<source
media="(min-width: 62em)"
srcset="large.jpeg">
<!-- Tablets -->
<source
media="(min-width: 48em)"
srcset="medium.jpeg">
<!-- Landscape Phones -->
<source
media="(min-width: 34em)"
srcset="small.jpeg">
<!-- Portrait Phones -->
<img
src="picture-tiny.jpg"
srcset="extrasmall.jpeg" >
</picture>
And our work is done. We're now serving responsive images: a perfectly sized image for each device our site is displayed on. We're saving bandwidth, and we're making sure our users see our images in the best format, adapted to their screen size. This is a responsive approach, so a different image will be loaded when a user expands and shrinks their desktop browser window. Have a play and see for yourself: keep your Chrome Developer Tools / Firebug open on the Network tab, resize the browser window, and see if a new image is requested each time you hit a breakpoint. If it does that means you did everything right. If it doesn't, go through this step-by-step guide again and double check your code against our examples! **Note: **The order of the source
tags is essential. Start from the bigger sizes, proceed with the smaller ones, and make sure the default img
tag contains the smallest image. Otherwise the browser will disregard our source
tags and always load the image specified in the img
tag.
And what did we learn?
Bootstrap 4 is about to be released, and is already available as an alpha release. We can harness the power of the new advanced media queries in ems and use the HTML5 picture
element to serve responsive images - a perfectly sized image for each device our site is viewed on. That approach is elegant, saves bandwidth, and ensures each device receives the best looking picture.