Skip to content

Instantly share code, notes, and snippets.

@manutheblacker
Forked from andresabello/SkeletonLoader.vue
Created November 25, 2022 13:28
Show Gist options
  • Save manutheblacker/0b9145d51438e004c41a635ae69732b5 to your computer and use it in GitHub Desktop.
Save manutheblacker/0b9145d51438e004c41a635ae69732b5 to your computer and use it in GitHub Desktop.
A skeleton loader for Vue JS. You will need to implement the setLoadingState. This one is just an example that hides the element after 5 seconds.
<template>
<div class="container">
<div class="row" v-show="loading">
<div class="col-xl-4 pt-5">
<div class="placeholder wave">
<div class="square"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
<div class="col-xl-4 pt-5">
<div class="placeholder wave">
<div class="circle"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
<div class="col-xl-4 pt-5">
<div class="placeholder wave">
<div class="rectangle"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SkeletonLoader',
data () {
return {
loading: true
}
},
mounted(){
setTimeout(() => {
this.setLoadingState(false)
}, 5000)
},
methods: {
setLoadingState (value) {
this.loading = value
}
}
}
</script>
<style scoped lang="scss">
.placeholder {
margin: 15px;
padding: 10px;
border-radius: 5px;
&.pulse div {
animation: pulse 1s infinite ease-in-out;
-webkit-animation: pulse 1s infinite ease-in-out;
}
&.wave div {
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;
}
div {
background: #E8E8E8;
}
.square {
float: left;
width: 30px;
height: 30px;
margin: 0 0 10px;
}
.rectangle {
float: left;
width: 40px;
height: 30px;
margin: 0 0 10px;
}
.line {
height: 12px;
margin: 0 0 10px 50px;
width: 70%;
}
.circle {
float: left;
width: 40px;
height: 40px;
margin: 0 15px 10px 0;
border-radius: 40px;
}
}
@keyframes pulse {
0% {
background-color: rgba(165, 165, 165, .1);
}
50% {
background-color: rgba(165, 165, 165, .3);
}
100% {
background-color: rgba(165, 165, 165, .1);
}
}
@-webkit-keyframes pulse {
0% {
background-color: rgba(165, 165, 165, .1);
}
50% {
background-color: rgba(165, 165, 165, .3);
}
100% {
background-color: rgba(165, 165, 165, .1);
}
}
@keyframes wave {
0% {
background-position: -468px 0
}
100% {
background-position: 468px 0
}
}
@-webkit-keyframes wave {
0% {
background-position: -468px 0
}
100% {
background-position: 468px 0
}
}
</style>
<template>
<div class="container">
<div class="row" v-show="loading">
<div class="col-xl-4 pt-5">
<div class="placeholder wave">
<div class="square"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
<div class="col-xl-4 pt-5">
<div class="placeholder wave">
<div class="circle"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
<div class="col-xl-4 pt-5">
<div class="placeholder wave">
<div class="rectangle"></div>
<div class="line"></div>
<div class="line"></div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SkeletonLoader',
props: {
loading: {
type: Boolean,
default: false,
required: true
}
}
}
</script>
<style scoped lang="scss">
.placeholder {
margin: 15px;
padding: 10px;
border-radius: 5px;
&.pulse div {
animation: pulse 1s infinite ease-in-out;
-webkit-animation: pulse 1s infinite ease-in-out;
}
&.wave div {
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;
}
div {
background: #E8E8E8;
}
.square {
float: left;
width: 30px;
height: 30px;
margin: 0 0 10px;
}
.rectangle {
float: left;
width: 40px;
height: 30px;
margin: 0 0 10px;
}
.line {
height: 12px;
margin: 0 0 10px 50px;
width: 70%;
}
.circle {
float: left;
width: 40px;
height: 40px;
margin: 0 15px 10px 0;
border-radius: 40px;
}
}
@keyframes pulse {
0% {
background-color: rgba(165, 165, 165, .1);
}
50% {
background-color: rgba(165, 165, 165, .3);
}
100% {
background-color: rgba(165, 165, 165, .1);
}
}
@-webkit-keyframes pulse {
0% {
background-color: rgba(165, 165, 165, .1);
}
50% {
background-color: rgba(165, 165, 165, .3);
}
100% {
background-color: rgba(165, 165, 165, .1);
}
}
@keyframes wave {
0% {
background-position: -468px 0
}
100% {
background-position: 468px 0
}
}
@-webkit-keyframes wave {
0% {
background-position: -468px 0
}
100% {
background-position: 468px 0
}
}
</style>
<template>
<skeleton-loader :loading="loading"></skeleton-loader>
</template>
<script>
import SkeletonLoader from './SkeletonLoader'
export default {
name: 'ParentSkeleton',
data () {
return {
loading: false
}
},
mounted () {
setTimeout(() => {
this.setLoadingState(false)
}, 5000)
},
methods: {
setLoadingState (value) {
this.loading = value
}
},
components: { SkeletonLoader }
}
</script>
<style scoped>
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment