1

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>
SoofNikki
  • 13
  • 1
  • 5
  • "_with a small browser view, it doesn't get the 'mobile version'_" Why should it? Your criteria to load different images is "_mobile image loads on mobile, and only the desktop image loads on desktop_", that will be fully fullfilled with mobile detection. You can ofcourse pick an image to load based on the screen width with media queries too, but then it's not mobile vs. desktop, rather just screen width dependent. – Teemu Jan 21 '21 at 13:34
  • @Teemu The reason why I want that is because the element/ background image looks different on a smaller screen size than a big screen size. I can do that with media queries, but then it already loads the html element (with the background image) which will load 2 images and is worse for pageload. Do you get what I mean? – SoofNikki Jan 21 '21 at 13:46
  • AFAIK the images in unapplied CSS rules are not loaded ..? – Teemu Jan 21 '21 at 13:47
  • @Teemu I edited my question. I think my biggest problem is that the background image is uploaded from the CMS, so I need to set it with inline styling on an element. I can't 'reach' the CSS with those uploaded images. – SoofNikki Jan 21 '21 at 13:49
  • 1
    @Teemu I'm sorry if I wasn't very clear. I edited my post with some code, I hope that makes this a bit clearer. – SoofNikki Jan 21 '21 at 14:17

2 Answers2

1

The best option would be to use media queries for the element that will contain the background image i.e.

<div class="bgImage"></div>

And then in CSS you would basically use media queries for each break point. I'm going to assume a mobile first design.

.bgImage {
   background: url(path_to_image);
}

@media screen and (min-width: 769px) {
  .bgImage {
    background: url(path_to_tablet_image);
  }
}

@media screen and (min-width: 1200px) {
  .bgImage {
    background: url(path_to_desktop_image);
  }
}

There is a site screensiz.es that contains a bunch of different breakpoints for mobile devices.

Also, upon reading your post again I would also consider using the picture element with different srcset for images.

thatguyjk
  • 11
  • 4
  • That is a great solution, but that won't work with dynamic uploaded background images in a CMS. Because I can't control the CSS with those tags. I need to set the background images inline on the html element. – SoofNikki Jan 21 '21 at 13:42
  • In that case the picture element is what you would want. You just need to make sure your image sizes conform to the different breakpoints you set on each picture source. – thatguyjk Jan 21 '21 at 13:48
  • Yeah I thought about picture and srcset, but that is not possible with background images. – SoofNikki Jan 21 '21 at 13:51
0

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.

Teemu
  • 22,918
  • 7
  • 53
  • 106