Skeleton

Frontbx's skeleton component lets you quickly display a placeholder preview of your content before the data gets loaded to reduce load-time and improve user experience on Pjax or Ajax requests.



Markup

Skeletons are simple to create, simply create an element with the .skeleton class inside a component.

Note that Skeletons by default with fill all available vertical and horizontal space inside their container. If you're placing a skeleton inside an empty column or a container without a height you'll need to either specify a height on the container or on the skeleton itself.

The example below shows the markup for a skeleton using a simple card:

<div class="card">
    <div class="card-header">
        <div class="card-header-left">
            <div class="skeleton skeleton-circle skeleton-wave" style="width: 40px; height: 40px;"></div>
        </div>
        <div class="card-header-content">
            <div class="skeleton-text-block skeleton-lines">
                <div class="skeleton" style="width: 71%;"></div>
                <div class="skeleton" style="width: 81%;"></div>
            </div>
        </div>
    </div>
    <div class="card-media">
        <div class="skeleton skeleton-block skeleton-wave" style="width: 100%; height: auto; aspect-ratio: 16 / 9;"></div>
    </div>
    <div class="card-block">
        <div class="skeleton skeleton-h5"></div>
        <div class="skeleton-text-block skeleton-lines">
            <div class="skeleton" style="width: 81%;"></div>
            <div class="skeleton" style="width: 84%;"></div>
            <div class="skeleton" style="width: 91%;"></div>
        </div>
    </div>
</div>

Base Variants

Skeletons come in a few different base variants .skeleton-wave, .skeleton-text, .skeleton-rounded, .skeleton-btn, .skeleton-input, .skeleton-circle and via modifier classes.

The table below outlines their core styles

Class Behavior
.skeleton-wave Sets skeleton animation to a wave effect. Good for images
.skeleton-text Sets skeleton to height of body copy with matching margins with addition of rounded corners
.skeleton-rounded Sets rounded corners on a skeleton
.skeleton-btn Creates a rectangular fixed height and width skeleton to match Frontbx button sizing
.skeleton-input Creates a rectangular fixed height skeleton to match Frontbx input sizing
.skeleton-circle Sets skeleton to a circle. Width and height can adjusted via modifier sizes or overridden manually
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-circle"></div>
<div class="skeleton skeleton-wave"></div>
<div class="skeleton skeleton-rounded"></div>
<div class="skeleton skeleton-input"></div>
<div class="skeleton skeleton-btn"></div>

.skeleton-circle comes in three modifier sizes .circle-sm, .circle-md and .circle-lg

<div class="skeleton skeleton-circle circle-sm"></div>
<div class="skeleton skeleton-circle circle-md"></div>
<div class="skeleton skeleton-circle circle-lg"></div>

Text

To display text and the .skeleton-text modifier class. The sizing, height and line height will match Frontbx's typography configurations:

Lorem ipsum dolore excepteur culpa sit.

Lorem ipsum velit amet officia minim fugiat.

Cillum laboris do est.

<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>
<div class="skeleton skeleton-text"></div>

To display text headings add the appropriate heading .skeleton-h[num] modifier class. The sizing, height and line height will match Frontbx's typography configurations:

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6
<div class="skeleton skeleton-h1"></div>
<div class="skeleton skeleton-h2"></div>
<div class="skeleton skeleton-h3"></div>
<div class="skeleton skeleton-h4"></div>
<div class="skeleton skeleton-h5"></div>
<div class="skeleton skeleton-h6"></div>

Text Blocks

For multi-line text blocks, wrap skeletons in a .skeleton-text-block element.

Aliquip veniam eu enim quis sit nisi enim exercitation ad irure sunt ut pariatur, cillum reprehenderit do duis voluptate proident dolor sint duis. Id commodo cupidatat minim labore elit officia eu officia eu velit sunt veniam. Quis aute minim dolore voluptate nisi ut aliquip et exercitation commodo nisi enim sunt labore et nulla enim in minim consequat ea velit dolore reprehenderit aute anim voluptate consectetur magna enim consectetur fugiat in occaecat magna dolor culpa elit.

<div class="skeleton-text-block">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
    ...
</div>

For multi-line heading use the same .skeleton-text-block wrapper with the appropriate heading modifier .skeleton-text-block-h[num]:

Lorem ipsum voluptate eiusmod.

<div class="skeleton-text-block skeleton-text-block-h1">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
</div>

Lorem ipsum voluptate eiusmod.

<div class="skeleton-text-block skeleton-text-block-h2">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
</div>

Lorem ipsum voluptate eiusmod velit.

<div class="skeleton-text-block skeleton-text-block-h3">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
</div>

Lorem ipsum voluptate eiusmod velit excepteur quis ullamco.

<div class="skeleton-text-block skeleton-text-block-h4">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
</div>
Lorem ipsum voluptate eiusmod velit excepteur quis ullamco.
<div class="skeleton-text-block skeleton-text-block-h5">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
</div>
Eu cupidatat cupidatat ut consequat non cupidatat qui irure magna sunt ullamco eu non consectetur.
<div class="skeleton-text-block skeleton-text-block-h6">
    <div class="skeleton"></div>
    <div class="skeleton"></div>
</div>

To align skeleton text to the right, add the text-right modifier to the wrapping element

In culpa voluptate laboris adipisicing.

In sed do incididunt labore magna elit ut consectetur do laborum ullamco do adipisicing mollit occaecat ad.

Enim veniam voluptate sunt non.

Incididunt amet nostrud in dolor aliquip in officia do ut duis incididunt ex ut.

<div class="skeleton-text-block skeleton-text-block-h3 text-right">
    <div class="skeleton"></div>
</div>
<div class="skeleton-text-block text-right">
    <div class="skeleton"></div>
</div>
<div class="skeleton-text-block skeleton-text-block-h4 text-right">
    <div class="skeleton"></div>
</div>
<div class="skeleton-text-block text-right">
    <div class="skeleton"></div>
</div>

Variant Examples

Try the example below create a few skeletons


JavaScript Utility

Frontbx comes with a handy JavaScript utility component for creating skeletons on the fly. You can create a skeleton by calling Skeleton via the container.

Usage

const skeleton = frontbx.Skeleton(DOMElement, options);

The component will build the skeleton(s) with the supplied options and append them to the the DOMElement.

Once you have created a Skeleton instance, you can destroy it via the destroy method. The skeleton(s) will be removed from the DOMElement wrapper.

skeleton.destroy();

If you want to fade out skeletons before destroying use the fade_out method. An optional callback can be supplied once the animation completes:

skeleton.fade_out(callback);

If you only want the skeleton(s) to fade out and want to destroy them manually, add a second argument as false:

skeleton.fade_out(callback, false);

Options

The table below outlines the available options:

Option Type Default Values
count integer 1 Number of skeletons to generate.
lines integer 1 Optional value number of lines for Text Block variants.
variant string block block text btn input circle wave rounded h1 h2 h3 h4 h5 h6 text-block block-h1 block-h2 block-h3 block-h4 block-h5 block-h6
width string null Any CSS width value
height string null Any CSS height value
aspectratio string null If provided will make skeleton width responsive while retaining aspect ratio. Value should be provided as w/h e.g 16/9.

Multi-variant values should be supplied as a single string separated by spaces. e.g for a wave block skeleton with rounded corners you would supply block wave rounded as the variant value.

const options  = {
    count: 5,
    variant: 'block wave rounded',
    width: '100%',
    height: '60px'
};

const skeleton = frontbx.Skeleton(DOMElement, options);

When creating a multi-line text-block variant (text-block block-h1 block-h2 block-h3 block-h4 block-h5 block-h6), any other options apart from count or lines will be ignored.

There are no modifier options for these skeletons. Additionally, the JS component will set a random width on each skeleton to give a natural text paragraph look.

const options  = {
    lines: 3,
    variant: 'text-block',
};

const skeleton = frontbx.Skeleton(DOMElement, options);

You can also provide options as an array to add multiple skeletons to single container element:

const options = [
    { lines: 2, variant: 'h3-block' },
    { lines: 6, variant: 'text-block' },
];

const skeleton = frontbx.Skeleton(DOMElement, options);

Or if you need more control to a layout you can provide an optional child selector key for each variant-set. The skeleton will get inserted into the the selector element rather than the parent wrapper element.

const options = [
    { selector: '.js-heading', lines: 2, variant: 'h3-block'},
    { selector: '.js-text', lines: 6, variant: 'text-block' },
];
const skeleton = frontbx.Skeleton(DOMElement, options);

Loading Content

Once you have reference to a Skeleton instance, you can gracefully load your own content in via the load method.

The method accepts both html as a string or an HTMLDomElement node with an optional callback when the animation completes.

let content = '<div>...</div>';

const callback = () => console.log('Complete!');

skeleton.load(content, callback);

When calling load on a multi-instance Skeleton, provide an object with the selector as key to replace the content:

let content =
{
    '.title' : '<div>...</div>',
    '.text'  : '<p>...</p>',
    '.image' :  document.createElement('IMG'),
};

skeleton.load(content);

The example below shows swapping out the contents of card component. Click the Load content button to try it out.

const [find]       = frontbx.import(['find']).from('_');
const cardWrapper  = find('.js-skeleton-loader-card');
const options      = 
{
    '.js-card-header-left' : '<div class="avatar"><img ... /></div>',
    '.js-card-header-content' : '<div class="text-bold">...</div>',
    '.js-card-media' : '<img ... />',
    '.js-card-title' : '<h5>...</h5>',
    '.js-card-text' : '<p>...</p>',
};

frontbx.Skeleton(cardWrapper).load(options);

CSS Customization

Skeleton uses local CSS variables on all .skeleton for enhanced component customization and styling. The base values are used by the UI to create all the sizing. Values for the CSS variables are set via Sass, so pre-compilation customization is still supported too.

Default values are set in the scss/_config.scss file in Frontbx's source.

scss/_config.scss
$skeleton-bg-1:                 rgba(0, 0, 0, 0.2) !default;
$skeleton-bg-2:                 rgba(0, 0, 0, 0.4) !default;
$skeleton-text-radius:          var(--fbx-border-radius) !default;


scss/components/_skeleton.scss
.skeleton
{
    --fbx-skeleton-bg-1: rgba(0, 0, 0, 0.2);
    --fbx-skeleton-bg-2: rgba(0, 0, 0, 0.4);
    --fbx-bg-animation: 1s ease-in-out infinite normal none running skeleton-pulse;
    --fbx-skeleton-width: 100%;
    --fbx-skeleton-height: 100%;
    --fbx-skeleton-radius: 0;
    --fbx-skeleton-margin: 0;
    --fbx-skeleton-display: block;
}

The example below shows customization using CSS Variables:

.skeleton
{
    --fbx-skeleton-bg-1: var(--fbx-theme-primary-300);
    --fbx-skeleton-bg-2: var(--fbx-theme-primary-600);
}