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 🙂