I am working on a website (with Statamic v3 which uses Antlers, Bootstrap, SCSS) which involves different uploads for mobile and desktop backgrounds (inline styling). What is the best way to do this? I am struggling quite a while with these kind of questions. Ofcourse I can use display none and display block with media queries, but I'm hoping for a solution where only the mobile image loads on mobile/ small screen sizes, and only the desktop image loads on desktop/ big screen sizes so it is better for the page load.
For the img tag it is possible to use the img srcset, but with an background image that is not possible. I am also questioning myself how I can do this with partials/ elements with just a lot of code (so not necessarily with background images)
I also tried to use the mobile detect with JavaScript, but the problem with that is if the user is working on desktop but with a small browser view, it doesn't get the 'mobile version' of the website.
I mostly end up with using Bootstraps d-none and d-block with media queries, but that doesn't feel right.
Anyone has a best practice for this with keeping good pageload in mind?
Edit: I added some code to show what I am trying to achieve. The user can upload a desktop background image, and a mobile background image at the CMS. As far as I know both of these images will be loaded into the page, but they won't show at the same time because of the display properties. My goal is that the page won't load both of the images, but only the image that is needed on that viewport size. I can't do this inside my SCSS with media queries, because I can't set the background url's inside my SCSS.
<div class="row d-md-none main-content" style="background-image: url('{{ bg_image_desktop }}')">
<div class="offset-md-2 col-md-8">
<h1></h1>
</div>
</div>
<div class="row d-none d-md-block main-content" style="background-image: url('{{ bg_image_mobile }}')">
<div class="col-12">
<h1></h1>
</div>
</div>
You can use media queries with a bit of JavaScript to achieve what you want. The idea is to use a data-*
attribute to pass the URLs of the images to the page, then copy the URLs to CSS variables using JS, and finally a media query shows the wanted image depending on the screen width. Like this:
(function () {
const div = document.querySelector('.bg-image'),
src = div.getAttribute('data-bg').split(','), // Exctracts URLs from data-bg to an array
html = document.documentElement; // A reference to <html> element
html.style.setProperty('--bg-desktop', `url(${src[0]})`);
html.style.setProperty('--bg-mobile', `url(${src[1]})`);
}());
/* :root is <html> element */
:root {
--bg-desktop: none;
--bg-mobile: none;
}
.bg-image {
min-height: 200px;
}
@media screen and (max-width: 768px) {
.bg-image {
background-image: var(--bg-mobile);
}
}
@media screen and (min-width: 769px) {
.bg-image {
background-image: var(--bg-desktop);
}
}
<div class="bg-image"
data-bg="https://cdn.pixabay.com/photo/2016/09/04/20/14/sunset-1645103_960_720.jpg,https://cdn.pixabay.com/photo/2018/05/18/16/41/globe-3411506_960_720.jpg"
>
</div>
For the presentation purposes I've hardcoded the URLs in the data-bg
attribute, but in practice, you'll write the value with the placeholders, which are then replaced with the correct URLs by your server:
data-bg="{{ bg_image_desktop }},{{ bg_image_mobile }}"
Because images in unapplied CCS rules are not loaded, this way you can ensure, that the desktop image will not be loaded on devices having screen smaller than 769px (or what ever you put to min-width
). On a desktop machine, one of the images is loaded at first, then when resizing the window, also that other image is loaded, if the limit is crossed.
You can also play with the code at jsFiddle.