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 variants —
list,grid,table,card,text - Shape presets —
rectangle,circle,text,avatar,image - Animations —
none,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
| Input | Type | Default | Description |
|---|---|---|---|
rows | number | 5 | Number of rows (or list/text items) |
columns | number | 1 | Number of columns (grid, table, card) |
width | string | number | '100%' | Item width (100%, 80%, 300px, or bare number as px) |
height | string | number | 40 | Item height (bare number treated as px) |
gap | string | number | 12 | Spacing between items (px) |
borderRadius | string | number | shape default | Border radius override |
variant | SkeletonVariant | 'list' | Layout variant |
shape | SkeletonShape | 'rectangle' | Shape preset (primarily for grid variant) |
animation | SkeletonAnimation | 'shimmer' | Animation style |
decorative | boolean | true | When true, skeleton is hidden from assistive tech |
loadingLabel | string | undefined | Accessible label when decorative is false |
responsive | boolean | true | Enable responsive column reduction on smaller screens |
Variants
| Variant | Description |
|---|---|
list | Avatar + two text lines per row |
grid | Uniform grid of rows × columns items |
table | Header row + rows data rows with columns cells each |
card | Product/dashboard cards with image + text placeholders |
text | Stacked text lines with varied widths |
Shapes
| Shape | Default border radius | Default height (grid) |
|---|---|---|
rectangle | 4px | 40px |
circle | 50% | 48px |
text | 4px | 14px |
avatar | 50% | 48px |
image | 8px | 160px |
Explicit borderRadius overrides shape defaults when provided.
Animations
| Animation | Description |
|---|---|
none | Static skeleton blocks |
pulse | Subtle opacity fade |
shimmer | Smooth 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:
| Input | Invalid example | Behavior |
|---|---|---|
rows | 0, -1 | Clamped to minimum 1 |
columns | 0, -5 | Clamped to minimum 1 |
height | -10 | Falls back to default (40px or shape default) |
gap | -20 | Falls back to default 12px |
width | invalid string | Falls 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 provideloadingLabelwhen 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.
- Fork the repository
- Create a feature branch
- Make your changes with tests
- Run
npm run buildandnpm run test:ci - Submit a pull request
License
MIT © Nikhil Makwana — see LICENSE.