How to make a skeleton loader using Vue

Andres Felipe Abello
May 14

In this tutorial, I am going to guide you through how to make a Skeleton loader using Vue js, CSS, and HTML. The main benefits of learning how to make a skeleton loader are that you will be able to change it however you want, for different kinds of content, your users will know that something is loading, your app or website will look more professional, and appear to be faster. 

Moreover, Skeleton screens offer a better experience by reducing loading-time frustration. Instead of wait times, users have to focus on progress, it creates an illusion that information will be incrementally displayed on the screen. Wheater you are trying to improve SEO on your website or engage your user on your app, a skeleton loader can help you get there. All of the big companies use it, so we know that it is a proven technique.

Let's get to it, you can watch the video and then look at the code. I will walk you through each block, so you can have a better understanding of how everything works. 

Create a component

In my case I name it SkeletonLoader.vue, you can name it however you want. I will be adding HTML, Javascript, and CSS inside this component. First, this is a simple HTML structure using Bootstrap 4 to create our placeholder. In this case I start with a col-xl-4 which will give a 4 column div inside the 12 column bootstrap grid, I will add an addition two columns, but right now let's focus on what is going on here. 

Inside col-xl-4, you will see the placeholder, this is the wrapper for skeleton loader, the square and lines are within the placeholder, this will make the structure and you want to make this as close as possible to the content that will be loaded. Next, I will give you examples with a square, rectangle, and circle. You can make as many shapes as you want. These are inside the two col-xl-4 which will give you a total of 1 row in the 12 column grid. As a result, you will see a row with three columns with our skeleton placeholders.
You can add as many lines as you want and different shapes if that is the case. What you want here is the most accurate representation of what the loaded content will look like. Next we will go over the script. This will register our Vue component and give us the right state and methods to work with our component. 

Register the Component

Now, we are going to register the component with the name of Skeleton Loader, then we are going to return the data which is the state of the component, In this case, we return loading: true. If loading is true then it will show our elements if not then it will hide them using display:none; 

Next, we are going to register the method setLoadingState(), this will simulate our call to the server, this is where you are going to load data within your component, you can also, use the loading as a prop and then pass it from the parent which is where you are going to load the data.

In this case, this component will call the setLoadingState() from its mounted() hook, so once the component loads it will call our method, the method changes the loading state after 5 seconds to demonstrate that the elements will hide. I will give you both examples so that you can implement it how you want. 

props: {
  loading: {
    type: Boolean,
    default: false,
    required: true


Finally, we will go over the CSS, in this case, I am using SCSS to build it. As you can see I am building the basic shapes we are using .square, .circle, .line, and .rectangle, you can create as many as you want. Then I am adding the two animations which will make it feel like its loading. I am using pulse and wave animations.

For pulse animation: pulse 1s infinite ease-in-out; -webkit-animation: pulse 1s infinite ease-in-out; will attach run infinitely and then attach the pulse animation which is registered after. 

For Wave animation: wave 1s infinite linear forwards; -webkit-animation: wave 1s infinite linear forwards; background: #f6f7f8; background: linear-gradient(to right, #eeeeee 8%, #dddddd 18%, #eeeeee 33%); background-size: 800px 104px;

Next I will register the keyframes, for it there is a start at 0, a middle at 50% and and end at 100% for pulse, this will change the opacity on the color to create the pulsing animation that runs from the .pulse selector. Wave only has a start at 0 and an end at 100% which moves the background position this based on the background size state about of 800px. 


A skeleton loader is a great UI tool for you to let your users know that something is loading. By implementing it, you are giving the perception that the application is faster than what it is. This will help your users be more engaged and improve your SEO. Your code will now look something like any of the two examples, first with everything inside one component and second with a property in case you have a parent component. 

Andres Felipe Abello
May 14