Kirby3-srcset with caption

Hey,
I’m using the great plugin from @bnomei kirby3-srcset. But this plugin doesn’t allow to set a caption to the image. A good practice would be to wrap the image inside a figure and a figcaption for the caption text. How do you think this could be done with the new Html:: method ?

 'tags' => [
        'srcset' => [
            // https://getkirby.com/docs/reference/text/kirbytags/image
            'attr' => ['caption', /* The caption attr */ 'preset', 'lazy', 'prefix', 'class', 'imgclass', 'link', 'linkclass', 'target', 'rel', 'snippet'],
            'html' => function ($tag) {
                // TODO: move code to class
                try { 
                    $file = Kirby::instance()->file($tag->value, $tag->parent());
                    if ($file) {
                        $preset = (string) $tag->preset;
                        if (\Kirby\Toolkit\Str::contains($preset, ' ') || \Kirby\Toolkit\Str::contains($preset, ',')) {
                            $preset = str_replace(['[', ']', ',', '  ', 'px'], ['', '', ' ', ' ', ''], $preset);
                            $preset = array_map(function ($v) {
                                return trim($v);
                            }, explode(' ', $preset));
                        }
                        $prefix = (string) $tag->prefix;
                        $class = $tag->class ? trim($tag->class) : null;
                        $imgclass = $tag->imgclass ? trim($tag->imgclass) : null;
                        $snippet = $tag->snippet ? trim($tag->snippet) : 'plugin-srcset-img';
                        $srcset = \Bnomei\Srcset::srcset($file, $preset, boolval($tag->lazy), $prefix, $class, $imgclass, $snippet);
                        if ($tag->link) {
                            $attr = [
                                'href' => trim($tag->link),
                            ];
                            if ($tag->linkclass) {
                                $attr['class'] = trim($tag->linkclass);
                            }
                            if ($tag->target) {
                                $attr['target'] = trim($tag->target);
                            }
                            if ($tag->rel) {
                                $attr['rel'] = trim($tag->rel);
                            }
                            // wrap $srcset in array to avoid encoding
                            // https://github.com/getkirby/kirby/blob/master/src/Toolkit/Html.php#L367
                            return \Kirby\Toolkit\Html::tag('a', [$srcset], $attr);
                            
                        } else {
                            return $srcset . PHP_EOL;
                        }
                    }
                    return '';
                } catch (Exception $ex) {
                    return $ex->getMessage();
                }
            },
        ],
    ],

According to the readme, you can set the figure option to true or false and since the plugin inherits the original image tag attributes, there should be a caption attribute?

Oh yes, the author has made some changes 12 hours ago, I didn’t noticed. It’s working !

Sorry for the inconvenience, and once again : congratulations for this wonderful plugin.

1 Like

But… :wink: I don’t understand why any lazyloading plugins are not using the “unknown height” technique as I mentionned in a previous thread.
Every time I have to fix it by myself to avoid the overlapping/flashing effect on load, and specially needed on a masonry layout…

With your help, I could fix it on Kirby 2 by overriding the default kirbytag, but here with this plugin, it’s a new challenge that comes up

thanks for using my plugin and even the still un-announced v3. :stuck_out_tongue_closed_eyes:

i could add the possibility to set the style attribute but personally i think using it is bad practice so i will not. but here is my solution for your problem.

add an basic ratio css class to your css and apply it to every figure. that is setting the class not the imgclass property.

.ratio-container {
    position: relative;
}
.ratio-container:after {
    content: '';
    display: block;
    height: 0;
    width: 100%;
    /* 16:9 = 56.25% = calc(9 / 16 * 100%) */
    padding-bottom: 42.86%; /*default: pick whatever is best for you*/
}
.ratio-container > * {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    display: block;
}

further more use sass mixin or do it by hand to generate 100 padding-bottom variants. like these

.ratio-49.ratio-container:after {
    padding-bottom: 49%;
}
.ratio-50.ratio-container:after {
    padding-bottom: 50%; 
}
.ratio-51.ratio-container:after {
    padding-bottom: 51%;
}

when building you srcsets from images apply the needed ratio padding-bottom variant as well as the container.

$classesForFigure = 'ratio-container ratio-' . round($image->dimensions()->ratio() * 100); 

edited: you probably will not need 100. maybe a range from 30 to 70 is good enough.

source: tip-specifying-image-dimensions-minimizing-reflows-and-avoiding-page-jumps

i am aware that you use the same technique before as linked in the k2 version thread but without the pre-generated ratio variants. i summed it up like this so i can link it from the readme of the plugins as well.

Haha thank you very much, I did’nt know this smart method with pseudo :after. But this looks a bit hacky for me, and I still think that it would be easier to use the ratio with padding style directly inside a div container.
The kirbytag could work as an all-in technique without additional style.

Note : to work, we just have to create an absolute div style wrapping the image, and set the ratio padding to the image. For me it’s a damn challenge to custom your code, for you it’s surely fingers in the nose :wink:
Let’s say something like (lazysrcset: myfile.jpg ratio:yes) and the magic is done !

the css creates a pseudo block using after which has the padding. the image is just stretched to fill the space the pseudo element creates. i do not think its hacky – just like the name implies after is an pseudo element and we need space where there was none.
solving it by creating another div does not make it better. you still have to stretch the image to fill the div. so its just one div more.

but you have a valid point. all this can not be done from the kirbytag. one would need php for that. i will think about that and report back.

this is why i do not like using the style attribute – it is the emperor himself: https://stuffandnonsense.co.uk/archives/css_specificity_wars.html

:wink:

magic done. almost… you still need to provide the css as described in the readme.

i thought about this a while and i think its a great addition. thanks @Oziris !

Yeah ! Thank you, I appreciate very much !

I have read the article and I have to say the authors has some heavy arguments. But as we know, things are more complicated than “good or bad” practices, and must be estimated for the efficiency they offer, I think.
I would like to know what changed your mind?

I have tried your last realease on my masonry layout, and every items are oversized by height, but I didn’t digged your code yet, I don’t know from where it come from. I have to say I don’t understand the additionnal css to include, same for the logic from data-ratio. For me it’s like : "Ok, we have a straight line solution (apply style % ratio directly inside the code), or we have another solution that consist to go to point D and C before going to point B from A. :slight_smile:

Did you take in account the figcaption option when applying the ratio to the figure ?

Edit : this would be the thing I would do, maybe I’m wrong :

<figure>
   <div class="container" style="padding-bottom: calc(100% / [ $image->dimensions()->ratio() ])">
      <img ....>
   <div>
   <figcaption>
      Blabla
   <figcaption>
</figure>

With basic style

.container {
 display: block;
 position: relative;
 height: 0;
}

.container img {
 position: absolute;
 top: 0;
 left: 0;
 width: 100%;
 height: 100%;
}
  • adding a div wrapper is not what i want. this is different element order than the kirby image tag creates. i will not do that. its not DCBA and it is not a more complicated solution. i am adding nothing to the dom. you want to add an structure element where no structure is happening. the render props of that image need to reflect what we want. i am solving an render problem with css logic. that is what css is for.
  • adding inline style makes it hard to override that element with css if you need to remove or adjust the padding bottom. i will not do that. otherwise the padding bottom will be there no matter what the global css says.
  • send me a picture of the oversized mazonry layout. preferable as an issue in the plugin repo. post the html code as well or give the an url. but i probablly just have something wrong in the code i created at close to midnight. i will fix that later today.
  • i did not take the figcaption into consideration since i never used the caption param of the image kirbytag before. you are right it creates an figcaption element. i will adjust my code and css to solve that.

done. https://github.com/bnomei/kirby3-srcset/releases/tag/v3.0.2

adding a div for the case with figcaption was indeed the only proper solution. i apologize for being ignorant in that regard. you need to grab the updated css from the readme as well.