3 Wrong Ways to Code Responsive Images

I often see a site unknowingly load both desktop and mobile images. But that is understandable since the way image loading works is quite weird.

I often see a site unknowingly load both desktop and mobile images. But that is understandable since the way image loading works is quite weird.

In this article, we will take a look at common mistakes when hiding images for responsive purpose.

1. Using Multiple IMG elements

Any Image that has src attribute will always load even if you hide it.

Example:

<!-- All 3 images are loaded -->

<img src="mobile-logo.png" class="show-on-mobile">
<img src="tablet-logo.png" class="show-on-tablet">
<img src="logo.png" class="show-on-desktop">

To fix that, use <picture> element:

<!-- Only 1 is loaded depending on screen size -->

<picture>
  <source srcset="mobile-logo.png" media="(max-width: 480px)">
  <source srcset="tablet-logo.png" media="(max-width: 767px)">
  <img src="logo.png">
</picture>

My rule of thumb: put the largest image in <img> tag for IE compatibility. The source should be ordered ascendingly and uses (max-width) media query.

2. Doesn’t Wrap All Background Image in Media Query

The background image that is not wrapped in media query will be loaded on all screen sizes.

In the example below, both images will load on mobile screen:

.hero {
  background-image: url('desktop-banner.jpg');
}

@media (max-width:767px) {
  .hero {
    background-image: url('mobile-banner.jpg');
  }
}

To fix that, wrap both properties with media query:

@media (min-width:768px) {
  .hero {
    background-image: url('desktop-banner.jpg');
  }
}

@media (max-width:767px) {
  .hero {
    background-image: url('mobile-banner.jpg');
  }
}

3. Hide the Wrong Element

Unlike <img>, you can stop a background image from loading by hiding its parent.

But I often see people hid the background element itself, which doesn’t stop it from loading:

<!-- Both images still loads -->

<figure style="display: none;" style="background-image:url('desktop-banner.jpg');">
  ...
</figure>

<figure style="background-image:url('mobile-banner.jpg');">
  ...
</figure>

To fix that, add a wrapper and hide that instead:

<!-- This will only load mobile banner -->

<div style="display: none;">
  <figure style="background-image:url('desktop-banner.jpg');">
    ...
  </figure>
</div>

<div>
  <figure style="background-image:url('mobile-banner.jpg');">
    ...
  </figure>
</div>

Extra Tip

If you don’t want to add parent wrapper, you can set the background value to none:

<figure class="desktop-bg" style="background-image:url('desktop-banner.jpg');">
  ...
</figure>
<figure class="mobile-bg" style="background-image:url('mobile-banner.jpg');">
  ...
</figure>
@media (min-width:768px) {
  .mobile-bg {
    display: none;
    background-image: none !important;
  }
}

@media (max-width:767px) {
  .desktop-bg {
    display: none;
    background-image: none !important;
  }
}

We add !important because we want to override the inline style. You don’t have to add that if the background is not inline.


Conclusion

It’s a big performance loss if your site loads both desktop and mobile images.

After following these tips, use the Network tab in DevTool to check whether they are loaded properly.

Leave a comment below if you have further question about responsive images 🙂

Default image
Henner Setyono
A web developer who mainly build custom theme for WordPress since 2013. Young enough to never had to deal with using Table as layout.
Leave a Reply