Bootstrap 5 Tutorial

v5.3.0

Bootstrap 5 Tutorial

Spinners in Bootstrap 5

Spinners: Indicate loading state of a component or page with Bootstrap spinners.

Border Spinner

Border Spinner (Default)
Loading...
<!-- Border spinner -->
            <div class="spinner-border" role="status">
            <span class="visually-hidden">Loading...</span>
            </div>

Spinner Colors

Color Variations
<!-- Color variations -->
            <div class="spinner-border text-primary" role="status"></div>
            <div class="spinner-border text-secondary" role="status"></div>
            <div class="spinner-border text-success" role="status"></div>
            <div class="spinner-border text-danger" role="status"></div>
            <div class="spinner-border text-warning" role="status"></div>
            <div class="spinner-border text-info" role="status"></div>
            <div class="spinner-border text-dark" role="status"></div>

Growing Spinner

Border Spinner
Loading...
spinner-border
Growing Spinner
Loading...
spinner-grow

Growing Spinner Colors

Growing Spinner Variations
<!-- Growing spinner colors -->
            <div class="spinner-grow text-primary" role="status"></div>
            <div class="spinner-grow text-secondary" role="status"></div>
            <div class="spinner-grow text-success" role="status"></div>
            <div class="spinner-grow text-danger" role="status"></div>
            <div class="spinner-grow text-warning" role="status"></div>
            <div class="spinner-grow text-info" role="status"></div>
            <div class="spinner-grow text-dark" role="status"></div>

Spinner Sizes

Size Options
Small (spinner-border-sm)
Default (2rem)
Large (3rem)
Extra Large (5rem)
Growing Spinner Sizes
<!-- Size variations -->

            <!-- Small -->
            <div class="spinner-border spinner-border-sm"></div>
            <div class="spinner-grow spinner-grow-sm"></div>

            <!-- Custom sizes -->
            <div class="spinner-border" style="width: 3rem; height: 3rem;"></div>
            <div class="spinner-grow" style="width: 3rem; height: 3rem;"></div>

            <!-- Extra large -->
            <div class="spinner-border" style="width: 5rem; height: 5rem;"></div>

Spinners with Text

Spinner with Loading Text
Loading...
Please wait while we process your request...
<!-- Spinner with text -->
            <div class="d-flex align-items-center">
            <div class="spinner-border text-primary me-3" role="status"></div>
            <strong>Loading...</strong>
            </div>

            <!-- Spinner in button -->
            <button class="btn btn-primary" disabled>
            <span class="spinner-border spinner-border-sm me-2" role="status"></span>
            Loading...
            </button>

            <!-- Growing spinner with text -->
            <div class="d-flex align-items-center">
            <div class="spinner-grow text-success me-3" role="status"></div>
            <span>Processing...</span>
            </div>

Interactive Example

Dynamic Spinner Demo
Content Loaded Successfully!

Your data has been loaded and is ready to view.

// React/JavaScript code for interactive spinner
            const [loading, setLoading] = useState(false);
            const [size, setSize] = useState('default');

            const toggleLoading = () => {
            setLoading(!loading);
            };

            const simulateLoad = () => {
            setLoading(true);
            setTimeout(() => setLoading(false), 3000);
            };

            // HTML Structure
            {loading ? (
            <div class="spinner-border text-primary" role="status">
                <span class="visually-hidden">Loading...</span>
            </div>
            ) : (
            <div>Content loaded</div>
            )}

            <button onclick="simulateLoad()">Start Loading</button>
            <button onclick="toggleLoading()">Toggle Loading</button>

Real-World Examples

Practical Use Cases
Form Submission
Data Table Loading
IDNameStatus
1John DoeActive
Content Loading
Page Loading
Loading Dashboard

Please wait while we prepare your dashboard...

Accessibility Features

Accessibility Best Practices
  • Always include role=&qout;status&qout;
  • Use aria-label or text content for screen readers
  • Include visually-hidden text for better accessibility
  • Ensure spinners don't create flashing that could trigger seizures
  • Provide alternative content when spinner is hidden
  • Test with screen readers

Custom Styling

Custom Dual Spinner
Pulse Animation
/* Custom CSS for spinners */

            .custom-spinner {
            width: 4rem;
            height: 4rem;
            border: 0.5em solid transparent;
            border-top-color: #3498db;
            border-right-color: #3498db;
            border-radius: 50%;
            animation: custom-spin 1s linear infinite;
            }

            .custom-spinner-inner {
            width: 100%;
            height: 100%;
            border: 0.25em solid transparent;
            border-top-color: #e74c3c;
            border-radius: 50%;
            animation: custom-spin-reverse 0.5s linear infinite;
            }

            @keyframes custom-spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
            }

            @keyframes custom-spin-reverse {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(-360deg); }
            }

            .pulse-spinner {
            width: 3rem;
            height: 3rem;
            background-color: #9b59b6;
            border-radius: 50%;
            animation: pulse 1s ease-in-out infinite;
            }

            @keyframes pulse {
            0%, 100% { transform: scale(1); opacity: 1; }
            50% { transform: scale(1.2); opacity: 0.7; }
            }

JavaScript Integration

JavaScript API Examples
// JavaScript for dynamic spinner control

            // Show spinner
            function showSpinner(spinnerId) {
            const spinner = document.getElementById(spinnerId);
            spinner.style.display = 'block';
            spinner.setAttribute('aria-hidden', 'false');
            }

            // Hide spinner
            function hideSpinner(spinnerId) {
            const spinner = document.getElementById(spinnerId);
            spinner.style.display = 'none';
            spinner.setAttribute('aria-hidden', 'true');
            }

            // Toggle spinner
            function toggleSpinner(spinnerId) {
            const spinner = document.getElementById(spinnerId);
            const isHidden = spinner.style.display === 'none';
            spinner.style.display = isHidden ? 'block' : 'none';
            spinner.setAttribute('aria-hidden', isHidden ? 'false' : 'true');
            }

            // Show spinner during AJAX request
            function fetchWithSpinner(url, spinnerId) {
            showSpinner(spinnerId);
            
            fetch(url)
                .then(response => response.json())
                .then(data => {
                hideSpinner(spinnerId);
                processData(data);
                })
                .catch(error => {
                hideSpinner(spinnerId);
                showError(error);
                });
            }

            // Button click handler with spinner
            document.getElementById('submitBtn').addEventListener('click', function() {
            const button = this;
            const originalText = button.innerHTML;
            
            // Show spinner in button
            button.innerHTML = `
                <span class="spinner-border spinner-border-sm me-2" role="status"></span>
                Loading...
            `;
            button.disabled = true;
            
            // Simulate API call
            setTimeout(() => {
                button.innerHTML = originalText;
                button.disabled = false;
                showSuccessMessage();
            }, 2000);
            });

            // Show full page spinner
            function showFullPageSpinner() {
            const spinner = document.createElement('div');
            spinner.id = 'fullPageSpinner';
            spinner.className = 'position-fixed top-0 left-0 w-100 h-100 d-flex justify-content-center align-items-center bg-dark bg-opacity-75';
            spinner.style.zIndex = '9999';
            spinner.innerHTML = `
                <div class="text-center">
                <div class="spinner-border text-light" style="width: 4rem; height: 4rem;" role="status">
                    <span class="visually-hidden">Loading...</span>
                </div>
                <p class="text-light mt-3">Loading, please wait...</p>
                </div>
            `;
            document.body.appendChild(spinner);
            }

            // Hide full page spinner
            function hideFullPageSpinner() {
            const spinner = document.getElementById('fullPageSpinner');
            if (spinner) {
                spinner.remove();
            }
            }