Search
Quick Commands
run:diagnostics Run all system checks
db:connect Connect to primary DB
cache:clear Clear application cache
users:list Show all active users
Notifications

Stay on top of recent system events and updates.

  • Notification avatar
    System Update Available

    Version 2.4.1 is ready to install with new features.

    2 minutes ago

  • AB
    New User Registration

    Alex Brown from Canada has joined the platform.

    15 minutes ago

  • Notification avatar
    Backup Completed

    Daily backup has been successfully completed.

    1 hour ago

  • Notification avatar
    Security Alert

    Unusual login activity detected from new location.

    3 hours ago

  • Notification avatar
    Monthly Report Ready

    Your analytics report for September is now available.

    Yesterday

  • MJ
    Server Maintenance

    Scheduled maintenance will begin at 2:00 AM EST.

    2 days ago

Bootstrap Scrollspy

Automatically update navigation links based on scroll position. The sidebar navigation highlights the current section as you scroll through the content.


info How Scrollspy Works

Standard Implementation: In a typical website, the <body> element is the scrolling container. Bootstrap Scrollspy listens to scroll events on the body and automatically highlights the corresponding navigation links based on the current viewport position.

Admin Dashboard Implementation: In the UltraViolet admin layout, the <body> doesn't scroll. Instead, the .ultraviolet-content div is the scrolling element. This is a common pattern in fixed-layout dashboards with sticky headers and sidebars.

The Solution: According to the Bootstrap documentation, Scrollspy can work with any scrollable container by:

  1. Creating a dedicated scrollable div with overflow-y: auto and a max-height
  2. Adding the scrollspy data attributes to that specific div (not the body)
  3. Keeping the navigation sidebar outside the scrolling container with position: sticky

Key Insight: Scrollspy must be applied to the actual scrolling element. In this page, that's the div you're currently scrolling in (with max-height: calc(100vh - 200px)), not the page body.


Standard Scrollspy Implementation

For typical websites where the <body> element scrolls, the standard Bootstrap Scrollspy implementation is straightforward:

HTML Structure - Standard Body Scroll
<body data-bs-spy="scroll" data-bs-target="#navbar" data-bs-smooth-scroll="true" tabindex="0">
    <nav id="navbar" class="navbar">
        <ul class="nav nav-pills">
            <li class="nav-item">
                <a class="nav-link" href="#section1">Section 1</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#section2">Section 2</a>
            </li>
            <li class="nav-item">
                <a class="nav-link" href="#section3">Section 3</a>
            </li>
        </ul>
    </nav>

    <div class="container">
        <section id="section1">
            <h2>Section 1 Content</h2>
            <p>Your content here...</p>
        </section>
        
        <section id="section2">
            <h2>Section 2 Content</h2>
            <p>Your content here...</p>
        </section>
        
        <section id="section3">
            <h2>Section 3 Content</h2>
            <p>Your content here...</p>
        </section>
    </div>
</body>
warning Important: This standard approach won't work in the UltraViolet admin dashboard because the body doesn't scroll!

Admin Dashboard Implementation

In the UltraViolet admin dashboard, we need a different approach because the layout uses a fixed header and the body doesn't scroll. Here's how to implement scrollspy in this environment:

HTML Structure - Custom Scrollable Container
@extends("layouts.admin")

@section("content")
    <div class="row">
        <!-- Main Content Column with Scrollspy -->
        <div class="col-md-9">
            <div data-bs-spy="scroll" 
                 data-bs-target="#tableOfContents" 
                 data-bs-smooth-scroll="true"
                 class="scrollspy-example" 
                 tabindex="0"
                 style="max-height: calc(100vh - 200px); overflow-y: auto; position: relative;">
                
                <section id="introduction">
                    <h2>Introduction</h2>
                    <p>Your content here...</p>
                </section>
                
                <section id="features">
                    <h2>Features</h2>
                    <p>Your content here...</p>
                </section>
            </div>
        </div>

        <!-- Sticky Sidebar Navigation -->
        <div class="col-md-3">
            <nav id="tableOfContents" class="nav nav-pills flex-column sticky-sidebar">
                <a class="nav-link" href="#introduction">Introduction</a>
                <a class="nav-link" href="#features">Features</a>
            </nav>
        </div>
    </div>
@endsection
Required CSS Styles
/* Make the sticky sidebar actually stick */
.sticky-sidebar {
    position: sticky;
    top: 20px;
    align-self: flex-start;
}

/* Style the active link */
.nav-pills .nav-link.active {
    background-color: #0d6efd;
    color: white;
}

.nav-pills .nav-link {
    color: var(--bs-body-color);
}

.nav-pills .nav-link:hover {
    background-color: rgba(13, 110, 253, 0.1);
}

/* Add spacing between sections for better scroll tracking */
section {
    padding-top: 50px;
    padding-bottom: 50px;
}
check_circle Key Points:
  • The scrollspy attributes are on the scrollable div, not the body
  • The sidebar is outside the scrolling container
  • Use max-height: calc(100vh - 200px) to fill viewport minus header space
  • The tabindex="0" attribute makes the div keyboard-accessible

JavaScript Initialization (Optional)

While the data attributes are sufficient for most use cases, you can also initialize scrollspy programmatically with JavaScript for more control:

JavaScript Initialization
// Initialize scrollspy programmatically
document.addEventListener('DOMContentLoaded', function() {
    const scrollSpyElement = document.querySelector('[data-bs-spy="scroll"]');
    
    if (scrollSpyElement && typeof bootstrap !== 'undefined') {
        const scrollSpy = new bootstrap.ScrollSpy(scrollSpyElement, {
            target: '#tableOfContents',
            smoothScroll: true,
            rootMargin: '0px 0px -40%',  // Trigger earlier/later
            threshold: 0.5                // How much of element must be visible
        });
    }
});

Scrollspy Options

Available Configuration Options
Option Type Default Description
target string | Element null Specifies element to apply scrollspy to (usually your nav)
rootMargin string '0px 0px -25%' Offset for intersection observer (when to trigger active state)
smoothScroll boolean false Enables smooth scrolling when clicking nav links
threshold number | array [0.1, 0.5, 1] Intersection observer threshold values

Nested Navigation

You can also create nested navigation for sub-sections:

Nested Nav Example
<nav id="tableOfContents" class="nav nav-pills flex-column sticky-sidebar">
    <a class="nav-link" href="#item-1">Item 1</a>
    <a class="nav-link" href="#item-2">Item 2</a>
    <a class="nav-link" href="#item-3">Item 3</a>
    
    <!-- Nested sub-navigation -->
    <nav class="nav nav-pills flex-column ps-3">
        <a class="nav-link" href="#item-3-1">Sub-item 3.1</a>
        <a class="nav-link" href="#item-3-2">Sub-item 3.2</a>
    </nav>
    
    <a class="nav-link" href="#item-4">Item 4</a>
</nav>

Best Practices & Troubleshooting

Follow these guidelines to ensure your scrollspy implementation works correctly in the admin dashboard:

tips_and_updates Best Practices
  • Section IDs: Ensure all sections have unique id attributes that match the href values in your nav links
  • Section Spacing: Add adequate padding to sections (e.g., padding-top: 50px) to ensure proper scroll tracking
  • Sidebar Position: Keep the sidebar outside the scrolling container for sticky behavior to work
  • Viewport Height: Use calc(100vh - XXXpx) to account for headers, breadcrumbs, and padding
  • Accessibility: Always include tabindex="0" on scrollable divs for keyboard navigation
bug_report Common Issues & Solutions

Problem: The sidebar scrolls away with the content.
Solution: Ensure the sidebar is outside the scrolling div and has position: sticky with align-self: flex-start in the CSS.

Problem: The active link doesn't change when scrolling.
Solution: Make sure scrollspy attributes are on the actual scrolling element, not the body. In admin dashboard, this is the div with overflow-y: auto.

Problem: Empty space at the bottom of the page.
Solution: Use max-height instead of fixed height, and adjust the calculation (e.g., calc(100vh - 200px)) to account for header/breadcrumb space.

Problem: Navigation links don't respond to clicks.
Solution: Ensure your nav links use proper anchor tags with href="#section-id" format, and include data-bs-smooth-scroll="true" for smooth scrolling.
school Learn More: Visit the official Bootstrap Scrollspy Documentation for more advanced configurations and examples.