When In Focus was first built for The Atlantic in 2011, TheAtlantic.com was already on three different content-management systems, or CMSs, each powering different parts of the site. The majority of TheAtlantic.com's traffic was from desktop computers. Today, we have standardized on one CMS, called Ollie, and half of TheAtlantic.com's traffic comes from phones and tablets. The one exception was In Focus, which neither used Ollie nor worked on phones.
While an increasing number of users are reading our site on smaller screens, the average size of desktop monitors has increased over the past four years. Over 55 percent of our desktop readers have screens larger than 1,300 pixels wide. To improve In Focus for all of our users meant increasing the maximum width of images for our desktop users while also keeping image sizes small enough to load on cellphones. However, these goals are conflicting. You cannot simultaneously increase the size of your images in pixels while reducing their size in megabytes.
One possible solution was to use an image as wide as the median width of our screen sizes. Say the median screen size across desktops, tablets, and phones is 1,000 pixels wide. We could use a single, 1,000-pixel-wide image that would then scale to fit any browser width. This would certainly improve the experience for the average user, but how would it affect the rest of our users?
Not in a very good way, it turns out. If we ask a user's browser to scale a 1,000-by-750-pixel image to 1,200 pixels wide, the browser would be left to fill in an additional 330,000 pixels. While this is certainly something browsers can handle, the resulting image will be blurry. In the example to the right, slide one is a screenshot of an image scaled to be 20 percent wider and slide two is that same image scaled down from the original using Photoshop. You'll notice that slide one is noticeably blurrier than slide two. We wanted our photography to display beautifully on any platform—settling for blurry images clearly wouldn't work.
Another issue is that all iPhone screens are narrower than 450 pixels. Data and memory limitations of even the latest models of smartphones limit our options for scaling down larger images. If a user with an iPhone 5 will only see an image as wide as 320 pixels, is there value in loading an image almost three times wider than his or her screen?
Since one image, scaled in a browser, wouldn't work, we needed to have multiple different sizes that we could show at correct screen widths.
Luckily, The Atlantic's in-house CMS, Ollie, has a system to upload and crop images, called Cropduster. One important feature of Cropduster is that it can crop multiple sizes of the same image. An editor can upload an image, crop it, and then automatically use that image in multiple sizes in different sections of the site. These different crop sizes are typically used on different areas of the site.
We decided on a set of four standard crop sizes ranging from 600 pixels wide to 1,500 pixels wide. For smaller screens, we took the two smallest crops (600 pixels and 900 pixels wide) and let browsers scale them exactly in half.
But, once we pulled the images out of the database, we ran into the challenge of displaying them. Currently, the most common way to handle responsive images is to set different background images at different widths using CSS media queries. However, with six different image sizes shown at different widths, the media queries can get tricky. Which image size do we show when the screen is between 992 pixels and 1,292 pixels wide? What about between 542 pixels and 692 pixels? (The answer to both is a 900 pixel-wide image). Keeping these sizes straight was already challenging enough, and writing this by hand would not be maintainable.
We have been using SCSS as a pre-compiler for the last few years and found its mixins system incredibly useful. To help keep track of which width corresponded to which breakpoint, we wrote a mixin that took the width of an image, a list of all image width, and an optional argument for padding around the images. It then generates the correct media query for us so we don't have to worry. See the code below:
With this mixin, correctly displaying images becomes as simple as iterating over the list of images and widths in our template:
An additional benefit to using this mixin is that we can easily add or remove image widths, depending on how big our source images are. If desktop monitors continue to grow larger, we can simply just add a new image width in our system and everything will be updated automatically. The results can be seen in a responsive design simulator.
New recommendations, including the
picture element and the
srcset attribute help to solve the harder problems of displaying different images for different sizes, but they do not have wide support across browsers yet. We considered using a polyfill, but fewer than half of our users have browsers that support the new responsive elements and attributes, so we spent our resources optimizing for our larger user base.
Plus, the pace of adoption for new elements has been increasing over the past few years—so we will continue to refine our approach.