Screwing the srcset

As much as I wasn't convinced with how the addition of srcset was included in the spec, what a difference a day makes.

At first I was not a fan of it's appaling syntax, but after a quick email from Jeremy in the WhatWG email list I was a little more convinced.

In Fact.

Before we go any further you should really read Jeremy's fantastic post of calmness and tranquility in explaining what has happened up until this point. 

Back yet? You migh want to read Dr. Bruce's post to.

You there? Cool. Now my issue is with the current polyfill that 'showed itsself' in my timeline on the twitter this morning.

A srcset polyfill

Ok, There's quite a bit of the polyfill I don't like so let's make a start ok? Ready? Let's go.

Let's have a look at the polyfill's HTML

<img alt="" srcset="big.png 1100w, medium.png 500w, small.png 200w" style="display:none" /> <noscript>
<img src="small.png" alt="Noscript alt"></noscript>

no <img src="">

In the polyfill there is not an initial image file like there is in the spec. I don't think that's good at all, it's not very 'future friendly'. So to fix that, let's add it to the HTML. While we're at it, let's tidy it up a little too.

<img src="small.png"
  srcset="big.png 1100w, 
          medium.png 500w, 
          small.png 200w"
      alt="alt text" 
    style="display:none"
/> 
<noscript><img src="small.png" alt="Noscript alt"></noscript>

That's better, but that's not it is it?

Display: none; is utter filth

As you can see in the HTML above the polyfill has put display: inline; inline with the HTML rather than within the CSS. Let's fix that.

So first up let's remove it from the HTML

<img src="small.png"
  srcset="big.png 1100w, 
          medium.png 500w, 
          small.png 200w"
      alt="alt text"
/> 
<noscript><img src="small.png" alt="Noscript alt"></noscript>

Now we've done that, let's add it to the CSS

img { display: none; }

Nice, sorted right?

Switching around the JavaScript

At the bottom of the JS file, where the original polyfill is hacking around the <img> tag it does this -

// Remove the stupid display:none made to hide the alt-text
img.style.display = ""

As we've now put display:none; in the CSS we need to change that by simply added "block" where "" is (let's change the comment too) -

// Change the style of the <img /> element to display decided upon image
img.style.display = "block"​

This now means that the polyfill will display the <img>. Good? Well, just one more thing.

No, no, no, no, <noscript>

At the end of the polyfill HTML code is the <noscript> tag with the small images so there's a fallback for browsers that don't have JavaScript enabled. Because we've added display: none; to the <img> elements in CSS, the <noscript> <img>'s will be 'hidden' too. So we need to change that in the CSS, like this -

noscript img { display: inline; } 

Excellent, that's great, isn't it? We fixed the internet right?

Ta-Da!

So. Here's all the code for the polyfill that I've edited to this state.

But, Two images?

Unfortunately because how browsers work this polyfill has the bastard audacity to download two images when all we need is one. This is because of our using of display:none; and calling an image at first then, with Javascript, calling the 'appropriate' image. That's an extra http request that could be costly and also some more page weight that could be detrimental. For the short term, that's something that could be ok though right?

Well, not really...

That's about as far as my 'knowledge and understanding' can probably take it. I'm sure it can be improved upon, refactored, edited, fucked with and corrected. I do feel it's a little bit 'cleaner and meaner' than the original polyfill I've edited.