0

(using latest version of Firefox)

I have my img written like so:

<body>
    <script>
        function imageLoaded(img) {
            console.log('the responsive image is loaded');
            img.className += ' loaded';
        }
    </script>

    <img class="backgroundImage"
         onload="imageLoaded(this)"
         src="assets/water_bg_1920.jpg"
         sizes="100vw"
         srcset="assets/water_bg_2560.jpg 2560w,
                 assets/water_bg_1920.jpg 1920w,
                 assets/water_bg_1024.jpg 1024w"/>
</body>

and my css—

@keyframes fadeIn
  0%
    opacity: 0
  100%
    opacity: 1

.backgroundImage
  opacity: 0

.loaded
  opacity: 1
  animation: fadeIn 3s

When my browser is at 960px, it loads the 1920 image. At 512px it loads the 1024 image. Anything higher and it loads the 2560 image.

I'm very confused as to exactly how it's deciding to load these images at these widths when I have sizes set to 100vw. Shouldn't it be using the 1024 image until the browser width is 1024px, the 1920 image when the browser width is from 1024px - 1920px and the 2560 img for anything higher? Am I misunderstanding something here?

edit: the behavior is also occurring in latest version of Chrome, except in addition to the original problem it's loading the 2560 image in addition to the smaller image— every time!

edit2: latest version of Safari is behaving the same as Firefox.

edit3: found a fiddle made by someone else testing. it behaves the same way (does not use the smaller image until the browser width is 50% of the image size). is this a bug? or an intended feature of srcset & sizes?

shan
  • 3,035
  • 5
  • 34
  • 50
  • Need to see the code for this function: `imageLoaded(this)` and possibly the CSS for `.backgroundImage` as well. – zer00ne Sep 28 '16 at 20:17
  • I edited the original post. Sorry, I didn't think they were relevant. – shan Sep 28 '16 at 20:20
  • No worries, I think it's the function that's probably throwing you off, let's see... – zer00ne Sep 28 '16 at 20:21
  • You are right, the JS is irrelevant. I h8 Firefox it used to be a good browser. I'm glad you figured it out. Happy coding.:) – zer00ne Sep 28 '16 at 20:35
  • No no, I didn't figure it out! The behavior is even worse in Chrome lmao. I edited my original post for more clarification. – shan Sep 28 '16 at 20:37
  • My bad, derp >.< I was going to say `sizes` does it's own math and determines which image to use. It's calculations include the device width which is different than viewport or screen-width, screen pixel density etc. Also I think the order of the images matter too so try reversing the order. – zer00ne Sep 28 '16 at 20:44

2 Answers2

0

Alright, well the solution that worked for me (which has approximately the same support with the exception of one older Safari version) is to use the <picture> tag like so:

<picture class="backgroundContainer">
    <source srcset="assets/water_bg_1024.jpg" media="(min-width: 0px) and (max-width:1024px)">
    <source srcset="assets/water_bg_1920.jpg" media="(min-width: 1025px) and (max-width: 1920px)">
    <source srcset="assets/water_bg_2560.jpg" media="(min-width: 1921px)">
    <img class="backgroundImage" onload="imageLoaded(this)" src="assets/water_bg_1920.jpg" alt="">
</picture>

Which loads all of the images correctly at the right breakpoints on all latest versions of browsers.

shan
  • 3,035
  • 5
  • 34
  • 50
0

I got to work more sanely, with a media query and a length set on the sizes. I see the img breakout to 2560w on my iPhone, but that's because of pixel-density of retina. To get the breakpoints hitting tighter, you'll need to add more media queries.

<!doctype html>
<html>

<head>
  <meta charset="utf-8">
  <title>sizes</title>
</head>

<body>
  <img src="http://placehold.it/1024x576/000/fff?text=1024w" sizes="(min-width: 36em) 33.3vw, 100vw" srcset="http://placehold.it/2560x1280/00f/fc0?text=2560w 2560w, http://placehold.it/1920x1080/e00/fcf?text=1920w 1920w, http://placehold.it/1024x576/000/fff?text=1024w 1024w" />
</body>

</html>
zer00ne
  • 41,936
  • 6
  • 41
  • 68