dannysmith / dannyis-jekyll

0 stars 0 forks source link

Responsive, lazy-loaded Images in articles #40

Closed dannysmith closed 4 years ago

dannysmith commented 4 years ago

It would be good to have a build-time plugin that does the following:

  1. Finds all images in markdown.
  2. For large images, generates smaller versions with the same aspect ratio in the build folder and inserts an appropriate srcset attribute into the image tag so the lowe-res versions are used in smaller containers.
  3. Optimises all versions.
  4. Adds explicit dimensions to the image tag, based on the original image size.
  5. Adds a native lazy loading attribute.

This eleventy plugin does steps 4 and 5, as well as adding a data encoded low-res version and some javascript to swap it out when the user scrolls near to it.

This one does the rest.

See this video for more https://www.youtube.com/watch?v=4-d_SoCHeWE

dannysmith commented 4 years ago

This can all be achieved using the eleventy-plugin-local-respimg plugin alone, though it will also convert images to webp and insert them in a picture element too.

const pluginLocalRespimg = require('eleventy-plugin-local-respimg')

module.exports = function (eleventyConfig) {
  eleventyConfig.addPlugin(pluginLocalRespimg, {
    folders: {
      output: '_site', // Build directory
    },
    images: {
      resize: {
        min: 250, // Minimum width to resize an image to
        max: 1500, // Maximum width to resize an image to
        step: 150, // Width difference between each resized image
      },
      sizes: '100vw', // Default image `sizes` attribute
      lazy: true, // Include `loading="lazy"` attribute for images
    },
  })
});

Example output from ![About](/uploads/2020-07-02-screenshot.png).

<picture>
  <source
    srcset="/uploads/2020-07-02-screenshot.250.webp 250w,
            /uploads/2020-07-02-screenshot.400.webp 400w,
            /uploads/2020-07-02-screenshot.550.webp 550w,
            /uploads/2020-07-02-screenshot.700.webp 700w,
            /uploads/2020-07-02-screenshot.850.webp 850w,
            /uploads/2020-07-02-screenshot.1000.webp 1000w,
            /uploads/2020-07-02-screenshot.1150.webp 1150w,
            /uploads/2020-07-02-screenshot.1300.webp 1300w,
            /uploads/2020-07-02-screenshot.1450.webp 1450w,
            /uploads/2020-07-02-screenshot.1500.webp 1500w"
    sizes="100vw" type="image/webp">
  <source
    srcset="/uploads/2020-07-02-screenshot.250.png 250w,
            /uploads/2020-07-02-screenshot.400.png 400w,
            /uploads/2020-07-02-screenshot.550.png 550w,
            /uploads/2020-07-02-screenshot.700.png 700w,
            /uploads/2020-07-02-screenshot.850.png 850w,
            /uploads/2020-07-02-screenshot.1000.png 1000w,
            /uploads/2020-07-02-screenshot.1150.png 1150w,
            /uploads/2020-07-02-screenshot.1300.png 1300w,
            /uploads/2020-07-02-screenshot.1450.png 1450w,
            /uploads/2020-07-02-screenshot.1500.png 1500w"
    sizes="100vw" type="image/png">
  <img src="/uploads/2020-07-02-screenshot.png" alt="About" height="937.5000000000001" width="1500" loading="lazy">
</picture>

This will not create large versions of small images.

dannysmith commented 4 years ago

This was implemented in Jekyll here: https://github.com/dannysmith/dannyis-jekyll/commit/af108896bb78d7d048b3f6aa3fb178dda66d31b7

Thanks to this article