Skip to content

Bootstrap Spinners

Spinners indicate that content is loading or an action is processing. This lesson covers the two spinner styles, sizing, color variants, and accessible usage inside buttons.

Bootstrap Spinners Overview

Bootstrap offers two spinner styles: .spinner-border, a rotating ring, and .spinner-grow, a pulsing dot that grows and fades. Both accept the same theme color classes (text-primary, text-success, and so on) used elsewhere in Bootstrap, and both include a visually-hidden 'Loading...' span by default for screen reader users.

Spinners are commonly placed inside buttons to indicate an in-progress action, combined with the disabled attribute to prevent duplicate submissions, or sized down with spinner-border-sm and spinner-grow-sm for more compact contexts.

Concept Description Common Usage
.spinner-border Rotating ring loading indicator General-purpose loading state
.spinner-grow Pulsing, growing dot indicator Alternative, softer loading style
spinner-*-sm Smaller sized spinner variant Inline use inside buttons or small UI
text-{color} on spinners Theme color applied to the spinner Matching spinner color to surrounding UI
visually-hidden loading text Screen-reader-only status text Accessible loading announcement

Bootstrap Spinners Example

<div class="spinner-border text-primary" role="status">
  <span class="visually-hidden">Loading...</span>
</div>

<button class="btn btn-primary" type="button" disabled>
  <span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span>
  Saving...
</button>

<div class="spinner-grow text-success" role="status">
  <span class="visually-hidden">Loading...</span>
</div>

The first spinner is a standalone loading ring with visually-hidden text describing its purpose for screen readers. The button example combines a small spinner-border-sm with the disabled attribute and visible 'Saving...' text to clearly communicate an in-progress action. The final example shows the alternative spinner-grow style with a success color.

Top 10 Bootstrap Spinners Examples

These are the spinner patterns you'll use to indicate loading and processing states.

# Example Syntax
1 Basic border spinner <div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div>
2 Growing spinner <div class="spinner-grow" role="status"><span class="visually-hidden">Loading...</span></div>
3 Small spinner <div class="spinner-border spinner-border-sm"></div>
4 Colored spinner <div class="spinner-border text-success"></div>
5 Spinner inside a button <button class="btn btn-primary" disabled><span class="spinner-border spinner-border-sm"></span> Loading</button>
6 Spinner with custom size <div class="spinner-border" style="width: 3rem; height: 3rem;"></div>
7 Centered page spinner <div class="d-flex justify-content-center"><div class="spinner-border"></div></div>
8 Spinner with aria-hidden icon usage <span class="spinner-border spinner-border-sm" aria-hidden="true"></span>
9 Multiple color spinners row <div class="spinner-grow text-warning"></div>
10 Full-page loading overlay spinner <div class="position-fixed top-50 start-50 translate-middle"><div class="spinner-border text-primary"></div></div>

Best Practices

  • Always include a visually-hidden 'Loading...' span (or similar) inside standalone spinners.
  • Disable buttons while their spinner is visible to prevent duplicate submissions.
  • Match spinner color to the surrounding button or theme context using text-{color} classes.
  • Use spinner-border-sm inside compact UI like buttons, and full-size spinners for page-level loading.
  • Pair a spinner with visible text ('Saving...', 'Loading...') for extra clarity beyond the animation alone.
  • Center full-page spinners using flex utilities instead of custom positioning CSS.
  • Remove or hide the spinner promptly once the underlying action completes.

Common Mistakes

  • Leaving out the visually-hidden loading text, so screen readers announce nothing meaningful.
  • Forgetting to disable the button while a spinner shows, allowing repeated clicks and duplicate requests.
  • Using spinner-grow and spinner-border inconsistently across similar loading states in the same app.
  • Not resetting the button back to its normal state if the request fails.
  • Using an oversized spinner inside a small button, breaking the layout.
  • Relying solely on a spinner with no fallback timeout message for very slow requests.

Key Takeaways

  • spinner-border and spinner-grow are Bootstrap's two built-in loading indicator styles.
  • Sizing modifiers and theme colors adapt spinners to buttons or full-page contexts.
  • Accessible spinners always include a visually-hidden status text.
  • Disabling the triggering button while a spinner shows prevents duplicate actions.
  • Spinners should be removed promptly once the underlying task finishes or fails.

Pro Tip

For network requests that might take a while, pair the spinner with a timeout-based fallback message like 'Still working...' after a few seconds, so users don't assume the app has frozen.