skeleton

Use to show a placeholder while content is loading.

PreviousNext
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';

@Component({
  selector: 'z-demo-skeleton-preview',
  imports: [ZardSkeletonComponent],
  template: `
    <div class="flex items-center space-x-4">
      <z-skeleton class="size-12 rounded-full" />
      <div class="space-y-2">
        <z-skeleton class="h-4 w-[250px]" />
        <z-skeleton class="h-4 w-[200px]" />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSkeletonPreviewComponent {}

Installation

Copy
npx zard-cli@latest add skeleton

Usage

import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';
Copy
<z-skeleton class="h-4 w-[250px]"></z-skeleton>
Copy

Examples

avatar

A compact avatar label: a size-10 circle standing in for z-avatar next to two short bars for a name and a secondary line.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';

@Component({
  selector: 'z-demo-skeleton-avatar',
  imports: [ZardSkeletonComponent],
  template: `
    <div class="flex w-fit items-center gap-4">
      <z-skeleton class="size-10 shrink-0 rounded-full" />
      <div class="grid gap-2">
        <z-skeleton class="h-4 w-[150px]" />
        <z-skeleton class="h-4 w-[100px]" />
      </div>
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSkeletonAvatarComponent {}

card

A loading z-card: the title and description bars are passed to z-card-title/z-card-description through their zTitle/zDescription template inputs, and an aspect-video bar fills z-card-content in place of media.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardCardImports } from '@/shared/components/card/card.imports';
import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';

@Component({
  selector: 'z-demo-skeleton-card',
  imports: [ZardCardImports, ZardSkeletonComponent],
  template: `
    <z-card class="w-full min-w-xs">
      <z-card-header>
        <z-card-title [zTitle]="titleSkeleton" />
        <z-card-description [zDescription]="descriptionSkeleton" />
      </z-card-header>
      <z-card-content>
        <z-skeleton class="aspect-video w-full" />
      </z-card-content>
    </z-card>

    <ng-template #titleSkeleton>
      <z-skeleton class="h-4 w-2/3" />
    </ng-template>

    <ng-template #descriptionSkeleton>
      <z-skeleton class="h-4 w-1/2" />
    </ng-template>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSkeletonCardComponent {}

text

A paragraph of body copy: three full-width lines, the last one narrower to mimic a line that does not reach the margin.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';

@Component({
  selector: 'z-demo-skeleton-text',
  imports: [ZardSkeletonComponent],
  template: `
    <div class="flex w-full min-w-xs flex-col gap-2">
      <z-skeleton class="h-4 w-full" />
      <z-skeleton class="h-4 w-full" />
      <z-skeleton class="h-4 w-3/4" />
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSkeletonTextComponent {}

form

Two label-and-control pairs plus a submit action: each label bar sits above an h-8 bar matching the height of z-input, and the trailing h-8 bar matches a default z-button.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';

@Component({
  selector: 'z-demo-skeleton-form',
  imports: [ZardSkeletonComponent],
  template: `
    <div class="flex w-full min-w-xs flex-col gap-7">
      <div class="flex flex-col gap-3">
        <z-skeleton class="h-4 w-20" />
        <z-skeleton class="h-8 w-full" />
      </div>
      <div class="flex flex-col gap-3">
        <z-skeleton class="h-4 w-24" />
        <z-skeleton class="h-8 w-full" />
      </div>
      <z-skeleton class="h-8 w-24" />
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSkeletonFormComponent {}

table

A z-table body: five rows, each with a flexible primary-column bar and two fixed-width bars for secondary columns.
import { ChangeDetectionStrategy, Component } from '@angular/core';

import { ZardSkeletonComponent } from '@/shared/components/skeleton/skeleton.component';

@Component({
  selector: 'z-demo-skeleton-table',
  imports: [ZardSkeletonComponent],
  template: `
    <div class="flex w-full min-w-sm flex-col gap-2">
      @for (row of rows; track row) {
        <div class="flex gap-4">
          <z-skeleton class="h-4 flex-1" />
          <z-skeleton class="h-4 w-24" />
          <z-skeleton class="h-4 w-20" />
        </div>
      }
    </div>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class ZardDemoSkeletonTableComponent {
  protected readonly rows = [0, 1, 2, 3, 4];
}

API Reference

z-skeletonComponent

Renders a customizable placeholder during data loading to improve perceived performance and prevent layout shifts. `class` is the only input — size and shape the placeholder yourself with utility classes (`size-12 rounded-full`, `h-4 w-full`, ...) to match the content it stands in for.

PropertyDescriptionTypeDefault
[class] Custom CSS classes sizing and shaping the placeholder string ''
github iconwhatsapp icondiscord iconX icon

Made with ❤ in Brazil. Open source and available on GitHub .