DEV Community

Cover image for 🎊 You don't need SVG! Creating animated loaders for content with Tailwind CSS
Vic Shóstak
Vic Shóstak

Posted on • Edited on

🎊 You don't need SVG! Creating animated loaders for content with Tailwind CSS

Introduction

Hi, DEV friends! 😁

Today we'll talk about how to improve the UX of your project by several times by implementing just a content loader in the right format.

It's not some kind of SVG or JavaScript “magic”, it's just pure HTML, Tailwind CSS built-in classes and some gradient colors.

🔥 Disclaimer: No one is going to CANCEL the use of technology (SVG) on a global scale. Only on a project scale where the Tailwind CSS framework is ALREADY used. If you don't use this framework in your project, you may find the information provided less useful.

Here we go! 🚀

📝 Table of contents

The main advantage

As you have already guessed from the title, this is a purely CSS solution using the Tailwind CSS v2.2.x framework. And the main advantage of this approach is that in fact it is just plain HTML and CSS, which is loaded very first in the user's browser.

There's no “jagged” user experience (UX), where they first see a blank page, then a JavaScript or SVG loader flashes and content shown immediately.

🔥 Attention! UX improvement works should be the highest priority for every frontend developer! Especially when customer loyalty to the business and the brand as a whole depends on it.

↑ Table of contents

Explanations of the code

In order not to dwell later on the explanation of some general points in the code, I decided to tell at once about the classes that will be used in the layout of the loaders.

The first of these is the gradient class itself .gradient-purple-pink-red:

/* ./src/assets/css/tailwind.css */

/* ... */

@layer utilities {

  /* Gradient color */
  .gradient-purple-pink-red {
    @apply bg-gradient-to-r;
    @apply from-purple-400 via-pink-500 to-red-500;
  }

  /* ... */
}
Enter fullscreen mode Exit fullscreen mode

I'm used to defining groups of properties, like colors or gradients, in the @layer utilities {} layer. E.g., “I add a utility to change the color of an element”.

😉 By the way! It would be interesting to read in the comments how you work with @layer and @apply in your Tailwind CSS projects.

Okay. Let's take a closer look at all the properties:

  • bg-gradient-to-{direction} this property indicates the direction of the gradient (in our case r equals to right);
  • from-{color} this property indicates the first (start) color of the gradient (in our case purple with weight 400);
  • via-{color} this property indicates the second (middle) color of the gradient (in our case pink with weight 500);
  • to-{color} this property indicates the third (end) color of the gradient (in our case red with weight 500);

The second class I would like to show is .animate-pulse (which is a standard Tailwind class). Just this class does the magic animation that turns a simple gradient background into a loader:

/* Animation keyframe */
@keyframes pulse {
    50% {
        opacity: .5;
    }
}

/* Class for element with animation */
.animate-pulse {
    animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
Enter fullscreen mode Exit fullscreen mode

↑ Table of contents

A simple content loader

The most common loader you'll find on websites is a content loader. It is usually enabled after navigating to a page that has not yet pulled content from the backend.

A good UX is to show the loader in full compliance with the structure of the content to be loaded. Thus, the user does not have the feeling that he got somewhere wrong. He will have a visual placeholder instead of content that will be displayed to him in a couple of moments.

The final version of our loader will look like this:

content loader

It seems simple, right? Lines are just div containers with a given height and width… But how do you make a circular element without SVG? Easy! Add any block element symmetric dimensions and the built-in .rounded-full class.

Now let's put it all together and build the content loader:

🎯 Note: Please follow comments in the code!

<div class="animate-pulse">
  <!-- First line heading -->
  <div class="mt-8 h-4 gradient-purple-pink-red rounded-full w-4/5"></div>
  <div class="py-6">
    <!-- Text block 1 -->
    <div class="my-4">
      <div class="h-3 my-3 gradient-purple-pink-red rounded-full w-4/6"></div>
      <div class="h-3 my-3 gradient-purple-pink-red rounded-full w-3/6"></div>
      <div class="h-3 my-3 gradient-purple-pink-red rounded-full w-2/6"></div>
    </div>
    <!-- Text block 2 -->
    <div class="my-6">
      <div class="h-3 my-3 gradient-purple-pink-red rounded-full w-5/6"></div>
      <div class="h-3 my-3 gradient-purple-pink-red rounded-full w-4/6"></div>
      <div class="h-3 my-3 gradient-purple-pink-red rounded-full w-2/6"></div>
    </div>
    <!-- User card (avatar + username) -->
    <div class="my-6 flex items-center space-x-3">
      <div class="h-10 w-10 gradient-purple-pink-red rounded-full"></div>
      <div class="h-3 gradient-purple-pink-red rounded-full w-1/12"></div>
      <div class="h-3 gradient-purple-pink-red rounded-full w-1/6"></div>
    </div>
    <!-- Post data -->
    <div class="my-6 h-3 gradient-purple-pink-red rounded-full w-1/6"></div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

📺 Live demo: https://play.tailwindcss.com/a7Pp2l65hF

This example illustrates perfectly how simple and flexible it is to customize the loader to your needs. To consolidate the material, let's look at the following loader.

↑ Table of contents

Loader for the card in the list

Let's move on. Another kind of uploader you've seen, for example, when scrolling through your Instagram feed or your favorite social network.

Such techniques help high-loaded web services improve the user experience while the data in the feed is being loaded.

Let's take the feed from the projects on some web service as an example:

card loader

This loader looks maximally organic and doesn't make you want to close the page, does it? This is achieved because the loader almost exactly repeats the content of the card (we talked about this earlier).

All right, let's implement this loader:

<div class="animate-pulse">
  <!-- Head line -->
  <div class="gradient-purple-pink-red h-6 rounded-t-3xl"></div>
  <div class="py-4 px-6">
    <!-- User card (avatar + username) -->
    <div class="flex items-center space-x-2">
      <div class="h-7 w-7 gradient-purple-pink-red rounded-full"></div>
      <div class="h-3 gradient-purple-pink-red rounded-full w-1/3"></div>
    </div>
    <!-- Text block -->
    <div class="my-6">
      <!-- Heading -->
      <div class="h-5 gradient-purple-pink-red rounded-full w-3/4"></div>
      <!-- Description -->
      <div class="my-4">
        <div class="h-3 my-2 gradient-purple-pink-red rounded-full w-full"></div>
        <div class="h-3 my-2 gradient-purple-pink-red rounded-full w-5/6"></div>
        <div class="h-3 my-2 gradient-purple-pink-red rounded-full w-4/6"></div>
        <div class="h-3 my-2 gradient-purple-pink-red rounded-full w-5/6"></div>
        <div class="h-3 my-2 gradient-purple-pink-red rounded-full w-3/6"></div>
        <div class="h-3 my-2 gradient-purple-pink-red rounded-full w-2/6"></div>
      </div>
    </div>
    <div class="my-4">
      <!-- Button -->
      <div class="h-11 gradient-purple-pink-red rounded-lg w-full"></div>
      <!-- Post data + time -->
      <div class="h-3 my-4 mx-auto gradient-purple-pink-red rounded-full w-1/2"></div>
    </div>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

📺 Live demo: https://play.tailwindcss.com/msRdcHcKne

Again there is nothing complicated, thanks to the built-in Tailwind CSS classes, we can do any block variations in a matter of seconds.

↑ Table of contents

Conclusion

Use your forms and styles for the loader to improve the UX of your project. It's simple, but believe me (in my 12+ years of the practical experience), will bring a lot of positive feedback.

Share your loaders through the Tailwind Play service in the comments!

And think of the users first! 👍

↑ Table of contents

Photos and videos by

P.S.

If you want more articles (like this) on this blog, then post a comment below and subscribe to me. Thanks! 😻

❗️ You can support me on Boosty, both on a permanent and on a one-time basis. All proceeds from this way will go to support my OSS projects and will energize me to create new products and articles for the community.

support me on Boosty

And of course, you can help me make developers' lives even better! Just connect to one of my projects as a contributor. It's easy!

My main projects that need your help (and stars) 👇

  • 🔥 gowebly: A next-generation CLI tool that makes it easy to create amazing web applications with Go on the backend, using htmx, hyperscript or Alpine.js and the most popular CSS frameworks on the frontend.
  • create-go-app: Create a new production-ready project with Go backend, frontend and deploy automation by running one CLI command.

Other my small projects: yatr, gosl, json2csv, csv2api.

Top comments (12)

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️ • Edited

...so what's the advantage over using SVG instead?

While this isn't really the best use-case for SVG, as the loader still ultimately adheres to the box-model, there's still nothing wrong with using SVG to build it. It certainly won't be slower than HTML+CSS, and might even be faster if your CSS loads from a remote file.


EDIT: Actually, SVG is the better option here: Not only will you need less of it, you will also need even less if you intend to repeat your loader several times thanks to <use> elements; so you can reduce your file-size by quite a bit.


For comparison: same thing with SVG, sans the animation because that's trivial anyway.

Collapse
 
koddr profile image
Vic Shóstak • Edited

Hi,

Yes, if you use inline SVG, it will be just as fast as my version.

But in this article I specifically mentioned a variant of SVG loaders, which I met in a huge number of projects on the Internet. Namely, a file like ./src/assets/images/loader.svg, which is not even on the CDN, and not optimized via SVGO... That's why such a provocative headline was born. :)

Compared to this approach, a bunch of Tailwind CSS + HTML will be much faster, since it's the markup and CSS have priority over loading, and only then everything else (as far as I remember the spec).

The main point I wanted to make is that you don't have to use SVG at all, if wonderful Tailwind provides all tools to implement loaders (of any complexity and appearance) through plain CSS. That's all.

EDIT: I'm not even talking about different solutions like this. Where they suggest installing additional dependencies in the project, for the sake of creating what Tailwind can do out of the box with just a few CSS classes. Or your inline SVG option.

Collapse
 
hoangvu12 profile image
Vu Nguyen

Uh I've been doing in this in most of my projects..

I just create a component that take children and add pulse animation and background color to it and it works.

I've tried SVG version, I need to adjust height, width also x and y (or maybe i did something wrong). It was really inconvenience.

With this, all I need to do is use width and height.

Nice article by the way!

Collapse
 
koddr profile image
Vic Shóstak

Hi,

Great example of a solution to the problem I bring up in this article! Thanks.

Collapse
 
divyeshkamalanaban profile image
Divyesh Kamalanaban • Edited

You can even create these graphics using normal CSS. Why Tailwind though? A little bit of JS can help you avoid Tailwind, maybe that will reduce load times?

Collapse
 
koddr profile image
Vic Shóstak

Hi,

Of course it is. But if you have a design system already using this CSS framework in the frontend team, why not use the built-in tools in Tailwind so you don't have to write the code yourself? ;)

Speeding up development is also a win.

Collapse
 
divyeshkamalanaban profile image
Divyesh Kamalanaban

Seems justified from your aspect. But making your own code gives you more flexibility. Either way, we win.

Thread Thread
 
koddr profile image
Vic Shóstak

As I answered in this comment, the purpose of the article was to show that you don't have to use loaders everywhere in SVG files or when plugging in JS dependencies to do the same via Tailwind (especially if it is ALREADY used in the project).

It's not like I'm saying anywhere in the article, "hey folks, install Tailwind to make the loaders animation". No! There was no such thing in the article. Even in the title and description I immediately pointed out that it was Tailwind's built-in features I was going to talk about.

Further, in the article I wanted to share my experience. I do a lot of reviews of different web projects (mostly on UX) and I often see a picture like this:

  • Files like loader-for-X.svg can be very numerous in the project for each type of content loading (I counted over 25 in one project, for example);
  • They are not optimized through SVGO;
  • The size of such files is many times greater than it could be;

Hence this article was born. I in no way meant to hurt the feelings of the true SVG developers (can I call them that?) who move this wonderful technology forward.

Yes, I understand that the flexibility to write your own solutions would be higher, but not many project managers are willing to wait for a frontend developer to implement such a thing on pure SVG or especially JavaScript (which you will then have to maintain). Time-to-market in 2k21 is a king.

Thread Thread
 
divyeshkamalanaban profile image
Divyesh Kamalanaban

I never knew there were these many hurdles in using SVGs. But, I might always use CSS (Normal CSS or Tailwind) than SVGs from now on. Anyways, thanks for the info!

Collapse
 
eshimischi profile image
eshimischi

Over-complexity. I have nothing against using CSS Frameworks, but we have SVG, period.

Collapse
 
koddr profile image
Vic Shóstak

Hi,

As I answered above in the comments (twice) here and here, the article was written from the perspective that Tailwind CSS is ALREADY in your project.

So why write something by hand from scratch if you ALREADY use a framework where this functionality is ALREADY implemented out of the box with just two classes?

That's all, there was no further purpose to this article.

OK. I will add a warning about this at the beginning of the article, so that readers immediately understand that no one is going to CANCEL their favorite technology (SVG) on a global scale. Only on a project scale, where Tailwind is ALREADY used.

Some comments may only be visible to logged-in visitors. Sign in to view all comments.