<h5>Loading Graphic | Page</h5>
<div class="has-loader style-guide__loading-indicator">
    <div class="style-guide__loader-content">Some Content</div>
    <div class="loading-graphic__container loading-graphic__container--overlay" role="alert" aria-live="assertive">
        <div class="loading-graphic__inner">
            <div class="loading-graphic__rings"></div>
            <p class="u-sr-only">Content is loading...</p>
        </div>
    </div>
</div>

<h5>Loading Graphic | Text Input</h5>
<form class="sample-inputs">
    <fieldset class="has-loader full">
        <div class="input__wrapper input__wrapper--loading sample-search-wrap" role="alert" aria-live="polite">
            <label for="searchSampleL">Search (With Label)</label>
            <input type="search" name="searchSampleL">
            <div class="loading-graphic__container loading-graphic__container--sm">
                <div class="loading-graphic__inner">
                    <div class="loading-graphic__rings"></div>
                    <p class="u-sr-only">Content is loading...</p>
                </div>
            </div>
        </div>
    </fieldset>
</form>
<h5>Loading Graphic | Page</h5>
<div class="has-loader style-guide__loading-indicator">
	<div class="style-guide__loader-content">Some Content</div>
	<div class="loading-graphic__container loading-graphic__container--overlay" role="alert" aria-live="assertive">
		<div class="loading-graphic__inner">
			<div class="loading-graphic__rings"></div>
			<p class="u-sr-only">Content is loading...</p>
		</div>
	</div>
</div>

<h5>Loading Graphic | Text Input</h5>
<form class="sample-inputs">
	<fieldset class="has-loader full">
		<div class="input__wrapper input__wrapper--loading sample-search-wrap" role="alert" aria-live="polite">
			<label for="searchSampleL">Search (With Label)</label>
			<input type="search" name="searchSampleL">
			<div class="loading-graphic__container loading-graphic__container--sm">
				<div class="loading-graphic__inner">
					<div class="loading-graphic__rings"></div>
					<p class="u-sr-only">Content is loading...</p>
				</div>
			</div>
		</div>
	</fieldset>
</form>
/* No context defined for this component. */
  • Content:
    @keyframes rotate-360 {
      0%   { transform: rotate(0deg); }
      100% { transform: rotate(360deg); }
    }
    
    .input {
    
      &__wrapper {
        position: relative;
        padding: 0;
      }
    }
    
    .loading-graphic {
    
      &__container {
        z-index: z-index(overlay);
        display: none;
        transition: opacity $transition-duration, visibility $transition-duration;
    
        &--sm {
    
          .loading-graphic__rings,
          .loading-graphic__rings::before,
          .loading-graphic__rings::after { border-width: 1px; }
    
          .loading-graphic__rings {
            width: 26px;
            height: 26px;
          }
    
          .loading-graphic__rings::before {
            top: 3px;
            right: 3px;
            bottom: 3px;
            left: 3px;
          }
    
          .loading-graphic__rings::after {
            top: 7px;
            right: 7px;
            bottom: 7px;
            left: 7px;
          }
        }
    
        &--overlay {
          position: absolute;
          top: 0;
          right: 0;
          bottom: 0;
          left: 0;
    
          &::before {
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
            display: block;
            background-color: rgba(color(default, light),.75);
            content: '';
          }
    
          &--fixed {
            position: fixed;
          }
        }
    
        .input__wrapper--loading & {
          position: absolute;
          right: 15px; // corresponds to standard input padding-right
          bottom: 15px;
          width: 26px; // needs dimensions when not horizontally and vertically centered
          height: 26px; // needs dimensions when not horizontally and vertically centered
        }
      }
    
      &__inner {
        z-index: z-index(overlay) + 1;
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
      }
    
      &__rings {
        border-radius: 50%;
        border: 3px solid transparent;
        border-top-color: color(primary, base);
        width: 100px;
        height: 100px;
        animation: rotate-360 2s linear infinite;
    
        &::before,
        &::after {
          position: absolute;
          border-radius: 50%;
          border: 3px solid transparent;
          content: '';
        }
    
        &::before {
          top: 8px;
          right: 8px;
          bottom: 8px;
          left: 8px;
          border-top-color: color(primary, base);
          animation: rotate-360 3s linear infinite;
        }
    
        &::after {
          top: 20px;
          right: 20px;
          bottom: 20px;
          left: 20px;
          border-top-color: color(primary, base);
          animation: rotate-360 4s linear infinite;
        }
      }
    }
    
    
    /*
     *   loading states
     *
     ***************************************************/
    
    // given to the parent container of a page, section, or element that is currently loading
    .has-loader {
      position: relative;
    
      .loading-graphic__container { display: block; }
    }
    
  • URL: /components/raw/loading-indicator/_loading-indicator.scss
  • Filesystem Path: components/loading-indicator/_loading-indicator.scss
  • Size: 2.7 KB

Usage

A loading graphic can appear when a page, section or component is in a loading state.

Loading graphics should include u-sr-only text to inform screen reader users what is going on. Additionally, loading graphics should exist in the DOM before the spinner is required because the change or addition of content inside these elements trigger the screen reader notification, not the addition of those attributes on the element.

The default styles for this loading graphic accomodate full page loaders, and the loading-graphic--sm modifier class should be included for inline loaders.

The state class has-loader can be dynamically given to the body or the parent container of a section or component while it is in a loading state.

Labelling Expectations

  • Each graphic container should have an aria-live attribute to create an accessible alert event.
  • For full page loading graphics, use aria-live="assertive" to immediately communicate to users to changes on the page.
  • For inline loading graphics, such as a search bar loader, use aria-live="polite" to update users at a graceful interval, when the stop typing in the search bar, for example.