Skeleton

Show a preview placeholder of your content to reduce load-time frustration.

We are undergoing a migration, the following examples might not be up-to-date.

Please refer directly to the Storybook documentation based on your preferred framework.

Example

Content is loading.
<div class="nj-skeleton-container" style="max-width: 600px;">
  <span class="nj-sr-only">Content is loading.</span>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--area">
    <span class="nj-skeleton__icon material-icons nj-icon-material nj-icon-material--tertiary nj-icon-material--xl">image</span>
  </div>
  <div style="display: flex; gap: 8px; align-items: center;">
    <div aria-hidden="true" class="nj-skeleton nj-skeleton--circle nj-skeleton--lg"></div>
    <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--giga" style="width: 260px;"></div>
  </div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--hecto" style="max-width: 80%;"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--base"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--base"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--base"></div>
</div>
  
<div aria-busy="true" style="display: none;">
  <!-- Your content being loaded goes here (hidden) -->
</div>

Why use a Skeleton

Consider using skeletons to enhance the perceived responsiveness of the page since the data required for your components may not be readily accessible. This approach creates the illusion of instant activity, followed by a gradual display of information on the screen, thus avoiding the use of a spinner.

Structure

Use the .nj-skeleton-container as a wrapper and add as many .nj-skeleton elements inside it to mock your content.

We provide 3 variations:

  • nj-skeleton-rectangle
  • nj-skeleton-circle
  • nj-skeleton-area

Don’t forget to provide a .nj-sr-only element stating the loading state for screen readers.

Usage

While your content is being loaded, you must pass it an aria-busy=”true” attribute.

You must also add a function that hides the skeleton and shows the content when it is loaded. This function must do two things:

  • flip the aria-busy attribute from true to false on the content node (which will make it visible),
  • and add aria-hidden="true" to the .nj-skeleton-container node (which will hide it).

We recommend hiding the content until it is loaded and the aria-busy attribute is set to false *[aria-busy=”true”] {display: none;}.

Rectangle skeleton

Available sizes: "peta", "tera", "giga", "mega", "kilo", "hecto", "deca", "base", "deci", "centi" or custom with style="height: {wantedHeight}px;"

Content is loading.
<div class="nj-skeleton-container">
  <span class="nj-sr-only">Content is loading.</span>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--peta"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--tera"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--giga"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--mega"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--kilo"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--hecto"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--deca"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--base"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--deci"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle nj-skeleton--centi"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--rectangle" style="height: 120px;"></div>
</div>

Circle skeleton

Available sizes: "sm", "base", "lg", "xl" or custom with style="height: {wantedHeight}px; width: {wantedWidth}px;"

Content is loading.
<div class="nj-skeleton-container">
  <span class="nj-sr-only">Content is loading.</span>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--circle nj-skeleton--sm"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--circle"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--circle nj-skeleton--lg"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--circle nj-skeleton--xl"></div>
  <div aria-hidden="true" class="nj-skeleton nj-skeleton--circle" style="height: 200px; width: 200px;"></div>
</div>

Area skeleton

Customize it to your needs: height, width, image - to give an insight of the type of content being loaded -, …

Use the .nj-skeleton__icon class on an nj-icon component, an svg, etc.. to have the correct styling.

Content is loading
<div class="nj-skeleton-container">
  <span class="nj-sr-only">Content is loading</span>

  <div aria-hidden="true" class="nj-skeleton nj-skeleton--area">
    <span class="nj-skeleton__icon material-icons nj-icon-material nj-icon-material--tertiary nj-icon-material--xl">image</span>
  </div>

  <div aria-hidden="true" class="nj-skeleton nj-skeleton--area" style="height: 400px; width: 600px;">
    <svg class="nj-skeleton__icon" width="48" height="48" viewBox="0 0 36 36" fill="none" xmlns="http://www.w3.org/2000/svg">
      <path
        d="M36 32V4C36 1.8 34.2 0 32 0H4C1.8 0 0 1.8 0 4V32C0 34.2 1.8 36 4 36H32C34.2 36 36 34.2 36 32ZM11 21L16 27.02L23 18L32 30H4L11 21Z"
        fill="currentColor" />
    </svg>
  </div>

</div>