Giter Club home page Giter Club logo

kirby-imageset's Introduction

ImageSet

GitHub release License Kirby Version

A flexible, responsive image component for Kirby CMS, featuring lazy loading, fancy placeholders and more.

NOTE: This plugin was realeased under a commercial license at first. As of October 2nd, 2019, the code has been re-issued under the MIT license. As I have stopped sales and development, please note that I do not offer support any longer. If you want to use this plugin with a legacy Kirby 2-website, just use this license key to get rid of any limitations of the trial version: IMGST1-00000000000000000000000000000000.


Table of Contents


1 Key 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 imagesets from within your templates and it 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 5 beautiful styles and reserves screen space for images before they are loaded 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 any other media query conditions.
  • 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 image sets are automatically detected and handled.
  • Error Handling When an image could not be loaded (e.g. due to a connection error), the plugin will display a broken image icon and alt text if supplied.
  • Small Footprint Frontend code has been designed for performance and comes with a minimal footprint. Less than ~2 kB CSS + ~8 kB JavaScript (+ ~6 kB Polyfill for older browsers), when 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 Download and Installation

2.1 Requirements

2.1.1 Server Requirements

  • PHP 5.6.0+
  • Kirby 2.3.0+ (not compatible with Kirby 3)
  • GD Library for PHP or ImageMagick command-line tools to resize images.
  • ImageKit for Kirby CMS 1.1.0+ (optional, but recommended for pages containing lots of image sets and/or image sizes)

2.1.2 Browser Support

ImageSet has been tested in the following browsers, but should work with any browser that supports modern web standards:

IE Edge Firefox Safari (OS X) Safari (iOS) Chrome Opera Opera mini
11+ ✓* 9+ 9+ ✓**

*) Includes Firefox ESR

**) Does not work with dynamic content (e.g. widgets loaded via XHR/AJAX) due to the limited JavaScript support in Opera mini.

2.1.3 Recommended Content Workflow

ImageSet works best with high-resolution source images, so they can be scaled according to your needs. This way, your content will also be more future-proof as in a couple of years, new devices might demand for images with even higher resolution. This also ensures an easier transition if new image formats like WebP become more popular. Make sure, that your server can handle scaling of thus large image files, though. If you use the GD library (Kirby’s default setting), also make sure that your server provides enough RAM to PHP, so large-sized images can be processed.

2.2 Plugin Installation

2.2.1 Kirby CLI

If you’re using the Kirby CLI, you need to cd to the root directory of your Kirby installation and run the following command:

kirby plugin:install fabianmichael/kirby-imageset

This will download and copy ImageSet into site/plugins/imageset.

2.2.2 Git Submodule

To install this plugin as a git submodule, execute the following command from the root of your Kirby project:

git submodule add https://github.com/fabianmichael/kirby-imageset.git site/plugins/imageset

2.2.3 Copy and Paste

  1. Download the contents of this repository as ZIP-file.
  2. Rename the extracted folder to imageset and copy it into the site/plugins/ directory in your Kirby project.

2.3 Template Setup

In order to make ImageSet work properly, you have to include the corresponding CSS and JavaScript files to your templates. Add the following lines to your header snippet:

<!-- replaces "no-js" class on html element with "js" -->
<script>(function(d,c,r){d[c]=r.test(d[c])?d[c].replace(r,'$1js$2'):[d[c],'js'].join(' ')})(document.documentElement,'className',/(?:(^|\s)no-js(\s|$))/)</script>

<?= css('assets/plugins/imageset/css/imageset.min.css') ?>

If you use lazy loading, also add the following line anywhere after the previous code in your template, it is recommended to include the file before the closing </head> tag to ensure that it loads as fast as possible. If this is not possible, you can also include the script right before the closing body tag, but this leads to later execution and can easily result in the flashing of un-rendered placeholders.

<?= js('assets/plugins/imageset/js/dist/imageset.min.js') ?>

Not all browsers are providing native support for the <picture> element. If your site does not already include a polyfill for this, you might also want to add the following lines within the <head> of your site to load the respimage polyfill conditionally and as fast as possible.

<script>
(function(w, d){
  function loadJS(u){var r = d.getElementsByTagName("script")[0], s = d.createElement("script");s.src = u;r.parentNode.insertBefore( s, r );}
  if(!window.HTMLPictureElement){
    d.createElement('picture');
    loadJS("<?= url('assets/plugins/imageset/js/dist/respimage.min.js') ?>");
  }
})(window, document);
</script>

Alright, your site should now be prepared for using ImageSet! :-D

ℹ️ For a dev environment or low-traffic sites, it is completely fine to link plugin assets directly. However, if performance is critical for your project, it is highly recommended to place a copy of the JS and CSS files linked above in your assets directory and link to them or to bundle up these assets with your regular CSS and JavaScript using the build tool of your choice.

3 Global Configuration

The settings listed below are meant to be defined in your config.php and change the global behavior of the plugin. To learn about configuring the default behavior of image sets in your templates (lazy loading, placeholders, fallback behavior etc.), have a look at 4.3.1 Available Options.

Option Default value Possible values Description
imageset.license '' Enter your license code here, once your site goes live.
See the License section of this document for more information.
imageset.styles.consolidate false true, false If you use image sets with multiple aspect-ratios, the plugin needs an inline <style> element for each of those. This is common practice in web design and works in every browser, but throws a validation error as this is not officially part of the HTML5 spec. Enabling this setting will consolidate all inline style decorations and move them to head <head> of your document.

⚠️ You should only enable this feature, if passing the validator is really important for your project and if you don’t use AJAX to load markup containing image sets dynamically.
imageset.tags.image true true, false If enabled, ImageSet will replace Kirby’s built-in image Kirbytag with one that will generate image sets instead of plain image tags.
imageset.tags.image.sizes.default '' any defined preset name Set the default size of image sets generated via the image Kirbytag. If this option is set, ImageSet will always generate image sets whenever the image Kirbytag is used, and no size parameter was given.
imageset.tags.image.class 'size-{size}' Added to the class attribute of every image set generated by the image Kirbytag.
{size} will be replaced by the name of the corresponding preset.

4 Usage

4.1 Template API

ImageSet offers a convenient API for including image sets into your Template-Code. Just use the global imageset() function in your templates:

The imageset() function

imageset(Media $image, mixed $sizes = 'default', array $options = null)

Parameters:

$image
The source image used to generate all resized versions. Must be an instance of the Media or File objects.
$sizes
Describes the image sizes, which should be generated. Must be a size descriptor or a preset. If no sizes are given, the function will check for a sizes preset called 'default' and uses it, if defined.
4.2 Describing Sizes
$options
An associative array of options, letting you override default settings and adjust things like placeholder style, fallback behavior etc.
4.3 Setting Options

Working with File objects:

Whenever your source image is inside Kirby's content folder, you should use Kirby’s API to retrieve the image as a File object, so you can use the imageset() method. In this case, you don’t have to specify the $image parameter:

if($image = $page->image('sample.jpg')) {
  echo $image->imageset('200,400,600');
}

Styling Image Sets

The markup generated by the plugin is wrapped in a <span> tag which has the class imageset and additional classes depending on your options. By default, image sets always span the full width of their parent container. You can override this behavior by either wrapping them with another container element that has a constrained width or by using something like .text .imageset { width: 50% ; } in your CSS.

Image sets also have have display: inline-block on their container element by default to make them behave similar to regular <img> tag with all its upsides and downsides. You can safely override this by adding .imageset.-ratio { display: block; } somewhere to your stylesheet after imageset.scss was included, if you would like image sets to behave like block elements.

4.2 Describing Sizes

4.2.1 Single Aspect-Ratio

As thumbnail sizes are usually defined by their width, ImageSet provides a convenient syntax for this.

List of widths

echo $image->imageset('200,400,600');
echo $image->imageset([200, 400, 600]);

This will generate 3 thumbnails with a width of 200, 400 and 600 pixels. You can provide the sizes either as array or as string of comma-separated values. For better readability, you may also add a space after each comma.

Range between widths

echo $image->imageset('200-600');

When you specifiy a range, ImageSet will calculate the intermediate sizes automatically. By default, the plugin will generate 2 intermediate sizes, so the example above will create a total of 4 thumbnails at widths of 200, 333, 467 and 600 pixels.

echo $image->imageset('200-600,3');

If you need more than 2 intermediate sizes, you can optionally tell the function, how many intermediate sizes it should calculate. The example above will create a total of 5 thumbnails at widths of 200, 300, 400, 500 and 600 pixel

List of cropped sizes

echo $image->imageset('400x200,800x400');

You can also describe explicit width and height parameters for images to create cropped thumbnails.

ℹ️ All images described in one size must have the same aspect-ratio. If you want to serve differently cropped images based on viewport-size, continue reading for more detailed information on more complex usage scenarios.

Range between cropped sizes

echo $image->imageset('400x200-800x400');   // (1)
echo $image->imageset('400x200-800x400,5'); // (2)

You can also provide a range between the smallest and the largest cropped thumbnail you need (1) and tell the plugin how many intermediate sizes it should generate (2).

The examples above should be enough for most scenarios. If your layout does not require different crop ratios for differently-sized viewports, you can safely continue at 4.3 Setting Options. 😌

4.2.2 Multiple Aspect-Ratios

Some scenarios require your images to be cropped in different aspect-ratios for different viewports.

Take the full-width hero image of a blog example for example; If a screen is much wider than tall, a hero image in 16:9 format might be a good choice, but on other screens — like a smartphone held upright, showing a square image might be the better option. The examples below demonstrates that:

<?= imageset($page->image('marina.jpg'), [
  [ '320x180-1920x1080,5', 'media' => '(min-aspect-ratio: 3/2)' ],
  [ '320x320-1000x1000,5' ],
]); ?>

The example will create an image set with 2 different aspect-ratios, based on the viewport’s aspect-ratio. The first size in 16:9 format is only shown when the viewport has an aspect-ratio of at least 3:2. On taller viewports, a square version of the image is shown instead.

4.2.3 Using the sizes Attribute

The HTML spec requires you to specify the sizes attribute for every <source> or <img> element with a srcset, that uses width descriptors. Otherwise, the HTML code does not pass the validator.

By default, ImageSet will add sizes="100vw" to your images to make your markup valid. As long as you use lazy loading (enabled by default), the plugin will automatically calculate the size based on the current width of each image set. If you disable lazy loading or a lot of your visitors use plugins like NoScript, you should pass a valid sizes descriptor to avoid the download of larger image files than needed.

<?= $image->imageset([ '160-1280,6', 'sizes' => '(min-width: 640px) 100vw, 50vw' ]) ?>

Further Reading:

4.3 Setting Options

The options described in this section define the behavior of a single image set and can be passed as additional parameter when calling the imageset() function in your templates:

<?= $image->imageset([
    '160-1280,6', 'sizes' => '(min-width: 640px) 100vw, 50vw'
  ], [
    'class'       => 'awesome-image',
    'placeholder' => 'blurred',
  ]) ?>

You can also define default values for all options by setting them in your config.php file with a prefix of imageset.[option name]:

c::set('imageset.placeholder', 'color');
c::set('imageset.noscript', false);

4.3.1 Available Options

Option Default value Possible values Description
class '' Additional classes added to the wrapper tag of the image set.
alt '' any string Sets the alternative text for this image set.
ratio true true, false Adds a ratio-placeholder/intrinsic size to the image set. This reserves space for the images while the page is loading and avoids reflows (aka “page-jumps”). This option is ignored, if placeholder has any other value than false or lazyload is enabled and always behaves like it had a value of true in these cases.
placeholder 'mosaic' false, 'triangles'*, 'mosaic', 'blurred', 'lqip', 'color' Sets the visual style of the placeholder shown while the main image is being loaded. Set to false if you don’t want to use a placeholder at all. Have a look at the Demo page to preview all available placeholder styles. *) May not render correctly in IE 10/11.
lazyload true true, false Enables lazy loading of image sets.
Remember to include the corresponding JavaScript file into your markup as described in 2.3 Template Setup.
noscript true true, false Includes a fallback for clients without JavaScript support or disabled JavaScript.
output 'auto' 'auto', 'plain' 'auto' = Image set will produce full-featured HTML according to your options.
'plain' = HTML output will be plain HTML without any classes, placeholders etc. img and source tags are also rendered in XHTML-compatible syntax.
output.xhtml false true, false When enabled, ImageSet will generate XHTML/XML-compatible markup for all image sets. This means that a trailing slash is added to void elements and a different handling of special chars.
cache true true, false When enabled, the HTML output of image sets is always cached, resulting for major speed improvements.

4.4 Working with Size Presets

4.4.1 Defining Presets

Your project probably has a lot of re-occuring image sizes. You can configure a set of default presets in your config.php to use them in your templates:

# site/config/config.php
c::set('imageset.presets', [
  'default' => [
    [ '300-1500,7' ],
  ],
  'hero'    => [
    [ '320x180-1920x1080,5', 'media' => '(min-aspect-ratio: 3/2)' ],
    [ '320x320-1000x1000,5' ],
  ],
  'small'   => [
    [ '200,300,600,800' ]
  ],
]);
<?php if($hero = $page->hero()->toFile()): ?>
<div class="hero">
  <?= $hero->imageset('hero') ?>
</div>
<?php endif ?>

4.4.2 Dynamic Presets API

In more complex scenarios, you might want to use different size presets depending on the current template, snippet or content area. Maybe your project uses Kirbytext in differently sized columns and you don’t want to use size names like “sidebar-small” in your Kirbytext markup. In these cases, you should have a look ate the dynamic presets API:

imageset::presets([ 'default' => … , 'small' => … ])
Defines new Presets. Extending presets will be overridden if a name preset of the same name already existed. A preset can be anything you can pass as $sizes parameter to the imageset() function.
imageset::presets('clear')
Clears all currently available presets, leaving you with no presets at all. However, this does not delete presets which have been defined in config.php via the imageset.presets. You can still load any presets that have been saved before by calling imageset::presets('save', …).
imageset::presets('load', $name)
Replaces all current set of presets with those that have been saved as $name before.
imageset::presets('reset')
Restores the presets defined in your config.php file.
imageset::presets('save', $name)
Saves all currently available presets for later use, where $name has to be anything that would be a valid PHP array key, except for the word 'inital', which is reserved.

Example

# /site/snippets/imageset-presets.php
<?php

// Presets for page content
imageset::presets([
  'default' => '200-1000,5',
  'small'   => '150-500',
  'square'  => '200x200-1000x1000,4',
]);

imageset::presets('save', 'content');
imageset::presets('reset');


// Presets for sidebar
imageset::presets([
  'default' => '200-500',
  'small'   => '100,150,200',
]);

imageset::presets('save', 'sidebar');
imageset::presets('reset');
# /site/snippets/header.php

<?php snippet('imageset-presets') ?>
<!DOCTYPE html>
<html>
[…]

In imageset-presets.php, two different sets of presets are defined, one for the main content ('content') and one for the narrower sidebar content ('sidebar'). This file was included in header.php to ensure that it loaded with every template. The following templates offers two different areas, where Kirbytext appears. Before calling the Kirbytext command, the corresponding set of size presets is loaded, so image tags inside your Kirbytext will be resized. After all Kirbytext has been generated, presets are reset to their initial state by calling imageset::presets('reset').

# /site/templates/default.php

<?php snippet('header') ?>

<main class="container">
  
  <article class="main-content">
    <?php imageset::presets('load', 'content') ?>
    <?= $page->text()->kirbytext() ?>
  </article>
  
  <aside class="sidebar">
    <?php imageset::presets('load', 'sidebar') ?>
    <?php if($image = $page->sidebar_image()->toFile()): ?>
      <?= $image->imageset() ?>
    <?php endif ?>
    <?= $page->sidenotes()->kirbytext() ?>
  </aside>
  
  <?php imageset::presets('reset') ?>
  
</main>
[…]
⚠️ If you’re using a snippet file for storing presets, it must not be named imageset.php as this name is reserved for a custom image set snippet as described in 7 Generating Custom Markup.

4.5 Kirbytext

ImageSet replaces Kirby’s built-in (image: …) Kirbytag by default to also allow usage of the plugin in your content. You can disable this custom image tag by setting imageset.tags.image to false in your config.php. It will also be ignored, if you have a file named image.php placed in the /site/tags directory.

The tag just works like Kirby’s image tag, but has an additional attribute called size. Using this parameter lets you use any of your size presets within Kirbytext:

(image: marina.jpg size: small)

If you want to transform every image within your content to an image set automatically, you can also specify a default size in your config.php:

c::set('imageset.tags.image.sizes.default', 'small');

If you do so, every image tag without the size attribute will be resized according to the preset you defined as default.

ℹ️ Only images in JPG, PNG or GIF format will be converted into ImageSets, other image types like SVG will just act like the original image tag and generate the same markup, as Kirby’s built-in image tag would do.
ℹ️ ImageSet will add the class defined in imageset.tags.image.class to the wrapper element of the generated markup to provide you a CSS hook for setting an image’s width according to your preset. The wrapper tag is either <a> (if image has the link parameter), <figure> (if enabled in Kirby’s configuration or image has a caption) or the wrapping <span> tag of the ImageSet itself.

6 Plain Output for RSS Feeds

If your site generates RSS-feeds, including full-blown image sets into the markup might not work with most RSS readers due to their lack of JavaScript and CSS support. You can force ImageSet to generate plain, RSS/XHTML-compatible markup by setting the output option.

# site/templates/feed.rss.php
[…]
<?= $image->imageset('200-800', [ 'output' => 'plain' ]) ?>
[…]

Because this is not suitable for Kirbytext, you can also change the global setting dynamically:

The imageset::outputStyle() function

imageset::outputStyle(string $style = 'auto')

$style : Takes either a value of 'plain' or 'auto' (default value).

Example

# site/templates/feed.rss.php
<?php
imageset::outputStyle('plain')
// All image sets created from this point will generate plain markup.
?>
[…]
<?= $image->imageset('200-800') ?>
[…]
<?php
imageset::outputStyle('auto');
// All image sets created from this point will generate regular markup again.

7 Generating Customized Markup

If the code generated by ImageSet does not satisfy the requirements of your project, you may override the snippet file, which is used to generate the markup for image sets.

Just place a copy of site/plugins/imageset/snippets/imageset.php in your snippets directory and make sure this file is also named imageset.php. Make your adjustments in the cloned file and ImageSet will load your custom snippet automatically.

⚠️ Keep in mind, that you might have to update your custom snippet file whenever ImageSet gets an update that makes changes to the vanilla snippet file. If you’re missing a feature that could be useful for other users as well, consider to open an issue describing your idea instead.

8 FAQ & Troubleshooting

So much markup for a single image? Yes … ImageSet was designed with broad compatibility among different browsers and progressive enhancement in mind. This does not work without more extensive markup. As browsers evolve, I will investigate into reducing the markup needed to be generated for image sets.
Will ImageSet slow down my site? ImageSet has been designed for performance. But as it uses Kirby’s built-in thumbs API, the plugin needs check the existence of every thumb on every page load. On pages with dozens of image sets and hundreds of corresponding thumbs, you may notice a performance impact. In these cases, it is recommended to enable Kirby’s page cache or to switch to a web hosting plan that comes with fast SSD storage. When a page has to generate hundreds of thumbnails on load, this may also exceed your maximum script execution time. In the latter case, consider to use the ImageKit plugin for asynchronous thumbnail creation or cloud-based service.
Frontend performance ImageSet uses JavaScript based filters for most placeholder styles to ensure good cross-browser support and nice-looking placeholders. However, these filters need some CPU time and low-quality sources have to be loaded for every image set. This can noticeably slow down page load on slow devices and also increases the overall download size of a page. If your page holds a huge number of ImageSets, you should consider to disable placeholders or use the `color` placeholder style, which is very lightweight. Rendering of placeholders is also much faster for images without an alpha channel, so prefer JPEGs or non-transparent PNGs wherever possible.
Does it support SVG images? There is only basic support for SVG images. That means, if you supply an SVG image as source file for your image set, the plugin will generate markup for the SVG image, using the <img> tag. But at SVG is a very complex document format, there is no simple way in PHP to generate placeholder thumbnails (imagemagick does not work reliably with every SVG file), so placeholder style will be ignored and the SVG file will be shown in its original aspect-ratio. Everything set in the $sizes parameter will be ignored.
Is it a good idea to apply custom CSS to my image sets? In general, it is not recommended to apply any custom CSS to anything inside the wrapper tag, as the HTML & CSS structure may possibly change with an update of ImageSet. It is recommended to apply all styles regarding custom positioning or sizing to the wrapping <span class="imageset […]">code> tag. You can use the class option to add custom classes, if you need different styles for different image sets.

9 Known Bugs & Limitations

Safari 10

When an image set appears within an element that uses CSS multi-colum layout (column-count > 1), the fade-in animation for lazy-loaded image sets does not work. However, the loaded image is displayed correctly. Currently, there is no way to fix this as far as I know.

Printing

Although it’s possible to trigger loading of images when a user hits the print button, that does not necessarily mean that images are generated before the browser generates its print preview or the user starts to print. A workaround for this is to preload all images after the page has been loaded. This ensures that image sets are loaded after other resources like JS and CSS files, but loads every image on the page and thus basically disables lazy-loading:

<script>
window.lazySizesConfig = window.lazySizesConfig || {};
window.lazySizesConfig.preloadAfterLoad = true;
</script>

12 Credits

ImageSet was developed and maintained by Fabian Michael, a graphic designer & web developer from Germany.

The plugin includes the following third-party components:

kirby-imageset's People

Contributors

daybugging avatar fabianmichael avatar grommas avatar tristantbg avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kirby-imageset's Issues

Add option for XHTML-compliant markup

Add option to generate XHTML-compliant output. As Kirby does omit the trailing slash for all HTML code generated by e.g. the Toolkit, this should be optional.

#2

Setting options with variables

Hi again @fabianmichael. I'm trying to dynamically add a caption using Imageset options but am running into an error. I expect it to work but no dice.

Image is being created with the following code (caption has definitely been set in Panel) with an error returned.

$image = $page->image($data->image());
$image_options = ['alt' => $image->caption(), 'placeholder' => 'blurred'];
echo imageset($image, '400, 500, 800, 1024', $image_options);

Uncaught exception 'Exception' with message 'Serialization of 'Closure' is not allowed

If I set a blank caption or an ordinary string (instead of $image->caption()) then it produces the Imageset image perfectly.

Thanks

Wrong error message if thumbs folder is missing

If the thumbs folder is missing the error message is "The cache directory does not exist".

I think the message is a little bit confusing because the cache folder exists. Maybe it is better to show a error message that the thumbs folder is does not exist.

Generate HiDPI images

Just an idea: are you planning to also generate HiDPI images?

Congrats on all the work so far, by the way, the plugin looks great!

Saturation issues

Thank you for the fantastic plugin my pages load so gracefully now.

I have noticed a slight issue with image saturation/vividness of colors are. It seems imageset is making the slightly muted as you can see in the attached thumbnail. I'm not sure whether this is a bug or bad implementation of the plugin by me. Any help would be greatly appreciated.

imageset_saturation

Template Code

<div>
    <div>Imageset</div>
    <?php if($image = $page->thumbnail()->toFile()):?>
        <?= $image->imageset([
                '160-1280,6', 'sizes' => '(min-width: 640px) 100vw, 50vw'
            ], [
                'class'       => 'awesome-image',
                'placeholder' => 'color',
            ]) ?> 	  
    <?php endif; ?>
</div>
<div>
    <div>Default</div>
    <?php if($image = $page->thumbnail()->toFile()):?>
        <img style="width: 100%;" src="<?= $image->url() ?>" />
    <?php endif; ?>
</div>

Using files from /assets

HI @fabianmichael. Thanks for your work on this great plugin.

I'm trying to create a srcset from an image that I have stored in my /assets folder but am having some trouble. I'm trying the global function as well as the File object method but get the following errors.

$image = new Media ($kirby->roots()->assets() . '/images/image.png');
$image->imageset('200');

Call to undefined method Media::imageset()
$image = new Media ($kirby->roots()->assets() . '/images/ISOW-video-holder.png');
imageset($image, '200');

Class 'Kirby\Plugins\ImageSet\url' not found

It may be that I have an incorrect understanding of the Media object but are you able to shed some light on accessing images from /assets?

Thanks!

Issue with Dynamic Presets API

Hi Fabian,

I run into the following issue:

If I include the Dynamic Presets API example snippet in my header snippet, without doing anything else (e.g. loading the preset), I get the following error:

Fatal error: Uncaught Exception: Initial presets are saved on initialization and cannot not be overridden at a later point.

What am I doing wrong?

For what it is worth, this is my imageset config:

c::set('imageset.styles.consolidate', false);
c::set('imageset.tags.image', true);
c::set('imageset.tags.image.sizes.default', 'default');
c::set('imageset.tags.image.class', 'figure-image size-{size}');
c::set('imageset.placeholder', 'triangles');
c::set('imageset.noscript', true);
c::set('imageset.lazyload', true);

c::set('imageset.presets', [
	'default' => [
		[ '300-2880,5' ],
	],
	'1of2' => [
		[ '320-1440,3' ],
	],
	'1of3' => [
		[ '320-960,2' ],
	],
	'hero' => [
		[ '320x180-1920x1080,5', 'media' => '(min-aspect-ratio: 3/2)' ],
		[ '320x320-1000x1000,5' ],
	],
]);

Any idea?

Whitespace at bottom of images

The span.imageset element has a little whitespace below the image. I don't believe I have other styles causing this, but feel free to close/ignore if you can't replicate.

In case you can, here's how I fixed it.

1
2

Implement API for JavaScript image loader

The JavaScript component of ImageSet should allow more control over how imagesets are loaded.

Use Cases:

  • Content containing imagesets is animated and placeholder rendering causes animations to stutter.
  • Devs might want to influence the loading priority of certain imagesets.
  • Cached imagesets should not display the transition from a placeholder, but should show the loaded image instantaneously.

hidden images render at smallest srcset size

I hide most of an article's content on page load, then reveal that content, with images, when the user clicks "read more". The images inside this initially-hidden area are rendered with the smallest srcset size, and thus appear blurry when finally revealed. Is there a way around this, or to ask the browser to choose a higher srcset?

Security vulnerability in build process

Hi there,

For a couple of weeks, Github has been giving me the following warning relating to the use of the Imageset plugin 1.1.0-beta2 on my Kirby build (now updated to 2.5.11).

screenshot 2018-07-03 11 33 32

screenshot 2018-07-03 11 34 02

I was hoping you'd have fixed this but maybe you didn't see; perhaps now it's right I draw your attention to it. I really need Imageset in my forthcoming build; all of my image work relies on it, and this issue is beyond my skillset.

Thanks,

Simon Collison

Can I set default sizes in imageset.presets?

I have the following code in site/config.php:

c::set('imageset.presets', [
    'project'    => [
        ['640-1380,1', 'sizes' => '(max-width: 320px) 640px, (max-width: 505px) 1010px, 1380px', 'placeholder' => 'color']
    ]
]);

Unfortunately I still get <img sizes="100vw"... on the front-end. Am I doing something wrong?

I tried with lazy loading turned off, c::set('imageset.lazyload', false);, but get the same thing.

Images aren't loaded properly

After playing more and more with Imageset I'm quite impressed by it's possibilites – great work so far :) However, it seems that my images are sometimes lacking the load event and therefore just the color is displayed… I'm not quite sure where and why this takes place, but all I can say is that it's only sometimes on initial load (after reloading, it works), and also only affecting images which are over the fold, so visible on initial load. I didn't encounter this when just using lazysizes, so I guess this has something to do with the Imageset JS?

Seen in the latest versions of Safari, Chrome and FF (Dev and normal version), placeholder style is color.

Uncaught SyntaxError: Unexpected token :

<?= js('assets/plugins/imageset/js/dist/imageset.js') ?>

Throws this error:
Uncaught SyntaxError: Unexpected token :
screenshot 2017-06-17 10 39 08

And

<?= js('assets/plugins/imageset/js/dist/imageset.min.js') ?>

Throws this error imageset.min.js:22:

Uncaught DOMException: Failed to execute 'getImageData' on 'CanvasRenderingContext2D': The source width is 0.
    at Object.r [as canvasRGB] (http://localhost/assets/plugins/imageset/js/dist/imageset.min.js:22:1806)
    at http://localhost/assets/plugins/imageset/js/dist/imageset.min.js:22:6440
    at e (http://localhost/assets/plugins/imageset/js/dist/imageset.min.js:22:4066)

Small images lead to fatal error

This issue has cost me several hours yesterday of trial and error, and fortunately I was able to find the reason and find a way around – but I'd love to see a fix (or a official recommended solution for this one). To be honest: I only tried with the color placeholder, but as I don't want to use the other effects, this somehow had to work ;-) Oh, and I'm using the modules and the patterns plugins (just to mention the important things), running locally with MAMP and PHP 7.1, and all necessary things installed. Everything else is basically the default configuration from Kirby or the plugins.

After installing the plugin, the first two images worked perfectly without any problems. With the third implementation and call of imageset(), I got the following error:

Method Kirby\Plugins\ImageSet\ImageSet::__toString() must not throw an exception, caught InvalidArgumentException: Passed variable is not a valid image source

Digging deeper into the code, I found out that hasTransparency() function triggered this error. The problem seems to be that the given $media object was corrupt, returning a root = NULL and stuff like that, while giving me the correct file URL.

After this I thought that my files where corrupt and tried the third implementation, where the error occured, with the files from instances 1 and 2. Worked like a charm. So I re-saved the original third image with Photoshop and re-uploaded it – resulting in a fatal error.

I then compared both debug info's from the File class, without any noticeable differences (besides path and name, of course) – and the dimensions: the first image was a hero, the second one a news preview from the old website I'm now rebuilding with 250x125px. After enlarging the image to 1000x500px, the error was gone and everything worked perfectly! But of course is not a reliable way of getting the error done – this site has only ~100 of such small images, but researching for the original images (if they still exist) and reuploading every image would cost me hours. Not speaking of sites with much more images…

In the end, I'm not really sure where the issue is coming from in the code, but to be honest, I'm not really motivated to search any further ;) It is definitely not related to the presets or sizes – I set them to '50,100' after finding out that the issue is related to the image dimensions…

Using ImageSet with Asset objects

Congratulations to 100 ⭐️
Question: Is there any way to use it with Asset objects (see docs)?

When I do this:

$fallback = new Asset('assets/images/header.jpg');
echo $fallback->imageset([ '900x243' ], [
  'placeholder' => 'triangles',
  'alt' => $image->img_desc()
]);

.. I get Call to undefined method Asset::imageset(). It seems to be similar to #4.

Future K3 compatibility?

I noticed you updated the readme stating incompatibility with K3. I'm eager to upgrade but have imageset woven into my build. Do you have a proposed date for K3 support? I'd be willing to pay again for an update.

JS Error in the console

Hey,
I am using the latest version of ImageSet and getting this error in the console recently Uncaught ReferenceError: el is not defined on line 945 of imageset.js. Maybe you could have a look :)

Btw are you planning future releases of ImageSet & ImageKit? Both seem a bit stagnant unfortunately :(

Dennis

How does js and css including work?

Sorry for the question, but on template setup you use

<?= css('assets/plugins/imageset/css/imageset.min.css') ?>

and

<?= js('assets/plugins/imageset/js/dist/imageset.js') ?>

but there is no such file nor plugins folder in my assets directory. It is still working tho, so I ask myself how does this even work?

Placeholder is removed before image has lazyloaded

Hello there,

the plugin is really great but I'm experiencing issues/unexpected behaviour with lazyloading:

The __wrapperLoadedClass (.is-loaded) seems to be set before the contained img is lazyloaded. Since .is-loaded is responsible for fading out the placeholder image, all placeholders for images outside the viewport are removed before the images behind them are loaded.

This means that the placeholder only works for elements that are already in the viewport on page load. Depending on image size, bandwidth and scroll speed, images outside the viewport will either be already rendered or pop in without any fade effect which is not very elegant.

I'm not sure if .is-loaded serves any other purpose besides the CSS fading but if it doesn't it should not be synced to the .lazyloaded class on the img container.

I hope this makes sense. A fix would be appreciated.

Cheers!

Integrating imageset.js in my workflow

Hey there,
quick question: I want to include imageset.js in my own workflow (currently webpack), how would I go about this? Importing the library (import 'path/to/plugin/imageset.js') works, but then execution fails.

Tested this with the latest version of ImageSet, any pointer is much appreciated!
Thank you.

Option / Possibility to change style attr

I'm currently working with the focus plugin and set the focus for the image with object-position. Currently I do a simple str_replace for the style attribute but this feels kinda hacky.

file::$methods['imagesetFocus'] = function($file, ...$args) {

  $imageset = $file->imageset(...$args);
  $position = $file->position();

  $div = new Brick('div');

  $div->addClass('o-focus');
  $div->attr('style', 'background-image: url("' . $imageset->src() . '"); background-position: ' . $position . ';');

  return $div->html(str_replace('style="max-width: 100%; height: auto;"', 'style="-o-object-position: ' . $position . '; object-position: ' . $position . ';"', $imageset));

};

Something like this would be more convinient.

file::$methods['imagesetFocus'] = function($file, ...$args) {

  $position = $file->position();
  $imageset = $file->imageset(...$args)->attr('style', '-o-object-position: ' . $position . '; object-position: ' . $position . ';');

  $div = new Brick('div');

  $div->addClass('o-focus');
  $div->attr('style', 'background-image: url("' . $imageset->src() . '"); background-position: ' . $position . ';');

  return $div->html($imageset);

};

Probably not that easy because there are a bunch of different output formats.

readme js file

about 2.3 template setup of readme... should be minified file, right? its currently not.

<?= js('assets/plugins/imageset/js/dist/imageset.min.js') ?>

Thumbnails blacking out during lazyload

Hey there,
until #16 is fixed I'm using v1.0.1 and stumbled across the behaviour described in the title:

black-out

Upon page load, sometimes there's a black-out of some thumbnails generated by ImageSet. I checked if this was fixed in the most recent beta release but didn't find anything.

Uncaught ReferenceError: el is not defined

imageset.js:945 Uncaught ReferenceError: el is not defined
    at process (imageset.js:945)
    at imageLoaded (imageset.js:710)
    at imageset.js:964
    at loop (imageset.js:725)

Using the latest imageset version. I tried to replace el with wrapper after looking through the commit history. I think the problem started with the latest refactoring and kugugug 😹 I switched back to 1.0.1, didn't try it with other effects than blurred/LQIP.

How to add an HTML attribute to the img tag

I try to use imageset for an image map. I would need to add usemap="#imagemap" within the <img> tag. Is this possible, and if, how? Thanks!

Well, i just learned that image maps don't scale, because they are pixel based. So i will have to check how i can build a responsive image map equivalent with SVG. I will post here again if i still need this functionality.

Ignore GIF

Is possible to make ImageSet ignore gifs? Because it eliminates the animation.

Placeholder is not removed in rare cases when lazyloading

I used your beautiful placeholders before but I came across an issue (could reproduce it in latest firefox, but not chrome/safari) where they just not disappear even though the image has loaded long before. This is certainly the case for images which are already in the viewport when the site loads (see the video below).

I inspected the elements and saw that the ".is-loaded" class is not appended to the lazily loaded image-wrappers ('s), so the placeholder won't disappear.

This happens not every time so I had to reload multiple times in the video before it breaks. But it happens so regularly (and client has also noticed) that I had to remove the placeholders from some of my live projects :(

Screenrecording: https://www.dropbox.com/s/dz3bnhlx7589wwl/ImageSet%20Lazyload%20Issue.mp4?dl=0

FocusCrop and Imageset

Hi there, first of all thank you for the great plugin!

I'm having the exact same issue as oliverschneider describes here: https://forum.getkirby.com/t/imageset-responsive-images-with-lazy-loading-and-beautiful-placeholders/6006/28

However, I should have come farther I thought by doing this

$image = $image->focusCrop(800); // making it an Asset Object btw.
$image = new Media($image->root());
echo $image->imageset('400-800');

... but no such luck "Call to undefined method Media::imageset()" - which is extra odd since imageset should support not only File, but Media Objects I believe. Neither does it work with an Asset object although the source suggest that Media Object get converted to Asset Objects in any case ;-)

Any help would be super appreciated!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.