3
votes

I'm trying to implement the new srcset attribute for <img> and I've run into some edge cases that are not working or I'm missing something.

I'm using the picturefill 2.1.0 polyfill, and I've read some articles like http://ericportis.com/posts/2014/srcset-sizes/ or https://html.spec.whatwg.org/multipage/embedded-content.html#embedded-content.

I get the idea of very simple examples, e.g:

<img
    src="small.jpg"
    srcset="
        small.jpg  100w,
        medium.jpg 200w,
        large.jpg  300w
    "
    sizes="100vw"
>

The browser loads small.jpg, medium.jpg or large.jpg depending on screen size, pixel density, zoom and other factors. It may load medium.jpg for a 200px simple screen or a 100px hdpi(2x) display. So far so good.

The problem relies on the sizes attribute. In the previous example we are telling the browser that the picture takes up the whole (100%) viewpoint width (vw).

The project I'm working in uses Foundation, which has fluid, em-padded grids that may have more or less columns based on screen sizes (media queries).

Let's say, for instance, that we want a grid in which small screens have 2 columns, and medium screens (min-width: 40em) 4 columns. Every column contains an image. What would be the correct sizes keeping in mind that each column is width-fluid and has a padding defined in ems?

<ul class="small-block-grid-2 medium-block-grid-4">
    <li>
        <img
            src="small.jpg"
            srcset="
                small.jpg  160w,
                medium.jpg 320w,
                large.jpg  480w
            "
        >
    </li>
</ul>
  1. sizes="(min-width: 40em) 25vw, 50vw"
  2. sizes="(min-width: 40em) ???em, ???em"
  3. sizes="(min-width: 40em) ???px, ???px"

The vw approach ignores the padding of the columns. The em or px approach ignores the fact that columns are fluid (and I'm not even sure which values should they have).

Any ideas?

Thanks in advance.

1
use calc: i.e: calc(25vw - 4em)alexander farkas
@alexanderfarkas Thanks! It seems to work fine. Do you know if ems are relative to root font-size or img's container font-size?Petit Saltamartí
@alexanderfarkas One more doubt: Do you know if the sizes attribute is only used while pre-loading images? I mean, if I say that an <img> is 100vw, but for some reason I'm wrong, or the page changes via JS, or whatever, and the image becomes 50vw, the browser will be smart enough to ignore my 100vw declaration and pick up the correct file?Petit Saltamartí
No, you need to add the correct sizes attribute. This is mandatory. In case the page changes via js you need to change the sizes accordingly. In case you are using JS it is quite simply, because then you can simply add a simple 'px' value.alexander farkas
The em is always using the default font-size (i.e. same as media queries), which means it's mostly 16px. It doesn't take into account any CSS changes by the author. In case you are struggling to generate the right sizes attribute. Maybe the following lazyLoader, which I created might help: github.com/aFarkas/lazysizes. Here an example markup: github.com/aFarkas/lazysizes#recommended-markup-lqip and here a demo: afarkas.github.io/lazysizes/#examplesalexander farkas

1 Answers

2
votes

Well Foundation doesn't work like that, for the moment they are use javascript data-interchange to deal with the new attr srcset:

<img 
     data-interchange="[/path/to/default.jpg, (default)], 
     [/path/to/small.jpg, (small)], 
     [/path/to/retina.jpg, (retina)], 
     [/path/to/medium.jpg, (medium)], 
     [/path/to/bigger-image.jpg, (large)]"
>

<!-- or your own queries -->
<img 
     data-interchange="[/path/to/default.jpg, (only screen and (min-width: 1px))], 
     [/path/to/bigger-image.jpg, (only screen and (min-width: 1280px))]"
>

Using Interchange With Images

data-interchange="[image_path, (media query)], [image_path, (media query)]"

Using Retina Images

data-interchange="[image/path/to/retina.jpg, (retina)]"

Custom Named Queries

$(document).foundation('interchange', {
  named_queries : {
    my_custom_query : 'only screen and (max-width: 200px)'
  }
});

In your case you could just make new custom Named Queries and pass it to your Img.