Skeleton Loader
A component that displays a loading skeleton while content is being loaded.
<!-- Skeleton Loader -->
<!-- An Alpine.js and Tailwind CSS component by https://pinemix.com -->
<div
x-data="{
// Configuration
objects: {
image: true,
text: true,
list: false,
avatar: false,
},
animated: true,
rounded: 'lg', // '', 'sm', 'md', 'lg', 'xl', 'full'
isLoading: true,
// Content loaded
setLoaded() {
this.isLoading = false;
},
// Get skeleton classes (animation + rounded)
getSkeletonClasses() {
return {
'animate-pulse': this.animated,
'rounded-sm': this.rounded === 'sm',
'rounded-md': this.rounded === 'md',
'rounded-lg': this.rounded === 'lg',
'rounded-xl': this.rounded === 'xl',
'rounded-full': this.rounded === 'full'
};
}
}"
>
<!-- Content Container -->
<div
class="mx-auto flex max-w-sm flex-col gap-6 rounded-lg border border-zinc-200 bg-white p-6 dark:border-zinc-700/75 dark:bg-zinc-900"
>
<!-- Content Loaded -->
<div x-cloak x-show="!isLoading">Your content here..</div>
<!-- END Content Loaded -->
<!-- Skeleton: Image -->
<div x-cloak x-show="objects.image && isLoading">
<div
class="h-48 w-full bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
<!-- END Skeleton: Image -->
<!-- Skeleton: Text -->
<div x-cloak x-show="objects.text && isLoading" class="space-y-4">
<template x-for="line in 4" :key="line">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
:style="line === 4 ? 'width: 75%' : 'width: 100%'"
></div>
</template>
</div>
<!-- END Skeleton: Text -->
<!-- Skeleton: List -->
<div x-cloak x-show="objects.list && isLoading" class="space-y-4">
<template x-for="item in 4" :key="item">
<div class="flex items-center gap-4">
<!-- Avatar -->
<div
class="h-10 w-10 flex-shrink-0 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<!-- Content -->
<div class="grow space-y-2">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 40%"
></div>
<div
class="h-3 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
<!-- Action placeholder -->
<div
class="h-6 w-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
</template>
</div>
<!-- END Skeleton: List -->
<!-- Skeleton: Avatar -->
<div
x-cloak
x-show="objects.avatar && isLoading"
class="flex items-center gap-4"
>
<div
class="size-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<div class="grow space-y-2">
<div
class="h-5 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 50%"
></div>
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
</div>
<!-- END Skeleton: Avatar -->
</div>
</div>
<!-- End Skeleton Loader -->
Image Only
<!-- Skeleton Loader: Image Only -->
<!-- An Alpine.js and Tailwind CSS component by https://pinemix.com -->
<div
x-data="{
// Configuration
objects: {
image: true,
text: false,
list: false,
avatar: false,
},
animated: true,
rounded: 'lg', // '', 'sm', 'md', 'lg', 'xl', 'full'
isLoading: true,
// Content loaded
setLoaded() {
this.isLoading = false;
},
// Get skeleton classes (animation + rounded)
getSkeletonClasses() {
return {
'animate-pulse': this.animated,
'rounded-sm': this.rounded === 'sm',
'rounded-md': this.rounded === 'md',
'rounded-lg': this.rounded === 'lg',
'rounded-xl': this.rounded === 'xl',
'rounded-full': this.rounded === 'full'
};
}
}"
>
<!-- Content Container -->
<div
class="mx-auto flex max-w-sm flex-col gap-6 rounded-lg border border-zinc-200 bg-white p-6 dark:border-zinc-700/75 dark:bg-zinc-900"
>
<!-- Content Loaded -->
<div x-cloak x-show="!isLoading">Your content here..</div>
<!-- END Content Loaded -->
<!-- Skeleton: Image -->
<div x-cloak x-show="objects.image && isLoading">
<div
class="h-48 w-full bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
<!-- END Skeleton: Image -->
<!-- Skeleton: Text -->
<div x-cloak x-show="objects.text && isLoading" class="space-y-4">
<template x-for="line in 4" :key="line">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
:style="line === 4 ? 'width: 75%' : 'width: 100%'"
></div>
</template>
</div>
<!-- END Skeleton: Text -->
<!-- Skeleton: List -->
<div x-cloak x-show="objects.list && isLoading" class="space-y-4">
<template x-for="item in 4" :key="item">
<div class="flex items-center gap-4">
<!-- Avatar -->
<div
class="h-10 w-10 flex-shrink-0 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<!-- Content -->
<div class="grow space-y-2">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 40%"
></div>
<div
class="h-3 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
<!-- Action placeholder -->
<div
class="h-6 w-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
</template>
</div>
<!-- END Skeleton: List -->
<!-- Skeleton: Avatar -->
<div
x-cloak
x-show="objects.avatar && isLoading"
class="flex items-center gap-4"
>
<div
class="size-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<div class="grow space-y-2">
<div
class="h-5 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 50%"
></div>
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
</div>
<!-- END Skeleton: Avatar -->
</div>
</div>
<!-- End Skeleton Loader: Image Only -->
Text Only
<!-- Skeleton Loader: Text Only -->
<!-- An Alpine.js and Tailwind CSS component by https://pinemix.com -->
<div
x-data="{
// Configuration
objects: {
image: false,
text: true,
list: false,
avatar: false,
},
animated: true,
rounded: 'lg', // '', 'sm', 'md', 'lg', 'xl', 'full'
isLoading: true,
// Content loaded
setLoaded() {
this.isLoading = false;
},
// Get skeleton classes (animation + rounded)
getSkeletonClasses() {
return {
'animate-pulse': this.animated,
'rounded-sm': this.rounded === 'sm',
'rounded-md': this.rounded === 'md',
'rounded-lg': this.rounded === 'lg',
'rounded-xl': this.rounded === 'xl',
'rounded-full': this.rounded === 'full'
};
}
}"
>
<!-- Content Container -->
<div
class="mx-auto flex max-w-sm flex-col gap-6 rounded-lg border border-zinc-200 bg-white p-6 dark:border-zinc-700/75 dark:bg-zinc-900"
>
<!-- Content Loaded -->
<div x-cloak x-show="!isLoading">Your content here..</div>
<!-- END Content Loaded -->
<!-- Skeleton: Image -->
<div x-cloak x-show="objects.image && isLoading">
<div
class="h-48 w-full bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
<!-- END Skeleton: Image -->
<!-- Skeleton: Text -->
<div x-cloak x-show="objects.text && isLoading" class="space-y-4">
<template x-for="line in 4" :key="line">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
:style="line === 4 ? 'width: 75%' : 'width: 100%'"
></div>
</template>
</div>
<!-- END Skeleton: Text -->
<!-- Skeleton: List -->
<div x-cloak x-show="objects.list && isLoading" class="space-y-4">
<template x-for="item in 4" :key="item">
<div class="flex items-center gap-4">
<!-- Avatar -->
<div
class="h-10 w-10 flex-shrink-0 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<!-- Content -->
<div class="grow space-y-2">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 40%"
></div>
<div
class="h-3 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
<!-- Action placeholder -->
<div
class="h-6 w-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
</template>
</div>
<!-- END Skeleton: List -->
<!-- Skeleton: Avatar -->
<div
x-cloak
x-show="objects.avatar && isLoading"
class="flex items-center gap-4"
>
<div
class="size-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<div class="grow space-y-2">
<div
class="h-5 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 50%"
></div>
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
</div>
<!-- END Skeleton: Avatar -->
</div>
</div>
<!-- End Skeleton Loader: Text Only -->
List Only
<!-- Skeleton Loader: List Only -->
<!-- An Alpine.js and Tailwind CSS component by https://pinemix.com -->
<div
x-data="{
// Configuration
objects: {
image: false,
text: false,
list: true,
avatar: false,
},
animated: true,
rounded: 'lg', // '', 'sm', 'md', 'lg', 'xl', 'full'
isLoading: true,
// Content loaded
setLoaded() {
this.isLoading = false;
},
// Get skeleton classes (animation + rounded)
getSkeletonClasses() {
return {
'animate-pulse': this.animated,
'rounded-sm': this.rounded === 'sm',
'rounded-md': this.rounded === 'md',
'rounded-lg': this.rounded === 'lg',
'rounded-xl': this.rounded === 'xl',
'rounded-full': this.rounded === 'full'
};
}
}"
>
<!-- Content Container -->
<div
class="mx-auto flex max-w-sm flex-col gap-6 rounded-lg border border-zinc-200 bg-white p-6 dark:border-zinc-700/75 dark:bg-zinc-900"
>
<!-- Content Loaded -->
<div x-cloak x-show="!isLoading">Your content here..</div>
<!-- END Content Loaded -->
<!-- Skeleton: Image -->
<div x-cloak x-show="objects.image && isLoading">
<div
class="h-48 w-full bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
<!-- END Skeleton: Image -->
<!-- Skeleton: Text -->
<div x-cloak x-show="objects.text && isLoading" class="space-y-4">
<template x-for="line in 4" :key="line">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
:style="line === 4 ? 'width: 75%' : 'width: 100%'"
></div>
</template>
</div>
<!-- END Skeleton: Text -->
<!-- Skeleton: List -->
<div x-cloak x-show="objects.list && isLoading" class="space-y-4">
<template x-for="item in 4" :key="item">
<div class="flex items-center gap-4">
<!-- Avatar -->
<div
class="h-10 w-10 flex-shrink-0 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<!-- Content -->
<div class="grow space-y-2">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 40%"
></div>
<div
class="h-3 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
<!-- Action placeholder -->
<div
class="h-6 w-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
</template>
</div>
<!-- END Skeleton: List -->
<!-- Skeleton: Avatar -->
<div
x-cloak
x-show="objects.avatar && isLoading"
class="flex items-center gap-4"
>
<div
class="size-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<div class="grow space-y-2">
<div
class="h-5 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 50%"
></div>
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
</div>
<!-- END Skeleton: Avatar -->
</div>
</div>
<!-- End Skeleton Loader: List Only -->
Avatar Only
<!-- Skeleton Loader: Avatar Only -->
<!-- An Alpine.js and Tailwind CSS component by https://pinemix.com -->
<div
x-data="{
// Configuration
objects: {
image: false,
text: false,
list: false,
avatar: true,
},
animated: true,
rounded: 'lg', // '', 'sm', 'md', 'lg', 'xl', 'full'
isLoading: true,
// Content loaded
setLoaded() {
this.isLoading = false;
},
// Get skeleton classes (animation + rounded)
getSkeletonClasses() {
return {
'animate-pulse': this.animated,
'rounded-sm': this.rounded === 'sm',
'rounded-md': this.rounded === 'md',
'rounded-lg': this.rounded === 'lg',
'rounded-xl': this.rounded === 'xl',
'rounded-full': this.rounded === 'full'
};
}
}"
>
<!-- Content Container -->
<div
class="mx-auto flex max-w-sm flex-col gap-6 rounded-lg border border-zinc-200 bg-white p-6 dark:border-zinc-700/75 dark:bg-zinc-900"
>
<!-- Content Loaded -->
<div x-cloak x-show="!isLoading">Your content here..</div>
<!-- END Content Loaded -->
<!-- Skeleton: Image -->
<div x-cloak x-show="objects.image && isLoading">
<div
class="h-48 w-full bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
<!-- END Skeleton: Image -->
<!-- Skeleton: Text -->
<div x-cloak x-show="objects.text && isLoading" class="space-y-4">
<template x-for="line in 4" :key="line">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
:style="line === 4 ? 'width: 75%' : 'width: 100%'"
></div>
</template>
</div>
<!-- END Skeleton: Text -->
<!-- Skeleton: List -->
<div x-cloak x-show="objects.list && isLoading" class="space-y-4">
<template x-for="item in 4" :key="item">
<div class="flex items-center gap-4">
<!-- Avatar -->
<div
class="h-10 w-10 flex-shrink-0 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<!-- Content -->
<div class="grow space-y-2">
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 40%"
></div>
<div
class="h-3 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
<!-- Action placeholder -->
<div
class="h-6 w-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
></div>
</div>
</template>
</div>
<!-- END Skeleton: List -->
<!-- Skeleton: Avatar -->
<div
x-cloak
x-show="objects.avatar && isLoading"
class="flex items-center gap-4"
>
<div
class="size-16 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="{
...getSkeletonClasses(),
'rounded-full': rounded === 'full' || true
}"
></div>
<div class="grow space-y-2">
<div
class="h-5 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 50%"
></div>
<div
class="h-4 bg-zinc-200 dark:bg-zinc-700"
x-bind:class="getSkeletonClasses()"
style="width: 75%"
></div>
</div>
</div>
<!-- END Skeleton: Avatar -->
</div>
</div>
<!-- End Skeleton Loader: Avatar Only -->
Props
The available data properties for this component.
Property | Default | Description |
---|---|---|
objects | { image: true, text: true, list: false, avatar: false } | An object array to populate the available objects in the skeleton loader. Values for 'image', 'text', 'list' and 'avatar' attributes have to be provided (true or false) |
animated | true | Sets the skeleton loader animation |
rounded | lg | Sets the skeleton loader rounded size, available options are 'sm', 'md', 'lg', 'xl' and 'full' |
isLoading | true | Sets the skeleton loader visibility |
Designed with
Tailkit
Featuring 1,900+ Tailwind CSS code snippets for HTML, React, Vue.js and Alpine.js projects
Unlock 15+ free templates
Join our pixelcave newsletter to get them now & we'll also keep you updated about any new Pinemix components!