Use data-src in video() Helper

I would like to use aFarkas/lazysizes to lazyload the video iframe. Therefore I need the video helper to output data-src instead of src.

The simplicity of embedding videos with video() is great! The fact that it changes the regular URL to the /embed URL and that we get a preview in the Panel makes it perfect for the editors. Therefore I would like to keep those functionalities.

I am a bit lost at the moment, so I wanted to ask what the right way would be to find a solution? I use it as a video block. Should I therefore create a custom block with the same content as the default video block and only change src to data-src?

A hint in the right direction would be super helpful. Thank you!

You need to override the default video snippet for the block and alter the code to match the output you want.

Thank you for the answer. There is a lot of new stuff which I never worked with before, so it is possible that this is completely wrong, but I tried something like this:



Kirby::plugin('mirkokokoko/customvideo', [
  'snippets' => [
    'blocks/customvideo' => __DIR__ . '/snippets/blocks/customvideo.php'


Which comes mostly from the video.vue file. I only changed all video to customvideo to better see if there is even something happening. And then of course the change of src to data-src.

panel.plugin("mirkokokoko/customvideo", {
blocks: {
  customvideo: {
    computed: {
      customvideo() {
            var url = this.content.url;
            if (!url) {
              return false;
            var youtubePattern = /^.*(\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/;
            var youtubeMatch = url.match(youtubePattern);
            if (youtubeMatch) {
              return "" + youtubeMatch[2];
            var vimeoPattern = /vimeo\.com\/([0-9]+)/;
            var vimeoMatch = url.match(vimeoPattern);
            if (vimeoMatch) {
              return "" + vimeoMatch[1];
            return false;
    template: `
      :empty-text="$t('field.blocks.customvideo.placeholder') + ' …'"
      <k-aspect-ratio ratio="16/9">
        <iframe v-if="customvideo" :data-src="customvideo" />

The block snippet snippets/blocks/customvideo.php

<?php if ($block->url()->isNotEmpty()): ?>
<figure class="video">
<?= customvideo($block->url(), 
    'class' => 'lazyload',
) ?>

  <?php if ($block->caption()->isNotEmpty()): ?>
  <figcaption><p><?= $block->caption() ?></p></figcaption>
  <?php endif ?>
<?php endif ?>

The part in the blueprint:

        name: Customvideo
        icon: video
        preview: video
            label: Customvideo
            type: url
            placeholder: Customvideo …
            label: Customvideo caption …
            type: writer
            inline: true

With this, I get the following error in the Frontend:
Block error: “Call to undefined function customvideo()” in block type: “customvideo”

This function is nowhere defined…

While you do define a JavaScript function called customvideo() this cannot be used in your PHP code…

The original block used the video() helper defined in /kirby/config/helpers.

Thank you for the tipps!

So the function customvideo() should be defined in the plugins/customvideo/index.php?
I couldn’t get this to work. I also couldn’t find anything which describes how to register and work with such a function inside a plugin in the docs. Where would I look for something like this?

Yes. Simple functions are defined outside the Kirby::plugin() wrapper.

Thank you @texnixe for the directions.
After some try and error I could make it work with the following code:


function customvideo(string $url, array $options = [], array $attr = []): string {
  if (!$url) {
    return false;
  $matches = null;

  $youtubePattern = '/^.*(\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/';
  $youtubeMatch = preg_match($youtubePattern, $url, $matches);

  if ($youtubeMatch) {
    return "" . $matches[2];

  $vimeoPattern = '/vimeo\.com\/([0-9]+)/';
  $vimeoMatch = preg_match($vimeoPattern, $url, $matches);
  if ($vimeoMatch) {
    return "" . $matches[1];

  return false;


Kirby::plugin('your-project/customvideo-block', []);


<figure class="video">
  <iframe class="lazyload" data-src="<?= customvideo($block->url()) ?>" frameborder="0" allowfullscreen></iframe>

  <?php if ($block->caption()->isNotEmpty()): ?>
    <figcaption><p><?= $block->caption() ?></p></figcaption>
  <?php endif ?>

There is maybe a simpler version, but it seems to work. Thanks again!