Create Image Loading Placeholders

Teri Eyenike

In today's world, where optimization and loading time is crucial for websites, loading placeholders are developed to improve the waiting experience of users on a webpage.

This article will discuss how to create a loading placeholder image that shows a lightweight version of an image, whether pixelated, blurry etc., before the target or original image is displayed.

We will be using NuxtJS, an open-source front-end framework built on top of Vue that features file-system routing, and it delivers both static-site generation (SSG) and on-demand server rendering.


You can fork and run the completed application in CodeSandbox.

The source code for this project is available on GitHub.


The requirement for completing this tutorial is experience building with Vue.js and Nuxt.js. To follow through the steps, we need to do the following:

  • Have node.js installed on our computer. npm will be available for installing dependencies with the installation done.
  • A Cloudinary account for storing and uploading our media assets. Signup for a free account, here.
  • A text editor of our choice.

Dependency installation

We scaffold a nuxt app in a folder called image-placeholders, using the following terminal command:

1`npm init nuxt-app image-placeholders`

The command above will trigger a set of prompts. And we can choose the following as shown below:

1`Project name: accept the default, Press Enter`
4`Programming language: JAVASCRIPT`
7`Package manager: Npm`
10`UI framework: Tailwind CSS`
13`Nuxt.js modules: N/A`
16`Linting tools: N/A`
19`Testing framework: None`
22`Rendering mode: Universal (SSR / SSG)`
25`Deployment target: Static (Static/Jamstack hosting)`
28`Development tools: jsconfig.json`
31`What is your GitHub username? <github-username>`
34`Version control system: GIT`

The above command created our project, image-placeholders. We will be using Tailwind CSS for styling, a utility-based CSS framework that helps build modern websites packed with classes used directly in our markup.

In the project directory, we run the following command to spin up a development server on port 3000.

1`npm run dev`

Cloudinary Account Details

We require the cloud name, API key, and API secret to configure Cloudinary in Nuxt. This is retrieved from our Cloudinary dashboard.

Cloudinary configuration

We require the @nuxtjs/cloudinary module and we install it with the command below:

npm install @nuxtjs/cloudinary

The nuxtjs/cloudinary module provides a robust development kit allowing us seamlessly use Cloudinary in Nuxt.js apps.

In the nuxt.config.js file, add @nuxtjs/cloudinary as a module in the modules section.


1modules: [
2 "@nuxtjs/cloudinary"

After that, we need to set configurations for the Cloudinary module within nuxt.config.js and add the cloudinary section.


1modules: [
2 "@nuxtjs/cloudinary"
5// add this section
6cloudinary: {
7 cloudName: "<your-cloud-name>",
8 apiKey: "<API-Key>",
9 apiSecret: "<API-Secret>",
10 useComponent: true,

The useComponent key set to true lets us use Vue components for images and videos embedded with Cloudinary functionalities.

Environment Variables

We create a file .env in the root of the folder. Add the variable's name within the file and set the value to the API key and secret retrieved from our Cloudinary dashboard. This protects critical information from exposure in the codebase.


1NUXT_API_KEY=<insert api key without quotes>
2 NUXT_API_SECRET=<insert api secret without quotes>

Next, we include the value and name set in the .env file into nuxt.config.js


1modules: [
2 "@nuxtjs/cloudinary"
3 ],
5 cloudinary: {
6 cloudName: "<your-cloud-name>",
7 apiKey: process.env.NUXT_API_KEY,
8 apiSecret: process.env.NUXT_API_SECRET,
9 useComponent: true,
10 }

Display Image with a placeholder

First, we upload a sample image to a folder called image-placeholders on Cloudinary.

Here is the final result of the saved image asset.

With the image stored in Cloudinary, we go to the index.vue component and add the following code snippet.


2 <div class="lg:flex items-center h-screen">
3 <div class="w-full px-8">
4 <h1 class="md:text-5xl lg:text-4xl font-bold text-stone-800">
5 IMAGE LOADING <span class="block">PLACEHOLDER</span>
6 </h1>
7 <h2 class="md:mb-4 lg:mt-3 text-blue-700">using Cloudinary and Nuxt</h2>
8 </div>
9 <cld-image
10 :public-id="publicId"
11 loading="lazy"
12 gravity="auto:subject"
13 fetchFormat="auto"
14 quality="auto"
15 alt="Calm teri sitting"
16 >
17 <cld-placeholder type="pixelate" />
18 </cld-image>
19 </div>
20 </template>
21 <script>
22 export default {
23 name: "IndexPage",
24 data() {
25 return {
26 publicId: "image-placeholders/teri",
27 };
28 },
29 };
30 </script>
31 <style>
32 .cld-image {
33 object-fit: cover;
34 border-radius: 10px;
35 }
36 </style>

From the above snippet of code, we did the following:

  • We included classes in the markup using Tailwind CSS.
  • Configured the cld-image component to deliver and transform our image. The loading attribute is set to lazy load the image and we passed the publicId of the Cloudinary as a prop to the component. Also, in the component, we added the gravity, quality, fetchFormat transformation properties on the image.
  • Configured the cld-placeholder component to display a lightweight image version of the target image with type attributes to define the kind of placeholder the image will use. The different placeholder types are:
    1- pixelate
    2- vectorize
    3- blur
    4- predominant-color


In this post, we used the @nuxtjs/cloudinary module to render a pixelated version of an image, while lazy loading the image. This technique provides immense user experience benefits.

Further Reading

Teri Eyenike

Software Developer

Teri Eyenike is a software developer interested in making things simple and usable.