Skip to content

Optimizing image loading using sprites in NuxtJS

When a webpage loads several images, especially of small sizes, the requests can become quite costly. If we combine them into a single image, we reduce the load on our server as well client load time. Creating sprites can be challenging as well as consuming them. Let us learn how we can easily use them in a Nuxt.Js app.

The completed project is available on Codesandbox.

You can find the full codebase on my Github

Cloudinary is a media management platform geared at allowing developers to unleash their full potential. We are going to use their platform to store our images and generate the image sprite. If you do not have an account, register here

Once your account is setup, proceed to the media library and create a folder called nuxtjs-image-sprites. Within this folder, upload the following files:

Once uploaded, you should have a folder similar to this one:

Image folder

Select all the images in the folder and give them the tag nis-cartoons.

Nuxt.Js is a VueJS framework that boasts of simplicity and productivity.

Ensure you have Yarn or npm v5.2+/v6.1+ installed and navigate to your preferred working directory in the terminal

yarn create nuxt-app nuxtjs-image-sprites
# OR
npx create-nuxt-app nuxtjs-image-sprites
# OR
npm init nuxt-app nuxtjs-image-sprites
Code language: PHP (php)

This will result in a set of questions to customize your project. Here are our recommended defaults:

Project name: nuxtjs-image-sprites Programming language: JavaScript Package manager: Yarn UI framework: Tailwind CSS Nuxt.js modules: N/A Linting tools: N/A Testing frameworks: None Rendering mode: Universal (SSR/SSG) Deployment target: Server (Node.js hosting) Development tools: N/A What is your Github username? <your-github-username> Version control system: Git

Once complete, you may run the project on http://localhost:3000

cd nuxtjs-image-sprites

yarn dev
# OR
npm run dev
Code language: PHP (php)

Cloudinary makes generating the image sprite a very easy process. You simply need to replace the <cloud_name> with your Cloudinary cloud name.

https://res.cloudinary.com/<cloud_name>/image/sprite/nis-cartoons.png

The generated image sprite should be similar to this one.

Image Sprite

Let us first store our images in our page state for reference.

// pages/index.vue
<script>
export default {
  data(){
    return {
      images:[
        {
          class: 'cartoon',
          credit: 'Cartoon icons created by wanicon - Flaticon',
          link: 'https://www.flaticon.com/free-icons/cartoon'
        },
        {
          class: 'chick',
          credit: 'Cartoon icons created by surang - Flaticon',
          link: 'https://www.flaticon.com/free-icons/cartoon'
        },
        {
          class: 'comic_book',
          credit: 'Cartoon icons created by Freepik - Flaticon',
          link: 'https://www.flaticon.com/free-icons/cartoon'
        },
        {
          class: 'leonardo',
          credit: 'Cute icons created by Smashicons - Flaticon',
          link: 'https://www.flaticon.com/free-icons/cute'
        },
        {
          class: 'mushrooms',
          credit: 'Mushroom icons created by Rabbixcons - Flaticon',
          link: 'https://www.flaticon.com/free-icons/mushroom'
        },
      ]
    }
  }
}
</script>
Code language: HTML, XML (xml)

As visible above, we store the class of our images. This is because we will use CSS to display our images. Let us generate the CSS we are going to use.

/* pages/index.vue */
<style>
.cartoon, .chick, .comic_book, .leonardo , .mushrooms {
  background: url('//res.cloudinary.com/hackit-africa/image/sprite/w_280,c_fit/nis-cartoons.png') no-repeat;
}
.cartoon { background-position: 0px 0px; width: 280px; height: 280px; }
.chick { background-position: 0px -280px; width: 280px; height: 280px; }
.comic_book { background-position: 0px -560px; width: 280px; height: 280px; }
.leonardo { background-position: 0px -840px; width: 280px; height: 280px; }
.mushrooms { background-position: 0px -1120px; width: 280px; height: 280px; }

</style>
Code language: HTML, XML (xml)

As visible in the above CSS code, we add a transformation to our image sprite limiting the width to 280px.

http://res.cloudinary.com/hackit-africa/image/sprite/w_280,c_fit/nis-cartoons.png

For each image, we create a class limiting width and height to 280px as we know the images we use are square-shaped. We change the background-position y-axis position by an offset of 280px per class. This will display different images contained in the image sprite.

Now to display image sprite, we simply need to iterate the images adding the classes.

// pages/index.vue
<template>
    ...
      <div 
        v-for="(image,index) in images"
        :key="index"
      >
        <div>
          <div :class="`${image.class} w-full h-full mx-auto`"></div>
        </div>
        <div>
          <div>
            <h3>
              <a
                :href="image.link" 
                target="_blank"
              >
                {{image.credit}}
              </a>
            </h3>
          </div>
        </div>
      </div>
    ...
</template>
Code language: HTML, XML (xml)

With the above code, we should now have an output similar to this one.

Final sprite output

With the above code, we only load our images once instead of having 5 separate requests being sent to our backend. Because we add the resize and crop transformation, we are even able to add more data savings to our app.

To learn more about image sprites, feel free to review the Cloudinary documentation.

Back to top

Featured Post