A global function for loading resources to base64-encoded data URLs

I am fond of a technique where I make a small, few kilobyte version of an image, and embed it as an inline base64-encoded data URL on the page, and layer the real image that’s normally stored in a file over that. The blurry version of the image loads instantly, so the layout, the colors and the rough shape of the image are right from the start preventing the infamous “Flash of unstyled content” style loading artefacts, and a few kilobytes don’t affect the page load time basically at all.

You can see an instance of this technique here. It’s a site I created with Zola: https://saunoja.jp

It would be very nice, if Zola supported a global function called “data_url” (or similar) that would load an arbitrary resource from a file as binary, and output it as base 64-encoded data URL. In combination with the image processing function, it would make this technique a lot easier and quicker to use.

I’m willing to contribute a PR, if this seems something that Zola would like to support.

How would you envision it as a usage -> output? I like the idea a lot.

I imagine a flow like this: I have a big image file I’d like to use as a background visual (such as the images on the linked page).

The background visual is different on every page, so it’s styled inline using templates:

<header style="background-image: url({{
    resize_image(path=header_image_path, width=1000, op='fit_width') | safe
  }}), url({{
    data_url(path=resize_image(path=header_image_path, width=100, op='fit_width', quality=0.50) | safe)
  }});">

Note the second url: the image is resized, but this time into a small thumbnail-like image that will take only a few kilobytes. resize_image outputs the path of that file. data_url then reads the contents of that file, and outputs a data URL like data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//gA7..., that ends up in the file, inline.

If the file already exists as a small file (such as a small emoticon .gif or a bullet point etc.), the user can just pass the path directly to data_url.

There’s two design questions about this flow that need to be solved:

  • At the moment, resize_images outputs a “finalized”, absolute URL, not a local path, so the flow I’m imagining wouldn’t work without some modifications. I haven’t thought yet what would make sense from a global viewpoint (and I’m not that experienced in Zola yet, so I might be missing something)
  • Data URLs include a MIME type. The function could have a parameter so that the user could specify that, but it would be nice if there were autodetection by default (a file extension based or content based; there also exists libraries such as libmagic for that.)

(A similar flow can be implemented using <img> tags also.)

About the first list item, there’s some other problems with outputting a “finalized” URL too, I filed a bug here: https://github.com/getzola/zola/issues/1245 Not sure if it’s an actual bug though, but it’s something that I find less than ideal.