Skeleton
Skeleton is a placeholder to show a loading state and the expected shape of a component.
Import
import { AvSkeletonComponent } from '@avesra/angular';Usage
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-basic-demo',
imports: [AvSkeletonComponent],
host: { class: 'block' },
template: `<div class="w-[250px] space-y-5 rounded-lg bg-transparent p-4 shadow-surface">
<div av-skeleton class="h-32 rounded-lg"></div>
<div class="space-y-3">
<div av-skeleton class="h-3 w-3/5 rounded-lg"></div>
<div av-skeleton class="h-3 w-4/5 rounded-lg"></div>
<div av-skeleton class="h-3 w-2/5 rounded-lg"></div>
</div>
</div>`,
})
export class SkeletonBasicDemo {}Anatomy
Use the div[av-skeleton] attribute selector and size or shape the placeholder with Tailwind utility classes. Optional animation-type overrides the theme default (--av-skeleton-animation).
<div av-skeleton class="h-20 w-32 rounded-full"></div>
<!-- Animation types -->
<div av-skeleton animation-type="shimmer" class="h-10 rounded-lg"></div>
<div av-skeleton animation-type="pulse" class="h-10 rounded-lg"></div>
<div av-skeleton animation-type="none" class="h-10 rounded-lg"></div>
<!-- Synchronized shimmer over a group -->
<div class="av-skeleton--shimmer relative grid grid-cols-3 gap-4 overflow-hidden rounded-xl">
<div av-skeleton animation-type="none" class="h-24 rounded-xl"></div>
<div av-skeleton animation-type="none" class="h-24 rounded-xl"></div>
<div av-skeleton animation-type="none" class="h-24 rounded-xl"></div>
</div>Text Content
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-text-content-demo',
imports: [AvSkeletonComponent],
host: { class: 'block w-full max-w-md' },
template: `<div class="w-full space-y-3">
<div av-skeleton class="h-4 w-full rounded"></div>
<div av-skeleton class="h-4 w-5/6 rounded"></div>
<div av-skeleton class="h-4 w-4/6 rounded"></div>
<div av-skeleton class="h-4 w-full rounded"></div>
<div av-skeleton class="h-4 w-3/6 rounded"></div>
</div>`,
})
export class SkeletonTextContentDemo {}User Profile
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-user-profile-demo',
imports: [AvSkeletonComponent],
host: { class: 'block w-full max-w-sm' },
template: `<div class="flex w-full items-center gap-3">
<div av-skeleton class="h-10 w-10 shrink-0 rounded-full"></div>
<div class="flex-1 space-y-2">
<div av-skeleton class="h-3 w-36 rounded-lg"></div>
<div av-skeleton class="h-3 w-24 rounded-lg"></div>
</div>
</div>`,
})
export class SkeletonUserProfileDemo {}List Items
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-list-demo',
imports: [AvSkeletonComponent],
host: { class: 'block w-full max-w-sm' },
template: `<div class="w-full space-y-4">
@for (item of items; track item) {
<div class="flex items-center gap-3">
<div av-skeleton class="h-10 w-10 shrink-0 rounded-lg"></div>
<div class="flex-1 space-y-2">
<div av-skeleton class="h-3 w-full rounded"></div>
<div av-skeleton class="h-3 w-4/5 rounded"></div>
</div>
</div>
}
</div>`,
})
export class SkeletonListDemo {
readonly items = [0, 1, 2];
}Grid
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-grid-demo',
imports: [AvSkeletonComponent],
host: { class: 'block w-full max-w-xl' },
template: `<div class="grid w-full grid-cols-3 gap-4">
<div av-skeleton class="h-24 rounded-xl"></div>
<div av-skeleton class="h-24 rounded-xl"></div>
<div av-skeleton class="h-24 rounded-xl"></div>
</div>`,
})
export class SkeletonGridDemo {}Single Shimmer
A synchronized shimmer effect that passes over all skeleton elements at once. Apply the av-skeleton--shimmer class to a parent container and set animation-type="none" on child skeletons.
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-single-shimmer-demo',
imports: [AvSkeletonComponent],
host: { class: 'block w-full max-w-xl' },
template: `<div
class="av-skeleton--shimmer relative grid w-full grid-cols-3 gap-4 overflow-hidden rounded-xl"
>
<div av-skeleton animation-type="none" class="h-24 rounded-xl"></div>
<div av-skeleton animation-type="none" class="h-24 rounded-xl"></div>
<div av-skeleton animation-type="none" class="h-24 rounded-xl"></div>
</div>`,
})
export class SkeletonSingleShimmerDemo {}Animation Types
Shimmer
Pulse
None
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-animation-types-demo',
imports: [AvSkeletonComponent],
host: { class: 'block w-full max-w-xl' },
template: `<div class="grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3">
<div class="space-y-2">
<p class="truncate text-xs text-muted">Shimmer</p>
<div class="space-y-3 rounded-lg bg-transparent p-4 shadow-surface">
<div av-skeleton animation-type="shimmer" class="h-20 rounded-lg"></div>
<div av-skeleton animation-type="shimmer" class="h-3 w-3/5 rounded-lg"></div>
<div av-skeleton animation-type="shimmer" class="h-3 w-4/5 rounded-lg"></div>
</div>
</div>
<div class="space-y-2">
<p class="truncate text-xs text-muted">Pulse</p>
<div class="space-y-3 rounded-lg bg-transparent p-4 shadow-surface">
<div av-skeleton animation-type="pulse" class="h-20 rounded-lg"></div>
<div av-skeleton animation-type="pulse" class="h-3 w-3/5 rounded-lg"></div>
<div av-skeleton animation-type="pulse" class="h-3 w-4/5 rounded-lg"></div>
</div>
</div>
<div class="space-y-2">
<p class="truncate text-xs text-muted">None</p>
<div class="space-y-3 rounded-lg bg-transparent p-4 shadow-surface">
<div av-skeleton animation-type="none" class="h-20 rounded-lg"></div>
<div av-skeleton animation-type="none" class="h-3 w-3/5 rounded-lg"></div>
<div av-skeleton animation-type="none" class="h-3 w-4/5 rounded-lg"></div>
</div>
</div>
</div>`,
})
export class SkeletonAnimationTypesDemo {}Styling
Global Animation Configuration
You can set a default animation type for all Skeleton components by defining the --av-skeleton-animation CSS variable:
/* In your global CSS / theme file */
:root {
/* Possible values: shimmer, pulse, none */
--av-skeleton-animation: pulse;
}
/* You can also set different values for light/dark themes */
[data-av-theme='light'],
.av-light {
--av-skeleton-animation: shimmer;
}
[data-av-theme='dark'],
.dark,
.av-dark {
--av-skeleton-animation: pulse;
} This global setting is overridden by the animation-type input when specified on an individual div[av-skeleton].
Passing Tailwind CSS classes
Pass utility classes on div[av-skeleton] to control size, shape, and layout.
import { Component } from '@angular/core';
import { AvSkeletonComponent } from '@avesra/angular';
@Component({
selector: 'app-skeleton-custom-styling-demo',
imports: [AvSkeletonComponent],
host: { class: 'block' },
template: `<div
class="w-[250px] space-y-5 rounded-xl border border-border/80 bg-surface p-4 shadow-sm ring-1 ring-black/5 dark:ring-white/10"
>
<div av-skeleton class="h-32 rounded-lg bg-neutral-200/90 dark:bg-neutral-800/90"></div>
<div class="space-y-3">
<div av-skeleton class="h-3 w-3/5 rounded-lg bg-neutral-200/90 dark:bg-neutral-800/90"></div>
<div av-skeleton class="h-3 w-4/5 rounded-lg bg-neutral-200/90 dark:bg-neutral-800/90"></div>
<div av-skeleton class="h-3 w-2/5 rounded-lg bg-neutral-200/90 dark:bg-neutral-800/90"></div>
</div>
</div>`,
})
export class SkeletonCustomStylingDemo {}Customizing the component classes
To customize the Skeleton classes, use the @layer components directive. Learn more.
@layer components {
/* Base skeleton styles */
.av-skeleton {
@apply bg-surface-secondary/50; /* Change base background */
}
/* Shimmer animation gradient */
.av-skeleton--shimmer::after {
@apply via-surface; /* Change shimmer gradient color */
}
/* Pulse animation */
.av-skeleton--pulse {
@apply animate-pulse opacity-75; /* Customize pulse animation */
}
/* No animation variant */
.av-skeleton--none {
@apply opacity-50; /* Style for static skeleton */
}
}Avesra follows the BEM methodology so component variants and states stay reusable and easy to customize.
CSS Classes
The Skeleton component uses these CSS classes:
Base Class
.av-skeleton— Base skeleton styles with background and rounded corners
Animation Variant Classes
.av-skeleton--shimmer— Shimmer animation with gradient effect (default).av-skeleton--pulse— Pulse animation using Tailwind's animate-pulse.av-skeleton--none— No animation, static skeleton
Animation
The Skeleton component supports three animation types, each with different visual effects:
Shimmer Animation
The shimmer effect creates a gradient that moves across the skeleton element:
.av-skeleton--shimmer::after {
@apply absolute inset-0 -translate-x-full animate-skeleton
bg-linear-to-r from-transparent via-surface-tertiary to-transparent
content-[''];
}The shimmer animation is defined in the theme using:
@theme inline {
--animate-skeleton: skeleton 2s linear infinite;
@keyframes skeleton {
100% {
transform: translateX(200%);
}
}
}Pulse Animation
The pulse animation uses Tailwind's built-in animate-pulse utility:
.av-skeleton--pulse {
@apply animate-pulse;
}No Animation
For static skeletons without any animation:
.av-skeleton--none {
/* No animation styles applied */
}API
Props for div[av-skeleton]. Size and shape come from host utility classes rather than dedicated inputs.
| Prop | Type | Default | Description |
|---|---|---|---|
animation-type | 'shimmer' | 'pulse' | 'none' | 'shimmer' or --av-skeleton-animation | Animation type for the skeleton. When omitted, reads --av-skeleton-animation from computed styles, then falls back to shimmer. |