Display Placeholder While Image is Loading

CldImage wraps the Unpic Image component, thus giving us access to the placeholder API which can display an SVG image while the image itself is loading.

This helps for providing a great user experience, rather than an empty space, to help let the visitor know that image is loading.

To do this, we have several options:

  • placeholder="blur" coupled with a blurDataURL
  • placeholder="..." with the contents being a data URL

Blurred Images

To achieve a blurred image effect, we can first convert our Cloudinary image to a Data URL then pass it in to our CldImage component.

Mountains

Inside of the SvelteKit app, we can utilize server side code to generate a data URL from our image.


import { getCldImageUrl } from 'svelte-cloudinary';

export const load = () => {
  const imageUrl = getCldImageUrl({
    src: '<Your Public ID>',
    width: 100, // Resize the original file to a smaller size
  });
  const response = await fetch(imageUrl);
  const arrayBuffer = await response.arrayBuffer();
  const buffer = Buffer.from(arrayBuffer);
  const base64 = buffer.toString("base64");
  const dataUrl = `data:${response.type};base64,${base64}`;
  return {
     dataUrl
  }
}

Then when rendering CldImage, utilize the dataUrl using placeholder and blurDataURL:


<script>
  import { CldImage } from 'svelte-cloudinary';
  export let data
</script>

<CldImage
  src="<Your Public ID>"
  width="600"
  height="400"
  alt="Decriptive text"
  placeholder="blur"
  blurDataURL={data.dataUrl}
/>

Shimmer

In a similar fashion, we can create a shimmer effect when our images are loading.

Mountains

Inside of the SvelteKit app you can use a server side code +page.server.js to generate a data URL from our image.

export const load = () => {
  const shimmer = (w: number, h: number) => `
    <svg width="${w}" height="${h}" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
      <defs>
        <linearGradient id="g">
          <stop stop-color="#333" offset="20%" />
          <stop stop-color="#222" offset="50%" />
          <stop stop-color="#333" offset="70%" />
        </linearGradient>
      </defs>
      <rect width="${w}" height="${h}" fill="#333" />
      <rect id="r" width="${w}" height="${h}" fill="url(#g)" />
      <animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite"  />
    </svg>`

  const toBase64 = (str: string) =>
    typeof window === 'undefined'
      ? Buffer.from(str).toString('base64')
      : window.btoa(str)

  const dataUrl = `data:image/svg+xml;base64,${toBase64(shimmer(600, 400))}`;
  return {
    dataUrl
  }
}

Then when rendering CldImage, utilize the dataUrl using placeholder:

<script>
  import { CldImage } from 'svelte-cloudinary';
  export let data
</script>

<CldImage
  src="<Your Public ID>"
  width="600"
  height="400"
  alt="Decriptive text"
  placeholder={data.dataUrl}
/>

Learn More


MIT 2023 ©