SPECIAL PRICING
BLACK FRIDAY SALE
PERSONAL $99
TEAM $349
ENDS DEC 1
GET IT NOW

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.

InputTypeDefaultDescription
enabledbooleantrueToggles 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.
classClassValue''Classes merged onto the host.

buiSkeletonRepeat

A structural directive that stamps out its ng-template a given number of times.

InputTypeDefaultDescription
buiSkeletonRepeatnumber1Number of times to render the template.

The following variables are available inside the ng-template:

PropertyTypeDescription
$implicitnumberZero-based index of the current iteration.
indexnumberZero-based index of the current iteration.
countnumberTotal number of iterations.
firstbooleantrue for the first item.
lastbooleantrue for the last item.
oddbooleantrue for odd-numbered items (1st, 3rd, ...).
evenbooleantrue for even-numbered items (2nd, 4th, ...).