Angular Smart Skeleton

August 2, 2026 · View on GitHub

A flexible and reusable Angular skeleton loader for dynamic rows, columns, cards, lists, tables, and custom layouts.

Provide configuration — the smart skeleton dynamically generates the layout.

Features

  • Configurable layout — rows, columns, gap, width, height, and border radius
  • Multiple variantslist, grid, table, card, text
  • Shape presetsrectangle, circle, text, avatar, image
  • Animationsnone, pulse, shimmer (CSS-only)
  • Accessible — decorative skeletons use aria-hidden; optional loading label
  • Responsive — grid and card layouts adapt on tablet and mobile
  • Reduced motion — respects prefers-reduced-motion
  • Standalone component — easy to copy into any Angular 19+ project
  • Strict TypeScript — strongly typed inputs and models
  • OnPush change detection — efficient rendering for large skeleton grids

Demo

Run the demo application locally:

npm install
npm start

Open http://localhost:4200 to explore live examples and the interactive configuration panel.

Screenshots

Add screenshots of the demo page here after running the application.

Installation

This project is designed for easy adoption. Clone the repository and copy the reusable component into your app:

src/app/components/smart-skeleton/   →  your-app/components/smart-skeleton/
src/app/models/skeleton.models.ts    →  your-app/models/skeleton.models.ts

Future releases will be published as an npm package (@nik_makwana/smart-skeleton).

Usage

Import the standalone component:

import { SmartSkeletonComponent } from './components/smart-skeleton/smart-skeleton.component';

@Component({
  imports: [SmartSkeletonComponent],
  // ...
})
export class MyComponent {}

Basic Example

<smart-skeleton
  variant="list"
  [rows]="5"
  animation="shimmer">
</smart-skeleton>

Grid Example

<smart-skeleton
  variant="grid"
  [rows]="3"
  [columns]="4"
  [height]="180"
  [gap]="16"
  animation="shimmer">
</smart-skeleton>

Table Example

<smart-skeleton
  variant="table"
  [rows]="8"
  [columns]="5"
  [height]="36"
  [gap]="10"
  animation="pulse">
</smart-skeleton>

Card Example

<smart-skeleton
  variant="card"
  [rows]="2"
  [columns]="3"
  [gap]="20"
  animation="shimmer">
</smart-skeleton>

Configuration

API

InputTypeDefaultDescription
rowsnumber5Number of rows (or list/text items)
columnsnumber1Number of columns (grid, table, card)
widthstring | number'100%'Item width (100%, 80%, 300px, or bare number as px)
heightstring | number40Item height (bare number treated as px)
gapstring | number12Spacing between items (px)
borderRadiusstring | numbershape defaultBorder radius override
variantSkeletonVariant'list'Layout variant
shapeSkeletonShape'rectangle'Shape preset (primarily for grid variant)
animationSkeletonAnimation'shimmer'Animation style
decorativebooleantrueWhen true, skeleton is hidden from assistive tech
loadingLabelstringundefinedAccessible label when decorative is false
responsivebooleantrueEnable responsive column reduction on smaller screens

Variants

VariantDescription
listAvatar + two text lines per row
gridUniform grid of rows × columns items
tableHeader row + rows data rows with columns cells each
cardProduct/dashboard cards with image + text placeholders
textStacked text lines with varied widths

Shapes

ShapeDefault border radiusDefault height (grid)
rectangle4px40px
circle50%48px
text4px14px
avatar50%48px
image8px160px

Explicit borderRadius overrides shape defaults when provided.

Animations

AnimationDescription
noneStatic skeleton blocks
pulseSubtle opacity fade
shimmerSmooth left-to-right shimmer overlay

When the user has reduced motion enabled, pulse and shimmer animations are disabled automatically.

Invalid input behavior

Invalid values are handled gracefully — no runtime errors:

InputInvalid exampleBehavior
rows0, -1Clamped to minimum 1
columns0, -5Clamped to minimum 1
height-10Falls back to default (40px or shape default)
gap-20Falls back to default 12px
widthinvalid stringFalls back to 100%

Accessibility

  • Decorative skeletons (default) set aria-hidden="true" on the container
  • Skeleton blocks are not focusable and use role="presentation"
  • Set [decorative]="false" and provide loadingLabel when the skeleton represents active loading state
  • Animations respect prefers-reduced-motion: reduce

Responsive Behavior

When responsive is enabled (default):

  • Desktop — uses configured column count
  • Tablet (≤992px) — grid/card columns capped at 2
  • Mobile (≤576px) — single column layout

Grid items use minmax(0, 1fr) to prevent horizontal overflow.

Project Structure

src/app/
├── components/
│   └── smart-skeleton/       # Reusable skeleton component
├── models/
│   └── skeleton.models.ts    # Types and utility functions
├── pages/
│   └── skeleton-demo/        # Demo page (not part of the reusable API)
├── app.component.ts
└── app.component.html

The reusable SmartSkeletonComponent contains no demo-specific logic. The demo page composes skeletons for real-world examples (user list, product grid, profile, article).

Testing

# Interactive watch mode
npm test

# CI / headless
npm run test:ci

Tests cover rendering, inputs, shapes, animations, invalid values, and accessibility.

Roadmap

  • Custom item configuration
  • Per-item width/height
  • Advanced layout configuration
  • Angular library package
  • npm publishing
  • Storybook
  • More examples

Contributing

Contributions are welcome! Please open an issue or pull request on the repository.

  1. Fork the repository
  2. Create a feature branch
  3. Make your changes with tests
  4. Run npm run build and npm run test:ci
  5. Submit a pull request

License

MIT © Nikhil Makwana — see LICENSE.