Optimizing image loading using sprites in NuxtJS

Eugene Musebe

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.

Codesandbox

The completed project is available on Codesandbox.

You can find the full codebase on my Github

Cloudinary setup

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:

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

Nuxt.Js Setup

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

1yarn create nuxt-app nuxtjs-image-sprites
2# OR
3npx create-nuxt-app nuxtjs-image-sprites
4# OR
5npm init nuxt-app nuxtjs-image-sprites

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

1cd nuxtjs-image-sprites
2
3yarn dev
4# OR
5npm run dev

Generating the image sprite

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

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

The generated image sprite should be similar to this one.

Using the image sprite

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

1// pages/index.vue
2<script>
3export default {
4 data(){
5 return {
6 images:[
7 {
8 class: 'cartoon',
9 credit: 'Cartoon icons created by wanicon - Flaticon',
10 link: 'https://www.flaticon.com/free-icons/cartoon'
11 },
12 {
13 class: 'chick',
14 credit: 'Cartoon icons created by surang - Flaticon',
15 link: 'https://www.flaticon.com/free-icons/cartoon'
16 },
17 {
18 class: 'comic_book',
19 credit: 'Cartoon icons created by Freepik - Flaticon',
20 link: 'https://www.flaticon.com/free-icons/cartoon'
21 },
22 {
23 class: 'leonardo',
24 credit: 'Cute icons created by Smashicons - Flaticon',
25 link: 'https://www.flaticon.com/free-icons/cute'
26 },
27 {
28 class: 'mushrooms',
29 credit: 'Mushroom icons created by Rabbixcons - Flaticon',
30 link: 'https://www.flaticon.com/free-icons/mushroom'
31 },
32 ]
33 }
34 }
35}
36</script>

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.

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

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.

1// pages/index.vue
2<template>
3 ...
4 <div
5 v-for="(image,index) in images"
6 :key="index"
7 >
8 <div>
9 <div :class="`${image.class} w-full h-full mx-auto`"></div>
10 </div>
11 <div>
12 <div>
13 <h3>
14 <a
15 :href="image.link"
16 target="_blank"
17 >
18 {{image.credit}}
19 </a>
20 </h3>
21 </div>
22 </div>
23 </div>
24 ...
25</template>

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

Conclusion

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.

Eugene Musebe

Software Developer

I’m a full-stack software developer, content creator, and tech community builder based in Nairobi, Kenya. I am addicted to learning new technologies and loves working with like-minded people.