ImageSet — Responsive images with lazy-loading and beautiful placeholders

plugin

#1

I finally released the first public version of ImageSet! :tada: This is just an early alpha release, so there might still be glitches in some browsers.

It took me some time to figure out how to design a convenient API for template developers, thinking about fallbacks and different placeholder styles. But the plugin is already on a good path to the first stable release, so I decided to release it today, giving it a chance to be discussed and tested by the Kirby community.

I’m happy to hear your feedback. :slight_smile:


Features

  • Responsive Images Add responsive images in different sizes to your website with ease by using ImageSet’s convenient template API.
  • Easy to Use ImageSet provides a convenient API for generating responsive image sets and also works with Kirbytext.
  • Lazy Loading It supports lazy loading for saving valuable bandwidth (especially on mobile) and faster page loads for everyone.*
  • Placeholders & Ratios ImageSet comes with placeholders in 4 beautiful styles and reserves screen space for images to avoid reflows (aka page-jumps) while the page is being loaded.
  • Art Direction Define different sizes and crop ratios for different screen sizes and/or media types.
  • Progressive Enhancement In case of doubt, the plugin works without JavaScript or native support for responsive images as a conditionally loaded polyfill is included for older browsers.
  • Web Standards ImageSet produces HTML5-based markup (using the <picture> element and srcset-attribute).
  • Works with AJAX ImageSet works with dynamic content, as new imagesets are automatically detected and handled.
  • Small Footprint Frontend code has been designed for performance and comes with a minimal footprint. Only 0,6 kB CSS + 4,8 kB JavaScript + 5,7 kB Polyfill for older browsers (minified & gzipped).

*) Lazy loading uses the very performant lazysizes script and requires JavaScript to be activated on the client. However, the plugin provides a <noscript>-fallback which is enabled by default.



#2

Great idea, looks awesome. :+1:
It feels indeed a bit scientific to implement images the right way these days.

Speaking of the license model, I would love to buy an all in one license together with Kirby. Just to save a bit time buying different licenses. Or something like a PRO Modules License in the Kirby shop, like the people from Processwire CMS are handling this.


#3

Yeah … I also rolled my eyes when I tried to implement responsive images in my first project (and sometimes I still do). I simply don’t want to create websites, that download a giant Full-HD hero image, when the viewport is just 400 pixels wide. I would consider this to be bad engineering. But on the other hand, even with the picture element finally arriving in more and more browsers, creating the corresponding markup does not really ease the pain. For example: the spec requires you to specify the sizes attribute whenever you use width descriptors in the srcset attribute. Well yes … prefetching and stuff. But honestly, why? Would it really that bad if the browser had to wait a few milliseconds before stylesheets are rendered and dimensions of images are known by the browser? Seems like the people behind the spec don’t think so … this might make sense for large-scale websites with large budgets. But how should a beginner be able to provide a good sizes attribute like "(min-width: 45em) calc((100vw - 3em) * 0.5 - 1.5em), calc(100vw - 3em)"?

This really caused me headaches in complex grid layouts, so I decided to use lazysizes to handle that for good (it automatically calculates the sizes attribute). When I started to experiment with lazy-loading and pllaceholders about 3 years ago, I was constantly shaking my head and I wish there would be a simpler solution, but let’s face it: even if intrinsic ratios would be supported in CSS natively, we still had the burden of calculating and processing different sizes of our images until there was a progressive image format, capable of doing this automatically. I thought, the best option to make “high-end” responsive images as seen on sites like Medium.com available for smaller projects as well would be to bundle all the functionality in a portable, standalone image component that can be used in most cases and is maintained and updated separately from client projects. This way, the component can improve by adapting to new requirements and browsers and keeps the actual image markup separate from the other frontend code of websites.

I can fully understand your pain-points here. I fear, this is currently something that is currently not possible. ImageKit & ImageSet are my own business that is not related to Kirby sales. However, ImageKit & ImageSet will be available as a bundle at a discounted price. Everyone, who bought ImageKit before ImageSet licenses are available for sale, will be able to upgrade once ImageSet reaches 1.0.0 final.


#4

Thanks a lot for your detailed answer, very appreciated.
And I’m 100% with you talking about the complex situation of srcsets, bandwidth, hires-displays, aspect ratio and all that stuff. It’s crazy.
Perfect time for your well designed plugin.

A bundled license of your plugins sounds great.

And off topic:
A good overview about all active developed plugins in general would be great. The plugins-website only seems to cover a few, hope I haven’t overlooked something here.
The packages archive of ATOM text editor for example pulls all data from Github, which seems to be a good way. https://atom.io/packages


#5

I think with »plugins website«, you mean getkirby-plugins.com? It’s not an official website, but you’re right as it does only show a small portion of the currently available plugins. You can however find another (inofficial) list, initiated by @jenstornell on GitHub. It is more up-to-date and includes several hundreds of plugins.


#6

big thumbs up for the detailed documentation provided via github. As someone who published some projects myself I know how tedious it can be to really break it down into clear and easy to understand text.


#7

I just released a new version of ImageSet (1.0.0-beta1) with lots of improvements and fixes. Get it from GitHub: https://github.com/fabianmichael/kirby-imageset


Changelog:

  • Improved JavaScript Code: Switched from SVG filters to canvas for better-looking blur effect and better cross-browser compatibility. Also seems to offer better scrolling-performance.
  • SVG support: ImageSet will not crash any more, if source image is an SVG file but instead print a basic ImageSet without placeholder.
  • XHTML-compatible Output can now be configured using the output.xhtml setting.
  • Transparency: Placeholders now work properly with images, that have alpha transparency.
  • Readability: imageset.php snippet is way more readable now.

#8

does imageset work with my custom thumbs driver? i am using imagekit as well, which does support the thumbs driver.

// config.php
c::set('thumbs.driver', 'mydriver');
c::set('imagekit.driver', 'mydriver');

#9

The only problem I am currently seeing here is, that the functions that check for transparency of the dominant color might interfere with it. In case of doubt, just try out if it works. The dominant color is only calculated, if you use the color placeholder type, transparency will only be checked, whenever you your source image is a PNG or GIF file as JPEGs cannot contain an alpha channel.

These two calculations have to be done on the server, where your Kirby install is running and the selection of you thumbnail backend determines whether they use GD or ImageMagick. In case of doubt, you could just override the built-in driver by naming your own driver gd. This way, ImageSet thinks that it’s fine to use the GD library for the transparency check. The dominant color is always using GD or the Imagick component of PHP.


#10

it works fine now. not sure what i changed. prefixing the plugin folder with a-. so it gets loaded before imagekit/set – maybe?

also being on localhost my custom driver is very slow since it need to upload a few MB for each image. imageskits build-in support for optimizer binaries seems more and more promising. :wink:


#11

i have a question about retina images with imageset. i did read up on srcset, sizes and retina a little bit.

all srcset and data-srcset values are defined with w (file width). with the default config of imageset (using the lazy option and thus lazysizes.js) the sizes attribute of the img element is set automatically. does that mean browser will pick the retina image itself?


#12

Yes, because the pixel-based value set automatically will still be multiplied with the devicePixelRation value of the browser internally, when it picks one of the image candidates defined in srcset. You just have to generate images with sufficient dimensions. E.g. if one of you images has a maximum width of 640 px on a »regular« scren (1x), a HiDPI/retina device like a newer MacBook Pro model, which has a pixel ratio of 2 doubles all px-based values internally. That means, you’re writing you code like for every other screen when setting stuff like borders, padding etc. Images however need to be served in a higher resolution to look really crisp. So your image should have a thumb at a width of 1280 px in this case:

echo $image->imageset('640,1280');

#13

thank you @fabianmichael. your explanation was very helpful.


#14

ImageSet 1.0.0-beta2 FTW! :v:

I just uploaded a new version to GitHub, feel free to play with it, as the final release is not too far away anymore. And there is a new filter for placeholder images called triangles! I’ also working on great new features for ImageKit. Also, have a nice weekend :wink:


Changes from beta1:

  • Caching ImageSets are now cached, so existance checks on load can be skipped after the first page load, resulting in major speed bumps. Can be disabled in options.
  • Improved Transparency Detection now also works for 8-bit palette GIF or PNG images.
  • Better Image IDs Some ImageSet require custom CSS rules and thus need a unique ID to target them. IDs now have more entropy and are less likely to collide.
  • New placeholder style Triangle mosaic, uses canvas-based rendering.
  • Updated embed code Offers better performance on page load by executing some JavaScript earlier.
  • Plus Several bugfixes and minor improvements.

#15

How can i combine photoswipe with kirby-imageset? Is there a solution?


#16

Hey @mthiebou,

PhotoSwipe is currently not supported out-of-the-box. But you could either modify make a copy of snippets/imageset.php` to add the attributes you need or extract the image dimensions (whose PhotoSwipe needs) from the thumb filenames.

Support for Photoswipe is already on my list, but it will probably have to wait until 1.1 is released.


#17

Great that support for Photoswipe is on your list for Imageset! No problem, i will wait untill 1.1 arrives.


#18

+1 for Photoswipe Support. Would even pay a Addon Fee for it.


#19

Please make it optional, I don’t need Photoswipe in every project :wink:


#20

What about responsive background images? You are already using the lazysizes script, so it would be easy to add (optionally) the lazysizes bgset extension.

Beside adding the bgset extension script, I need imageset to output the following code:

<div class="lazyload" data-bgset="image-300.jpg 300w, image-400.jpg 600w, image-1200.jpg 1200w" data-sizes="auto"></div>
<noscript>
     <div style="background-image:url(image-1200.jpg);"></div>
</noscript>

Maybe you can add a third bgimage output option besides the auto and plain options that are already there to generate the responsive background images markup in the template?

Do you already have this on your list and/or could you lead the way in how to do add this without breaking it with future imageset updates?