0

I've come across this multiple times now and always solved it with a combination of CSS and JS, but with increasing support for responsive images, I've been searching for a more eloquent solution. I'm simply trying to not load an image on mobile, while retaining semantics (so no CSS background-image), taking advantage of browser pre-loading (so no JS lazy loading).

How can I accomplish this?

Marcus McLean
  • 1,306
  • 2
  • 13
  • 24

1 Answers1

0

tl;dr

Use the srcset attribute with an image candidate string that has a URL of about:blank and a width descriptor of 1w and set the sizes attribute's fallback <source-size-value> to 0vw. Then, add CSS rules to hide the image for smaller viewports. Finally, wrap it in a <picture> with <source>s for absolute control.


srcset

It appears to me that this can be solved using responsive images and a bit of CSS.

Consider the following responsive image:

<img
    src="foo-585.png"
    alt="foo"
    srcset="foo-375.png 375w, foo-585.png 585w"
    sizes="(min-width: 1200px) 585px, (min-width: 768px) 375px"
>

Despite there being no fallback <source-size-value> in sizes, foo-375.png is still loaded. So it appears we need to find an image candidate string that doesn't send any additional HTTP requests.

I searched SO for tips on how to essentially set a null image candidate string. I found several methods, all of which can be implemented like so:

<img
    src="foo-585.png"
    alt="foo"
    srcset="[URL] 1w foo-375.png 375w, foo-585.png 585w"
    sizes="(min-width: 1200px) 585px, (min-width: 768px) 375px, 0vw"
>

Note that a new image candidate string with a width descriptor of 1w and a fallback <source-size-value> of 0vw are added. In this example, [URL] is a placeholder for one of the URLs described below:

Empty Fragment

One answer advises using an empty fragment (#) as a valid option. Unfortunately, my tests indicate this method repeatedly sends HTTP requests to the current URL. Not good.

Tiny Data URL

Another answer recommends using The Tiniest GIF Ever in a Base64-encoded data URL:

data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=

Initially, I thought that at 58 bytes with very little opportunity for gzip compression on its own, it stands to reason that saving the GIF as an external resource with a shorter URL might be more efficient than multiple data URLs, but I was wrong; gzip eats multiple instances of this data URL for breakfast.

But, as one comment points out, data URLs are slow on mobile.

No Scheme, No Host, Port 0

Yet another answer suggests using a URL with no scheme, no host, and port 0 (//:0). This appears to work, but there are concerns about firewall warnings. CSS is also required to hide the broken image styling.

about:blank

That same commenter suggested using about:blank, which actually seems to work well enough, but like the last method, does require CSS to hide the broken image styling:

img {
    display: none;
}

@media (min-width: 768px) {
    img {
        display: inline-block;
    }
}

To me, this seems like the best option, as it is valid, efficient, and will not display any user-facing warnings. Those few lines of CSS seem well-worthwhile to me.

<picture>

As the comments have pointed out, srcset isn't guaranteed. If the browser for some reason decides against your about:blank image candidate, then the solution falls apart. To remedy this, wrap your <img> in <picture> element and add the relevant <source>s:

<picture>
    <source
        media="(min-width: 768px)"
        srcset="[URL] 1w foo-375.png 375w, foo-585.png 585w"
    >
    <source srcset="about:blank">
    <img
        src="foo-585.png"
        alt="foo"
        srcset="[URL] 1w foo-375.png 375w, foo-585.png 585w"
        sizes="(min-width: 1200px) 585px, (min-width: 768px) 375px, 0vw"
    >
</picture>
Community
  • 1
  • 1
Marcus McLean
  • 1,306
  • 2
  • 13
  • 24
  • You can not solve this with one `srcset`, you will need to use `picture`: http://stackoverflow.com/questions/26574422/how-do-i-tell-srcset-attribute-to-load-no-images-when-viewport-smaller-than-cert – alexander farkas Apr 25 '16 at 17:32
  • @alexanderfarkas While my method does not explicitly prohibit a browser from loading any source for a specific media query, it assumes the browser will select the `about:blank` candidate for that media query. Are you suggesting there are browsers which would not honor my combination of `srcset` and `sizes` (i.e. select a candidate other than `about:blank`)? – Marcus McLean Apr 25 '16 at 17:47