WebflowWebflow Enterprise Partner
09Responsive Images

Managing imagery across any responsive site can be a real pain. Background images allow the designer more control over the presentation, allowing for height and width adjustments across different viewports without distorting the image, but they create accessibility issues and require more work to support optimal loading time across viewports (a process that involves cropping and uploading the image at multiple sizes). They also require the creation of a new class for each new background image, which means more effort up front and more effort over time. Image elements are easier to manage and they also leverage Webflow’s responsive images support out of the box. Display, however, can be difficult to control across viewports.

For some time we searched for a happy medium that was still easy to manage in Webflow, oscillating between the two, throwing in some flexbox support for good measure, until we settled on an approach that uses the image-fit: cover; CSS style declaration. Essentially, this approach uses a parent div to define the size and shape of the image across different viewports, inside which the image behaves as if it’s set to background-size: cover;, expanding to fill the div and cropping out any excess image. This approach affords full control over display across viewports, supports accessibility (alt. tag, title, etc.), leverages Webflow’s responsive image support and is easy to maintain in Webflow. This ticked all the boxes for us.

Tip: Since Webflow doesn’t support the object-fit style property out of the box, this has to be added manually as custom code. And since the Designer doesn’t parse CSS added to the Custom Code sections of Webflow, we maintain an HTML embed element as a symbol at the top of each page for CSS styles that the Designer will acknowledge. This way, we can see exactly how the image is going to display in the browser.

HTML Embed

<style>
  
.object-fit---cover {
    object-fit: cover;
  }
</style>

We'll also define a number of styles for the .object-fit class in the Webflow Styles panel. The result mimics background-size: cover; and background-position: center;.

Object Fit - Cover

.object-fit---cover {
  height: 100%;
  width: 100%;
  left: 50%;
  
top: 50%;
  transform: translate(-50%,-50%);
}

To define the size of the image, we generally use percentage padding to create a container that maintains its aspect ratio across the width of a given viewport. For instance, a 16:9 aspect ratio would require padding-top: 56.25%; (9/16 = .5625 = 56.25%). A consistent aspect ratio means a predictable crop of the image, regardless of browser width; we don’t have to worry about essential image content being cropped out or cropped awkwardly, and because the .object-fit image is set to absolute positioning, it will center itself on top of the padding. This also allows for optimized display across different viewports. An image might display at 21:9 on Desktop (padding-top: 42.8571%;), 16x9 on Tablet (padding-top: 56.25%;) and 2x3 on Mobile (padding-top: 66.6667%;), essentially “zooming” in as the viewport gets smaller, cropping off the left- and right-most pieces of the image and maintaining the legibility of the image’s content.

The drawback of this approach is that it doesn’t support some versions of IE, displaying an image that stretched to width: 100%; and height:  100%;. Our fallback is a javascript that displays the image as the background of the parent div, setting the distorted image opacity to 0 (retaining the accessibility attributes). With this approach, cover images should find support on all modern browsers.

HTML Embed

<!-- Internet Explorer Object Fit fallback -->
<style>
/* CSS Fallback from Modernizr */
.object-fit-wrapper.compat-object-fit {
   background-size: cover;
   background-position: center;
}

.object-fit-wrapper.compat-object-fit img {
   opacity: 0;
}
</style>

<!-- JavaScript/jQuery -->
<script src="https://cdn.jsdelivr.net/jquery/2.2.4/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/modernizr/2.8.3/modernizr.min.js"></script>
<script>
// Execute this if IE is detected.
function msieversion() {
   var ua = window.navigator.userAgent;
   var msie = ua.indexOf("MSIE ");
   
   if (msie > 0 || !!navigator.userAgent.match(/Trident.*rv\:11\./)) {
       if ( ! Modernizr.objectfit ) {
           $('.object-fit-wrapper').each(function () {
               var $container = $(this),
                   imgUrl = $container.find('img').prop('src');
               if (imgUrl) {
                   $container
                       .css('backgroundImage', 'url(' + imgUrl + ')')
                       .addClass('compat-object-fit');
               }
           });
       }
   }
   return false;
} // End
$(document).ready(msieversion);
</script>

Read more

Up next

10 Symbols
Runtime: 2m 29s

A great way to manage repetitive elements from page to page is to utilize symbols for components that will appear across multiple pages, such as headers, footers and social.

Take me there