<script setup lang="ts">
const users = ref([])
const loading = ref(true)
onMounted(async () => {
users.value = await fetchUsers()
loading.value = false
})
</script>
<template>
<div v-if="loading" class="skeleton-list">
<div
v-for="n in 5"
:key="n"
class="skeleton-card"
/>
</div>
<UserCard
v-else
v-for="user in users"
:key="user.id"
:user="user"
/>
</template>
<style scoped>
.skeleton-card {
height: 120px;
border-radius: 12px;
margin-bottom: 16px;
}
</style>
We fetch users, but when the fetch is in progress we display the same hard coded number of loaders/skeletons. When the users are loaded there is no layout shift as it occupies the same space improving perceived performance and User Experience.
If we don't know how many results there will be, we have to assume some number but it is still better than not having skeletons at all :)
Many apps still use simple spinners or text/icon loaders like:
<div>Loading...</div>
But modern UX usually prefers Skeleton loaders because they mimic final layout, reduce layout shift, and improve perceived speed.
🧪 Best Practices
- Prefer skeleton loaders over tiny spinners
- Reserve space before content loads
- Keep loading and final layouts similar
- Always define image dimensions
- Avoid injecting large content suddenly
- Test CLS using Lighthouse or Core Web Vitals tools
- Think about perceived performance — not just raw speed
📖 Learn more
If you would like to learn more about Vue, Nuxt, JavaScript or other useful technologies, checkout VueSchool by clicking this link or by clicking the image below:
Vue School Link
It covers most important concepts while building modern Vue or Nuxt applications that can help you in your daily work or side projects 😉
🧪 Advance skills
A certification boosts your skills, builds credibility, and opens doors to new opportunities. Whether you're advancing your career or switching paths, it's a smart step toward success.
Check out Certificates.dev by clicking this link or by clicking the image below:
Certificates.dev Link
Invest in yourself—get certified in Vue.js, JavaScript, Nuxt, Angular, React, and more!
✅ Summary
Loaders are much more important than most developers realize.
In this article, you learned:
- What Cumulative Layout Shift (CLS) is
- Why poor loading states hurt UX
- How skeleton loaders improve perceived performance
- How to avoid layout jumping in Vue and other frameworks
- Best practices for stable, responsive interfaces
Fast apps are great.
But apps that feel smooth and stable are what users truly remember.
Take care!
And happy coding as always 🖥️