Skeleton
Placeholder directives that render an animated shimmer while content is loading, keeping the layout stable and giving users immediate visual feedback.
Usage
import { BuiSkeleton, BuiSkeletonRepeat } from '@/bui/ui/skeleton';<div buiSkeleton></div>
<ng-template [buiSkeletonRepeat]="3">
<div buiSkeleton></div>
</ng-template>Example
Apply buiSkeleton to any element to turn it into an animated placeholder. Combine with buiSkeletonRepeat on an ng-template to render multiple rows at once.
Single skeleton lines with custom widths.
<div buiSkeleton class="h-5 w-48"></div>
<div buiSkeleton></div>
<div buiSkeleton class="h-5 w-3/4"></div>Repeated skeleton rows rendered from a single template.
<ng-template [buiSkeletonRepeat]="3" let-index="index">
<div class="flex items-center gap-x-3">
<div buiSkeleton class="h-8 w-8 rounded-full"></div>
<div class="flex flex-1 flex-col gap-y-1.5">
<div buiSkeleton class="h-3 w-1/3"></div>
<div buiSkeleton class="h-3 w-2/3"></div>
</div>
</div>
</ng-template>Repeat
A structural directive applied to an ng-template that stamps out its content a given number of times. It exposes template context variables so each iteration can be styled differently.
<!-- Stamp out 5 rows -->
<ng-template [buiSkeletonRepeat]="5" let-i>
<div buiSkeleton class="h-4"></div>
</ng-template>
<!-- Use context variables -->
<ng-template
[buiSkeletonRepeat]="4"
let-index="index"
let-first="first"
let-last="last"
>
<div
buiSkeleton
[class]="first ? 'h-6 w-1/2' : 'h-4'"
></div>
</ng-template>Compact repeat
When you don't need the template context variables, you can apply *buiSkeletonRepeat directly on the skeleton element itself. Angular's structural directive shorthand desugars it into an ng-template automatically, keeping the template concise.
<div *buiSkeletonRepeat="5" buiSkeleton></div>
<div *buiSkeletonRepeat="3" buiSkeleton class="h-8 w-8 rounded-full"></div>Conditional skeleton
Because buiSkeleton only toggles CSS classes, the typical pattern is to use empty placeholder elements alongside an @if that swaps in the real content once it has loaded. Use [enabled] when a directive-level style toggle is more convenient than restructuring the template with an @if:
<!-- Recommended: use @if to swap placeholder elements with real content -->
@if (isLoading()) {
<div buiSkeleton class="h-6 w-40"></div>
<div buiSkeleton class="h-4 w-full"></div>
<div buiSkeleton class="h-4 w-3/4"></div>
} @else {
<h2>{{ article.title }}</h2>
<p>{{ article.body }}</p>
}
<!-- Alternatively, use [enabled] when a style-only toggle is more convenient -->
<div buiSkeleton [enabled]="isLoading()" class="h-6 w-40"></div>Custom shapes
Use the class input to override the default dimensions and border radius. The default skeleton is h-4 w-full rounded-xl:
<!-- Rectangular image placeholder -->
<div buiSkeleton class="h-48 w-full rounded-lg"></div>
<!-- Avatar circle -->
<div buiSkeleton class="size-12 rounded-full"></div>
<!-- Pill-shaped tag -->
<div buiSkeleton class="h-5 w-16 rounded-full"></div>
<!-- Square thumbnail -->
<div buiSkeleton class="size-16 rounded-md"></div>API Reference
buiSkeleton
An attribute directive that adds the shimmer animation and base skeleton styles to any host element. Unlike buiSkeletonRepeat, it is not a structural directive. The host element and any content inside it are always present in the DOM regardless of the enabled state. enabled only toggles the CSS classes that produce the shimmer effect.
| Input | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Toggles the skeleton CSS classes on and off. Does not affect DOM presence. The host element and its children are always rendered. Useful as a convenience when you need a directive to programmatically control whether the shimmer is shown. |
class | ClassValue | '' | Classes merged onto the host. |
buiSkeletonRepeat
A structural directive that stamps out its ng-template a given number of times.
| Input | Type | Default | Description |
|---|---|---|---|
buiSkeletonRepeat | number | 1 | Number of times to render the template. |
The following variables are available inside the ng-template:
| Property | Type | Description |
|---|---|---|
$implicit | number | Zero-based index of the current iteration. |
index | number | Zero-based index of the current iteration. |
count | number | Total number of iterations. |
first | boolean | true for the first item. |
last | boolean | true for the last item. |
odd | boolean | true for odd-numbered items (1st, 3rd, ...). |
even | boolean | true for even-numbered items (2nd, 4th, ...). |