(window.matchMedia().matches bug

Associate
Joined
5 Jan 2005
Posts
2,234
Location
Cyprus
I am using if (window.matchMedia().matches to swap some background images on an element(class) depending on the screen resolution. When l resize the page the corresponding code of the new matchMedia runs but also the code of the previous match media runs as well.
Here is an example of the code:


Code:
var bar_restaurant_images = function () {

// IMAGES 4K   
    
  if (window.matchMedia("(max-width: 7680px) and (min-width: 3441px)  and (-webkit-max-device-pixel-ratio:1.0)").matches) {
    var imagesOfficers = ["officers-mess-section-4k.webp", "officers-mess-section-2-4k.webp", "officers-mess-section-3-4k.webp"];
    jQuery(function () {
      var i = 0;
      jQuery(".officers_mess_section_content_img_wrap").css("background-image", "url(https://officers-mess.co.uk/stage/wp-content/themes/vintclub-child/img/" + imagesOfficers[i] + ")");
      setInterval(function () {
        i++;
        if (i == imagesOfficers.length) {
          i = 0;
        }
        jQuery(".officers_mess_section_content_img_wrap").fadeOut("slow", function () {
          jQuery(this).css("background-image", "url(https://officers-mess.co.uk/stage/wp-content/themes/vintclub-child/img/" + imagesOfficers[i] + ")");
          jQuery(this).fadeIn("slow");
        });
      }, 10000);
    });   

}

else if (window.matchMedia("(max-width: 2560px) and (min-width: 1921px) and (-webkit-max-device-pixel-ratio:1.0)").matches) {

        var imagesOfficers2560 = ["officers-mess-section-2560.webp", "officers-mess-section-2-2560.webp", "officers-mess-section-3-2560.webp"];
    jQuery(function () {
      var i2560 = 0;
      jQuery(".officers_mess_section_content_img_wrap").css("background-image", "url(https://officers-mess.co.uk/stage/wp-content/themes/vintclub-child/img/" + imagesOfficers2560[i2560] + ")");
      setInterval(function () {
        i2560++;
        if (i2560 == imagesOfficers2560.length) {
          i2560 = 0;
        }
        jQuery(".officers_mess_section_content_img_wrap").fadeOut("slow", function () {
          jQuery(this).css("background-image", "url(https://officers-mess.co.uk/stage/wp-content/themes/vintclub-child/img/" + imagesOfficers2560[i2560] + ")");
          jQuery(this).fadeIn("slow");
        });
      }, 10000);
    });   

}


};

jQuery(window).on('resize', bar_restaurant_images);
bar_restaurant_images();
When the page first loads the correct size of background images gets loaded, when the page is resized both the 4K and 2.5K images are loaded to the div and the speed of the delay halves. For example instead of swapping an image every 5000ms the images get swapped every 2500ms or so. In addition it loads both arrays of images (4k+2.5K) to the class. Anyone can shed some light?
 
I suspect it's the duplication of timers; clear current timer before creating another for the slideshow.

Also you're duplicating a lot of code when it's only the image array that changes - arguably, you could create one array with 2560 images, check matchMedia and if 4K replace the array with 4K images.
 
You don't need to use javascript at all to get this functionality, just the srcset tag on the img.
Code:
<img 
srcset="small.jpg 640w, 
      medium.jpg 916w, 
      large.jpg 1030w" 
   src="fallback.jpg"
alt="Responsive image" />

Your browser will choose the appropriate sized image to fit. Or you can tell it exactly which sizes to use for each screen size using the 'sizes' tag:

Code:
<img 
   srcset="small.jpg 640w, 
      medium.jpg 916w, 
      large.jpg 1030w" 
   sizes=" 
      (min-width: 800px) 640px, 
      (min-width: 1256px) 916px, 
      1030px" 
src="fallback.jpg"
alt="Responsive image" />
 
What exactly are you trying to achieve? Because this seems overlay complicated to just display a responsive image for a sequencer. What's wrong with having a single large image that is scaled purely using CSS? Why exactly are you using background images instead of img tags with the srcset attribute?

Oh, and as a suggestion, it's almost 2023. Kill jQuery with extreme prejudice, it's just unnecessary.
 
Last edited:
What exactly are you trying to achieve? Because this seems overlay complicated to just display a responsive image for a sequencer. What's wrong with having a single large image that is scaled purely using CSS? Why exactly are you using background images instead of img tags with the srcset attribute?

Oh, and as a suggestion, it's almost 2023. Kill jQuery with extreme prejudice, it's just unnecessary.
Arguably there's plenty of slideshow libraries/plugins out there but would your solution be?
 
Arguably there's plenty of slideshow libraries/plugins out there but would your solution be?
Probably a set of images in a single size, preload them into an array then cycle through on a single setInterval timer. Thinking about it, to prevent triggering a page reflow I'd probably set the image to a container DIV's background image and use CSS background-size: cover to scale the image to fit, regardless of the DIV's dimensions. Actual DIV size would be controlled by media queries if I needed some specific aspect ratio change on different viewports.

The only concern, which would require some actual thinking, would be performance hit of displaying a big image on a small device. But then I'm not entirely use of the benefit of using actual 4K images in the first place.
 
Back
Top Bottom