Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

ngx-skeleton-loader

willmendesneto508.9kMIT11.0.0TypeScript support: included

Make beautiful, animated loading skeletons that automatically adapt to your Angular apps

angular, ngx, skeleton, ghost, loader, ngx-skeleton-loader, facebook-loading, loading, skeleton-loader, skeleton-animation, animation

readme

NGX Skeleton loader

npm downloads npm npm

NPM NPM

Build Status Coverage Status npm bundle size (minified + gzip) npm

ngx-skeleton-loader in action

Why skeletons?

If you want to get more details about that, please read "NGX-Skeleton-Loader — States, Animations, Performance, and Accessibility for your Angular App" blog post

The idea of this component is make the process transparent and easier. So the main point is integrate this component with other tooling process, such as:

  • Server-side rendering;
  • Progressive rendering;
  • Any other that you like :)

It's totally transparent for you and you can integrate easier in your application, improving your user experience 🎉

Demo

Try out our demos on Stackblitz!

Install

You can get it on NPM installing ngx-skeleton-loader module as a project dependency.

npm install ngx-skeleton-loader --save

Setup

You'll need to add NgxSkeletonLoaderModule to your application module. So that, the <ngx-skeleton-loader> components will be accessible in your application.

...
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
...

@NgModule({
  declarations: [
    YourAppComponent
  ],
  imports: [
    ...
    NgxSkeletonLoaderModule,
    ...
  ],
  providers: [],
  bootstrap: [YourAppComponent]
})

export class YourAppComponent {}

After that, you can use the ngx-skeleton-loader components in your templates, passing the configuration data into the component itself.

  • ngx-skeleton-loader: Handle the skeleton animation and the skeleton styles of your app;
<div class="item">
  <ngx-skeleton-loader count="5" appearance="circle" />
</div>

Using NgxSkeletonLoaderModule.forRoot()

Also, you can import the module in your app by calling NgxSkeletonLoaderModule.forRoot() when adding it. So it will be available across your Angular application.

Importing the module this way also allows you to globally configure the default values for the ngx-skeleton-loader components in your application, in case you need some different default values for your app.

...
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
...

@NgModule({
  declarations: [
    YourAppComponent
  ],
  imports: [
    ...
    NgxSkeletonLoaderModule.forRoot({ animation: 'pulse', loadingText: 'This item is actually loading...' }),
    ...
  ],
  providers: [],
  bootstrap: [YourAppComponent]
})

export class YourAppComponent {}
<div class="item">
  <ngx-skeleton-loader count="5" appearance="circle" />
  <!-- above line will produce the rendering of 5 circles with the pulse animation and the aria-valuetext attribute set with "This item is actually loading..." -->
</div>

Extending theme via NgxSkeletonLoaderModule.forRoot()

By default when using NgxSkeletonLoaderModule.forRoot({ theme: /* ...list of CSS atributes */} }) the application is using this value as source of truth, overriding any local theming passed to <ngx-skeleton-loader> component via [theme] input. Check these steps in case you need to change this behaviour in your app

This method is also accepting the option of having a global theme and local theme inputs. You can enable it by passing NgxSkeletonLoaderModule.forRoot({ theme: { extendsFromRoot: true, /* ...list of CSS atributes */} }) in your module. Quite simple, right? 😄

By using that configuration in your application, you should also be aware that:

  • By default, every <ngx-skeleton-loader> component will use theme coming from NgxSkeletonLoaderModule.forRoot() as the source of truth
  • If there's any CSS attribute on the component locally which overrides the CSS spec, it combines both themes, but overriding global CSS attributes in favor of local ones.

As an example:

...
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
...

@NgModule({
  declarations: [
    YourAppComponent
  ],
  imports: [
    ...
    NgxSkeletonLoaderModule.forRoot({
      theme: {
        // Enabliong theme combination
        extendsFromRoot: true,
        // ... list of CSS theme attributes
        height: '30px',
      },
    }),
    ...
  ],
  providers: [],
  bootstrap: [YourAppComponent]
})

export class YourAppComponent {}
<div class="item">
  <ngx-skeleton-loader />
  <!-- above line will produce a skeleton component using `height: 30px;`" -->
  <ngx-skeleton-loader [theme]="{background: 'blue'}" />
  <!-- above line will produce a skeleton component using `height: 30px; background: blue;`" -->
  <ngx-skeleton-loader [theme]="{height: '50px', background: 'red'}" />
  <!-- above line will produce a skeleton component using `height: 50px; background: red;`" -->
</div>

Angular 17+ Deferrable Views example

<div class="item">
  @defer {
    <my-item-view />
  } @placeholder (minimum 1000ms) {
    <ngx-skeleton-loader />
  }
</div>

WAI-ARIA values

  • loadingText - default Loading...: attribute that defines the text value for aria-valuetext attribute. Defaults to "Loading..."
  • aria-label - default loading: you can add ariaLabel as input of the component to set a different value.

Appearance

You can also define which appearance want to use in your skeleton loader by passing the options in your component via [appearance] attribute.

Options

  • '' - default: it will use it '' as appearance. At the end, it will render like a line;
  • line: it will render like a line. This is the same behavior as passing an empty string;
  • circle: it will use circle as appearance. Great for avatar skeletons, for example :);
  • custom-content: it will NOT add any appearance. Great for custom content, such as SVG, internal components and such;

Animations

You can also define which CSS animation you want to use - even not use any, if it's the case - in your skeleton loader by passing the options in your component via [animation] attribute.

Options

  • "false" (as string): it will disable the animation;
  • false (as boolean): it will disable the animation. Animation will receive false as string when attribute field it's not using binding. Component now can receive false (boolean), "false" (string), or any other animation type via binding;
  • progress - default: it will use it progress as animation;
  • progress-dark: it will use it progress-dark as animation. Recommended if your color schema is darken;
  • pulse: it will use pulse as animation;

progress is the default animation, used as the single one previously. If you don't pass the animation attribute, it defaults to progress.

<!--
If you need to change all the background wrapper
you need to apply the style changes on the 
`ngx-skeleton-loader` component wrapper
-->
<div class="item">
  <!-- Disables the animation -->
  <ngx-skeleton-loader animation="false" />
  <!-- Disables the animation, but receiving boolean value from binding -->
  <!-- Via binding it can receive `false` (boolean), "false" (string), or any other animation type -->
  <ngx-skeleton-loader [animation]="classAttributeWithBooleanFalseValue" />
  <!-- Uses `progress` as animation -->
  <ngx-skeleton-loader animation="progress" />
  <ngx-skeleton-loader />
  <!-- Uses `pulse` as animation -->
  <ngx-skeleton-loader animation="pulse" />
</div>

You can check the code details in the Stackblitz Live Demo Link

Theming

You can also define different styles for the skeleton loader by passing an object with the css styles - in dashed case - into the component via [theme] attribute.

<!--
If you need to change all the background wrapper
you need to apply the style changes on the 
`ngx-skeleton-loader` component wrapper
-->

<div style="background: #FF0001; padding: 10px;">
  <ngx-skeleton-loader
    count="5"
    [theme]="{ 
      'border-radius': '5px',
      height: '50px',
      'background-color': '#992929',
      border: '1px solid white'
    }"
  />
</div>

The [theme] attribute now accepts the same configuration as [style] as well. That means you can manage to use like you're doing with the built-in directive, having a pleasure and beautiful experience

<!--
Note that we are using a combination of styles and [style] inside theme object,
having `height.px` receiving a number and `background-color` receiving a HEX Color
-->
<div style="background: #FF0001; padding: 10px;">
  <ngx-skeleton-loader
    count="5"
    [theme]="{ 
      'height.px': 50,
      'background-color': '#992929'
    }"
  />
</div>

⚠️ This is here only as a documentation, but it's not encouraged to be used. Please consider use it with caution ⚠️

Also, you can use CSS to add theme styles into your component. However, there are some implications:

  • You're using :host in your stylesheet, which means you are aware of any possible problem :host can create for your app at that level since it's based on :host DOM style scoping
  • You're adding stylesheet based on <ngx-skeleton-loader> internal classes. It means that class naming changes on module's side will be breaking changes for your application as well.

As an example, your Component file is like this

import { Component } from '@angular/core';

@Component({
  selector: 'my-ngx-skeleton-loader-with-theming',
  templateUrl: './my-ngx-skeleton-loader-with-theming.component.html',
  styleUrls: ['./my-ngx-skeleton-loader-with-theming.component.css'],
})
export class MyNGXSkeletonLoaderWithThemingComponent {
  /* ... code goes here*/
}

And your component HTML code is

<!--
file: my-ngx-skeleton-loader-with-theming.component.html

As an example, it's not using themes via [theme] attributes.
-->

<ngx-skeleton-loader count="5" animation="pulse" />

You can apply theme changes in our stylesheet. At the end it will be

/* file: `my-ngx-skeleton-loader-with-theming.component.css`
 *
 * You can find more details about `:host` at
 * Angular Component Style Docs https://angular.io/guide/component-styles#host
 */
:host >>> ngx-skeleton-loader .skeleton-loader {
  border-radius: 5px;
  height: 50px;
  background-color: #992929;
  border: 1px solid white;
}

You should change the styles on the skeleton wrapper element in case you need to change the background color. You can check the code details in the Stackblitz Live Demo Link or check it out a content load simulation in this Stackblitz Live Demo Link

Development

Run demo locally

  1. This project uses Angular CLI as base. That means you just need to run npm start and access the link http://localhost:4200 in your browser

Run tests

  1. Run npm test for run tests. In case you want to test using watch, please use npm run tdd

Publish

this project is using np package to publish, which makes things straightforward. EX: npx np <patch|minor|major> --no-yarn --no-cleanup --contents=dist/ngx-skeleton-loader

For more details, please check np package on npmjs.com

Contribute

For any type of contribution, please follow the instructions in CONTRIBUTING.md and read CODE_OF_CONDUCT.md and PUBLISHING_HOTFIX.md files.

Author

Wilson Mendes (willmendesneto)

changelog

Change Log

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog and this project adheres to Semantic Versioning.

Unreleased

11.0.0 - 2025-04-09

Updated

  • Upgrading project to use Node.js v22.14.0
  • Upgrading project to Angular v19
  • Removing [ngStyle] and [ngClass] in favor of [style] and [class], respectively. These directives are expected to be removed in future Angular versions, since their behavior can be replicated using native bindings. This change also reduces the initial bundle size for applications that don’t use these directives.

10.0.0 - 2025-01-24

Removed

  • Removing warnings in dev mode in favor of typed angular signals integration. It should not affect consumers in general, but it will be released as a major version, since this project follows the SEMVER standards

Updated

Thanks to @lekhmanrus

Added

  • Adding PUBLISHING_HOTFIX.md file describing all the steps to cover a hotfix in older version of NGX-Skeleton-Loader module

9.0.0 - 2024-01-13

Updated

  • Upgrading @angular/* packages to v17
  • Upgrading NodeJS to v20.10.0

8.1.0 - 2023-09-12

Fixed

  • fixing issue with optional chaining not being supported on apps using Angular CLI <=v11;

Updated

  • Updated input values validation in order to remove optional chaining. Instead, the code is now using object destructuring to get config theme value;

8.0.2 - 2023-09-11

Fixed

  • Fixing README.md docs

8.0.1 - 2023-08-30

Fixed

  • Fixing CSS reduce motion in MacOS;

8.0.0 - 2023-06-20

Updated

  • Updating project to support Angular v16;
  • Updating NodeJS version to v18;
  • Updating peerDependencies to point to latest @angular/* packages;

Removed

  • Removing perf-marks dependency library;

7.0.0 - 2023-02-04

Added

  • Adding support for extending global theme added via NgxSkeletonLoaderModule.forRoot({ theme: /* ...list of CSS atributes */} })

By default when using NgxSkeletonLoaderModule.forRoot({ theme: /* ...list of CSS atributes */} }) the application is using this value as source of truth, overriding any local theming passed to <ngx-skeleton-loader> component via [theme] input.

By using NgxSkeletonLoaderModule.forRoot({ theme: { extendsFromRoot: true, /* ...list of CSS atributes */} }) in your application, you should also be aware that:

  • By default, every <ngx-skeleton-loader> component will use theme coming from NgxSkeletonLoaderModule.forRoot() as the source of truth
  • If there's any CSS attribute on the component locally which overrides the CSS spec, it combines both themes, but overriding global CSS attributes in favor of local ones.
<!-- 
  // ... E.G: App is using this configuration below

  NgxSkeletonLoaderModule.forRoot({
    theme: {
      // Enabliong theme combination
      extendsFromRoot: true,
      // ... list of CSS theme attributes
      height: '30px',
    },
  }),
-->

<div class="item">
  <ngx-skeleton-loader></ngx-skeleton-loader>
  <!-- above line will produce a skeleton component using `height: 30px;`" -->
  <ngx-skeleton-loader [theme]="{background: 'blue'}"></ngx-skeleton-loader>
  <!-- above line will produce a skeleton component using `height: 30px; background: blue;`" -->
  <ngx-skeleton-loader [theme]="{height: '50px', background: 'red'}"></ngx-skeleton-loader>
  <!-- above line will produce a skeleton component using `height: 50px; background: red;`" -->
</div>
  • Adding new custom-content appearance. From now on, consumers can now add their own content inside <ng-skeleton-loader></ng-skeleton-loader> component. So that, they can add some custom content, such as SVG, as an example
  • Adding examples for custom-content usage

Updated

  • Updagrading module to Angular v15

Fixed

  • Removing build warnings

6.0.0 - 2022-08-18

Updated

  • Adding Publishing setup using NPX
  • Replacing CSS class namespace from .loader to .skeleton-loader

Breaking Change

The CSS class used as namespace was changed. Previously, it was called .loader and now is .skeleton-loader. It might cause some issues in cases of :host DOM style scoping usage. For the sake of semantic versioning, please bear in mind this scenario in case of :host usage.

5.0.0 - 2022-02-08

Updated

Thanks @yharaskrik

Breaking Change

Bundle distribution are now esm2020, fesm2015 and fesm2020. UMD and CommonJS versions were support were removed from Angular CLI directly. So the next version for the package will be a major version to cover these changes accordingly.

  • Updating package bundle distribution
  • Updating @angular/cli to v13
  • Applying project changes to v13
  • Updating bundlesize check to point to fesm2020

4.0.0 - 2021-07-28

Fixed

Breaking Change

  • Rolling back "Adding mechanism to prevents calling forRoot() more than once if module is loaded asynchronously in a submodule.". Unfortunately, this was affecting consumers and it needed to be reverted to avoid friction in other applications.

If you need to have this feature in place, the suggestion is to create a specific module in your app and apply the changes on your application.

3.0.0 - 2021-07-23

Added

Breaking Change

  • Adding mechanism to prevents calling forRoot() more than once if module is loaded asynchronously in a submodule. This is required in order to avoid issues in consumers. To avoid that, consumers should load the module once on the main module instead - if loading submodules async.

2.10.1 - 2021-07-13

Fixed

  • Ensures every ARIA progressbar node has an accessible name. This is caused by missing aria-label on the <span> element.

Thanks @rkristelijn for raising the issue and the pull request!

2.10.0 - 2021-06-15

Added

  • Adding module configuration support via forRoot() method. Now you can add configure your module via forRoot(). You can now set the default of appearance, animation, theme, loadingText, count and/or items.E.G.

@NgModule({
  // ...
  imports: [NgxSkeletonLoaderModule.forRoot({ appearance: 'circle', count: 3 )],
  // ...
})

2.9.2 - 2021-04-11

Updated

  • Updating link in README.md

Fixed

  • Bumping dev dependencies to avoid security issues

2.9.1 - 2021-02-20

Fixed

  • Adding appearance attribute to be checked via ngOnChanges

Updated

  • Updating examples with new features

2.9.0 - 2021-02-19

Added

  • Adding validation for @Input attributes that needs internal manipulation. After these changes:
    • if count is not a numeric value, it will use the default value as 1
    • if animation is not a valid attribute, it will use the default value as progress
    • PS: The other values alredy have a fallback, so nothing to worry here
  • Adding error feedback for appearance attribute in case of wrong configuration. Now it will show a error message on the console in case of receiving a wrong value

Updated

  • Adding ngOnChange to validate count input in case of changes via binding
  • Updating README.md with information about appearance and theme usage.

2.8.0 - 2021-02-18

Fixed

Updated

2.7.0 - 2021-02-06

Added

  • Adding new loadingText attribute to be used as WAI-ARIA aria-valuetext. In this case, it will render the component using "Please wait ...". Otherwise, it defaults to "Loading..."
<!-- Passing loading text to be used as WAI-ARIA `aria-valuetext` -->
<!-- In this case, it will render the component using "Please wait ..." -->
<!-- Otherwise, it defaults to "Loading..." -->
<div class="skeleton-with-specific-loading-text">
  <ngx-skeleton-loader loadingText="Please wait ..."></ngx-skeleton-loader>
</div>

Updated

  • Using OnPush as changeDetection mechanism into ngx-skeleton-loader component
  • Adding ability to pass false as string or boolean (coming from variable value via binding) on animation attribute in ngx-skeleton-loader component configuration. animation will receive false as string when attribute field it's not using binding. Component now can receive false (boolean), "false" (string), or any other animation type via binding.
<div class="item">
  <!-- Disables the animation -->
  <ngx-skeleton-loader animation="false"></ngx-skeleton-loader>
  <!-- Disables the animation, but receiving boolean value from binding -->
  <!-- Via binding it can receive `false` (boolean), "false" (string), or any other animation type -->
  <ngx-skeleton-loader [animation]="classAttributeWithBooleanFalseValue"></ngx-skeleton-loader>
  <!-- Uses `progress` as animation -->
  <ngx-skeleton-loader animation="progress"></ngx-skeleton-loader>
  <ngx-skeleton-loader></ngx-skeleton-loader>
  <!-- Uses `pulse` as animation -->
  <ngx-skeleton-loader animation="pulse"></ngx-skeleton-loader>
</div>

2.6.2 - 2020-12-08

Fixed

  • Removing Lighthouse "Avoid non-composited animations" issue. Lighthouse shows warnings from ngx-skeleton-loader.scss -file (progress).

  • "Avoid non-composited animations":

  • "Animations which are not composited can be janky and contribute to CLS"

To solve that, instead of using CSS background-position the module is now using CSS translate3d, which improves the animation by using GPU instead of CPU. Issue fixed and performance boost added 🎉

2.6.1 - 2020-11-30

Fixed

2.6.0 - 2020-11-15

Added

  • Adding NgxSkeletonLoaderModule.forRoot() method. Usage:
import { NgModule } from '@angular/core';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
// ... list of other app dependencies

import { AppComponent } from './app.component';
// ... list of other app components/modules

@NgModule({
  declarations: [AppComponent],
  imports: [NgxSkeletonLoaderModule.forRoot()],
  providers: [],
  bootstrap: [AppComponent],
})
export class AppModule {}

2.5.0 - 2020-10-10

Fixed

  • Fixing bundle size command on CircleCI pipeline

Updated

  • Upgrading NodeJS to v14.11.0
  • Updating perf-marks package to v1.14.0
  • Improving skeleton animations fps by using cubic-bezier instead of ease-in-out

2.4.4 - 2020-08-21

Fixed

  • Remove check requirements if perf-marks is running in a browser or not in Angular apps 🔥

Added

  • Adding Angular Universal support for examples. Now we can run npm run dev:ssr and access http://localhost:4200/index.html and the page will run using angular universal 💪
  • Adding .prettierrc file with some of the code styling rules

2.4.3 - 2020-08-13

Fixed

  • Avoiding perf-marks call if running in Angular Universal applications

2.4.2 - 2020-08-01

Updated

  • Bumping perf-marks to latest version

2.4.1 - 2020-08-01

Updated

  • Bumping perf-marks to latest version

2.4.0 - 2020-08-01

Added

  • Adding User Timing API to track component render and content loader time

Updated

  • Updating examples with new skeleton simulation
  • Adding Stackblitz link for user card skeleton loading demo

2.3.0 - 2020-08-01

Added

  • Adding User Timing API to track component render and content loader time

Updated

  • Updating examples with new skeleton simulation
  • Adding Stackblitz link for user card skeleton loading demo

2.2.1 - 2020-06-30

Fixed

  • For compatibility with IE11 by using indexOf instead of includes

Updated

  • Updating npm run postinstall command to follow the new rules from update.angular.io website

2.2.0 - 2020-06-01

Added

2.1.0 - 2020-06-01

Updated

  • Upgrading @angular/cli to version 9
  • 🎉 Decreasing bundle size to 1.17KB 🎉

2.0.0 - 2020-05-15

Updated

  • Upgrading NodeJS to v12.16.2
  • Updating documentation with animation attribute

Added

  • Supporting for new animation progress-dark to enable users when using theme with darker color schema
  • Supporting for different animations 🎉

Now we can define the animation we want to use in <ngx-skeleton-loader> component via animation input. It's a string that can defined the animation used during the loading, having as options:

  • false: it will disable the animation;
  • progress - default: it will use it progress as animation;
  • pulse: it will use pulse as animation;

progress is the default animation, used as the single one previously. If you don't pass the animation attribute, it defaults to progress.

<div class="item">
  <!-- Disables the animation -->
  <ngx-skeleton-loader animation="false"></ngx-skeleton-loader>
  <!-- Uses `progress` as animation -->
  <ngx-skeleton-loader animation="progress"></ngx-skeleton-loader>
  <ngx-skeleton-loader></ngx-skeleton-loader>
  <!-- Uses `pulse` as animation -->
  <ngx-skeleton-loader animation="pulse"></ngx-skeleton-loader>
</div>
  • Supporting enabling/disabling animations. Now the users will be able to enable/disable animations by using animation input. It's a string with false as value that the component receives to check if it should not load progress animation.

It works only to disable it. In case you want to keep enable it

<div class="item">
  <ngx-skeleton-loader animation="false"></ngx-skeleton-loader>
</div>

1.2.7 - 2020-04-13

Updated

  • Decreasing bundle size after disable Ivy in production build
  • Adding description, keywords and github information on package.json files

1.2.6 - 2020-02-26

Fixed

  • Changing angular library configuration to prod and forcing it at publish time

1.2.5 - 2020-02-25

Fixed

  • Changing angular library configuration to prod

1.2.4 - 2020-02-25

Updated

  • Updating Github templates
  • Updating Angular CLI to v9

1.2.3 - 2020-02-25

Fixed

  • Solving peerDependency warning when installing library in an Angular 9 project

1.2.2 - 2019-06-22

Fixed

  • Fixing component dimensions via theme

1.2.1 - 2019-06-08

Updated

  • Updating Angular CLI to v8

1.2.0 - 2019-04-19

Updated

  • Updating Angular CLI to 7.3.8

1.1.2 - 2019-01-07

Added

  • Adding badges for stackblitz, bundlephobia and license

Updated

  • Removing unnecessary CSS styles for skeleton

1.1.1 - 2018-12-17

Fixed

  • Fixing Stackblitz link demo link

1.1.0 - 2018-12-17

Added

  • Added GitHub urls into package.json
  • Added Circle CI integration
  • Added Coveralls integration
  • Added GitHub templates
  • Added CODE_OF_CONDUCT.md with the Code of conduct
  • Added unit tests for skeletons and demo components

Updated

  • Decreased bundle size
  • New gif showing ngx-skeleton-loader in action

1.0.2 - 2018-12-16

Fixed

  • Added markdown files in dist folder in build time

1.0.1 - 2018-12-16

Fixed

  • Added markdown files in dist folder in build time

1.0.0 - 2018-12-16

Fixed

  • Fixed build script

0.0.1 - 2018-12-16

Added

  • Created ngx-skeleton-loader
  • Created test automation for the module