Lazy Load Responsive Images using LazySizes JS

The code below lazy loads responsive images using lazysizes, a native javascript framework that loads images upon visibility in the viewport. You can see a demo on my art and photography site, Pacific Modern Art, which is built with Jekyll.

To begin, I create a YAML data file as shown below which is built from a directory of images that were rendered automatically using gulp-responsive. You'll see that I have both JPG and WEBP image formats and and HTML is such that devices and browsers that understand WEbP will use that format but a fallback to JPG is used just in case, for example with Firefox.


- title: Motel Trail's End
  category: retro-signs
  img_xl: motel-trails-end-1200px.jpg
  img_lg: motel-trails-end-960px.jpg
  img_med: motel-trails-end-640px.jpg
  img_thumb: motel-trails-end-480px.jpg
  img_xl_webp: motel-trails-end-1200px.webp
  img_lg_webp: motel-trails-end-960px.webp
  img_med_webp: motel-trails-end-640px.webp
  img_thumb_webp: motel-trails-end-480px.webp
  orientation: portrait

- title: El Rancho Motel
  category: retro-signs
  img_xl: el-rancho-motel-1200px.jpg
  img_lg: el-rancho-motel-960px.jpg
  img_med: el-rancho-motel-640px.jpg
  img_thumb: el-rancho-motel-480px.jpg
  img_xl_webp: el-rancho-motel-1200px.webp
  img_lg_webp: el-rancho-motel-960px.webp
  img_med_webp: el-rancho-motel-640px.webp
  img_thumb_webp: el-rancho-motel-480px.webp
  orientation: landscape


The index page which calls the loop using BEM

Note the line, for art in which calls the YAML in the works data file in the site's _data directory.

<main id="content" class="content " role="main">
  <div class="grid grid__col--2s grid__col--3m grid__col--4l">
    <div class="grid__sizer"></div>
    {%- for art in -%}
    {%- if art.code_categories == "retro-signs" -%}
    {%- include works_loop.html -%}
    {%- endif -%}
    {%- endfor -%}

The Responsive Image Loop

We use a responsive image setup here using the <picture> and srcset tags so as to create the JPG fallback. We also draw heavily upon the HTML5 data attribute for both lazysizes and the responsive light-box which also has responsive images.

<div class="grid__item grid__item--{{ art.orientation }} lazyload" data-lazyload-children=".grid__img">
  <a data-fancybox="{{ art.category }}"
     data-srcset="/media/{{ art.category }}/{{ art.img_xl }} 1200w,
       /media/{{ art.category }}/{{ art.img_lg }} 960w,
       /media/{{ art.category }}/{{ art.img_med }} 640w,
       /media/{{ art.category }}/{{ art.img_thumb }} 310w"
     href="/media/{{ art.category }}/{{ art.img_lg }}"
     data-caption="{{ art.title }}">

      <source data-srcset ="/media/{{ art.category }}/{{ art.img_lg_webp }} 960w,
                /media/{{ art.category }}/{{ art.img_med_webp}} 760w,
                /media/{{ art.category }}/{{ art.img_thumb_webp }} 310w"

      <img data-sizes="auto" class="grid__img lazyload no-src"
           data-src="/media/{{ art.category }}/{{ art.img_med }}"
           data-srcset="/media/{{ art.category }}/{{ art.img_lg }} 960w,
             /media/{{ art.category }}/{{ art.img_med }} 760w,
             /media/{{ art.category }}/{{ art.img_thumb }} 310w"
           data-title="{{ art.title }}"/>