Adjust the classes of the static navigation bar based on the background of the section it is positioned over

In the process of developing a website using Bootstrap 4, I encountered a challenge with sections featuring both light and dark backgrounds along with a fixed navbar.

The navbar, which is set to dark using the css class bg-dark, becomes indistinguishable against the dark background sections while being easily visible on the light ones.

To address this issue, I attempted to dynamically change the navbar's style from navbar-dark bg-dark to navbar-light bg-light when the user scrolls into a dark section. The solution provided on StackOverflow involved utilizing scroll spy functionality:

$(window).on('activate.bs.scrollspy', function (e,obj) {
    if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {
        return;
    }
    var isBGLight = $(obj.relatedTarget).hasClass('bg-light');
    $('.navbar').toggleClass('navbar-dark bg-dark', isBGLight)
                .toggleClass('navbar-light bg-light', !isBGLight);
});
.page-section {
  padding: 70px 10px
}

.page-section.bg-dark * {
  color: #fff;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

<body data-spy="scroll" data-target=".navbar" data-offset="15">
  <nav class="navbar navbar-expand-sm bg-dark navbar-dark fixed-top">
    <a class="navbar-brand" href="#">Logo</a>
    <ul class="navbar-nav ml-auto">
      <li class="nav-item">
        <a class="nav-link" href="about.html">About Us</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="services.html">Services</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="contact.html">Contact</a>
      </li>
    </ul>
  </nav>

  <div class="container-fluid bg-light page-section">
    <h1>Section 1</h1>
    <p>Try scrolling through this section and observe the navigation bar behavior! Try scrolling through this section and observe the navigation bar behavior!</p>
    <p>Try scrolling through this section and observe the navigation bar behavior! Try scrolling through this section and observe the navigation bar behavior!</p>
  </div>
  <div class="container-fluid bg-dark page-section">
    <h1>Section 2</h1>
    <p>Try scrolling through this section and observe the navigation bar behavior! Try scrolling through this section and observe the navigation bar behavior!</p>
    <p>Try scrolling through this section and observe the navigation bar behavior! Try scrolling through this section and observe the navigation bar behavior!</p>
  </div>
  <div class="container-fluid bg-light page-section">
    <h1>Section 3</h1>
    <p>Try scrolling through this section and observe the navigation bar behavior! Try scrolling through this section and observe the navigation bar behavior!</p>
    <p>Try scrolling through this section and observe the navigation bar behavior! Try scrolling through this section and observe the navigation bar behavior!</p>
  </div>
</body>

While my attempt with scroll-spy was helpful, it conflicted with its requirement for anchors to point to elements with an id, whereas my navbar's items directed users to other pages rather than sections within the same page.

I am seeking alternative solutions tailored to the scenario described above. Your input are highly appreciated!

Answer №1

Instead of bypassing Bootstrap scrollspy's rules, consider leveraging the "activate.bs.scrollspy" event to enhance functionality without overriding default navigation behavior with JavaScript code.

My recommendation is to reintroduce IDs to divs and corresponding fragment hrefs to anchors. Utilize Bootstrap to provide the target in the "activate.bs.scrollspy" event through obj.relatedTarget, toggle classes as required, and potentially remove the "activated" class from nav items for improved section delineation. For additional sections, consider hidden anchors or a concealed navigation menu.

In my opinion, a cleaner approach would involve abandoning scrollspy in favor of window.scrollY and $(window).on('scroll', ...).

Take a look at the following snippet:

$(window).on('activate.bs.scrollspy', function (e, obj) {
    if ((window.innerHeight + window.pageYOffset) >= document.body.offsetHeight) {
        return;
    }

    var isBGLight = $(obj.relatedTarget).hasClass('bg-light');
    $('.navbar').toggleClass('navbar-dark bg-dark', isBGLight)
                .toggleClass('navbar-light bg-light', !isBGLight);

    // Optional: Remove the active class from the anchor so it doesn't look like the nav is linked to the sections
    $('.navbar-nav a[href="' + obj.relatedTarget + '"]').removeClass('active');
});

// Here we handle the actual navigation
$('.navbar-nav a').click(function(e) {
    // Prevent anchor's default behavior of briefly jumping to the given section before navigating to another page
    e.preventDefault();
    // Substring to eliminate the leading "#"
    window.location.href = $(e.target).attr('href').substring(1) + '.html';
})
.page-section {
  padding: 70px 10px
}

.page-section.bg-dark * {
  color: #fff;
}
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>

<body data-spy="scroll" data-target=".navbar" data-offset="15">
  <nav class="navbar navbar-expand-sm bg-dark navbar-dark fixed-top">
    <a class="navbar-brand" href="#">Logo</a>
    <ul class="navbar-nav ml-auto">
      <li class="nav-item">
        <!-- Notice I changed the hrefs to point to the div ids -->
        <a class="nav-link" href="#about">About Us</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#services">Services</a>
      </li>
      <li class="nav-item">
        <a class="nav-link" href="#contact">Contact</a>
      </li>
    </ul>
  </nav>

  <!-- Notice I added the id's to let Bootstrap do its job -->
  <div id="about" class="container-fluid bg-light page-section">
    <h1>Section 1</h1>
    <p>Try to scroll this section and monitor the navigation bar while scrolling! Try to scroll this section and observe how the navigation bar behaves.</p>
    <p>Try to scroll this section and monitor the navigation bar while scrolling! Try to scroll this section and observe how the navigation bar behaves.</p>
  </div>
  <div id="services" class="container-fluid bg-dark page-section">
    <h1>Section 2</h1>
    <p>Try to scroll this section and monitor the navigation bar while scrolling! Try to scroll this section and observe how the navigation bar behaves.</p>
    <p>Try to scroll this section and monitor the navigation bar while scrolling! Try to scroll this section and observe how the navigation bar behaves.</p>
  </div>
  <div id="contact" class="container-fluid bg-light page-section">
    <h1>Section 3</h1>
    <p>Try to scroll this section and monitor the navigation bar while scrolling! Try to scroll this section and observe how the navigation bar behaves.</p>
    <p>Try to scroll this section and monitor the navigation bar while scrolling! Try to scroll this section and observe how the navigation bar behaves.</p>
  </div>
</body>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Extracting Tailwind color palette through API request

After conducting some research, I have not been able to find a definitive answer to my query. I possess a CMS API that supplies branding colors and other assets for a React application that can dynamically change its appearance using a combination of colo ...

An issue has been detected where the bullet list is uneven due to the CSS property/value columns being set

Is there a more effective way to split a bulleted list into two columns than the method I am currently using and ensure that the columns are aligned at the top? .hand-bullet-list ul{ list-style-type: none; margin-left: 0px; } .hand-bullet-list ...

Having Trouble with Your CSS Styles?

After working with HTML and CSS for over 5 years, I find myself stumped by this particular issue. At the provided URL, there is a single div in that container with an ID of Clarity. The CSS rules I have implemented are as follows: #clarity { text-align: ...

Discover the nodes with the highest connections in a D3 Force Graph

As I explore the functionalities of a D3 Force Directed Graph with zoom and pan features, I encounter an issue due to my limited knowledge of d3.js. Is there a way to estimate the number of links for each node in this scenario? I am currently at a loss on ...

How can we prevent Material-UI and Redux-form from re-rendering when an option is clicked in the select input?

I am facing an issue with rendering options dynamically. Whenever I click on the select or the options, the component re-renders and changes the options. As a result, I need to click twice to select an option in the dropdown. This re-rendering is happening ...

"Challenges with Full-Width Dropdowns in Multi-level Mega Menus

I am currently attempting to design a multi-level mega menu that spans the full width of the screen, while keeping the content within it restricted to a maximum width of 1240px. I have managed to set the content to the maximum width, but I am facing challe ...

Choosing the primary camera on a web application with multiple rear cameras using WebRTC

Having a bit of trouble developing a web app that can capture images from the browser's back camera. The challenge lies in identifying which camera is the main one in a multi-camera setup. The issue we're running into is that each manufacturer u ...

Using ReactJS to send formData to an Express API and retrieving a JSON response

Attempting to have the ReactJS frontend send a username and password from a form to my express API via a proxy, with the intention of having the API return a JSON file containing a user id. While the proxy connection is working as expected, the issue arise ...

Find the two numbers within a specific range in an array using jQuery

I have two arrays and I need to check for any duplicate ranges. How can I achieve this? let startingArray = ['1', '6.1', '10', '31','6.2',3]; let endingArray = ['2', '9.9', '30&ap ...

When utilizing Angular 2, this message is triggered when a function is invoked from the Observable

One of my services is set up like this: @Injectable() export class DataService { constructor(protected url: string) { } private handleError(error: Response) { console.log(this.url); return Observable.throw(new AppError(error)); ...

Troubleshooting 404 Error When Using Axios Put Request in Vue.js

I'm trying to update the status of an order using Axios and the Woocommerce REST API, but I keep getting a 404 error. Here's my first attempt: axios.put('https://staging/wp-json/wc/v3/orders/1977?consumer_key=123&consumer_secret=456&apos ...

The Bootstrap 4 component remains visible in XS screen sizes

I have been trying to use the Display Property in Bootstrap 4 after reading the documentation, but I find it more challenging than with Bootstrap 3. In my sidebar, I have two elements: widget-game and last-game, both of which need to be hidden in SM and X ...

Align boxes in the center within a DIV container

Here is the box design that I have created: https://i.sstatic.net/3rtcn.jpg The green color boxes are generated dynamically inside a "col-md-10" div. If there are less than 3 boxes in the second row, I would like to center align them. For example, in thi ...

Retrieve the data from an HTTP Request using AngularJS

I've been working on creating a JavaScript function that sends an HTTP Request to retrieve data, but I'm struggling with how to handle and use the result in another function. Here are the two functions I've tried (both intended to achieve t ...

"Regardless of whether it is checked or not, the MVC 3 checkbox consistently displays as true

Below is the code snippet I am working with: @foreach (var item in Model.Defaults) { <tr class="CertainCategory"> <td> @item.Item1 </td> <td> @Html.Che ...

The error of "No 'Access-Control-Allow-Origin' header is present on the requested resource" persists even after implementing the Access-Control-Allow-Origin header

I'm trying to retrieve JSON data from a Firebase cloud function. The JSON URL works fine on the browser and my Android app, but I encounter issues when trying to fetch it in my JavaScript code. This results in an error message: No 'Access-Cont ...

When attempting to execute "nodemon," the command was not detected

When trying to use 'nodemon' in the command line, an error occurs stating that it is not recognized as a cmdlet, function, script file, or operable program. The system suggests checking the spelling of the name and verifying that the path is corr ...

Discover the second character in the sequence and substitute it with a different numeral

I need to manipulate a string where I want to replace the second digit with a random number. The challenge lies in identifying the second digit and performing the replacement. How can I accomplish this task? 1. "data[KPI][0][rows][0][name]" 2. "data[KPI][ ...

Error handling proves futile as Ajax upload continues to fail

Utilizing a frontend jQuery AJAX script, I am able to successfully transfer images onto a PHP backend script hosted by a Slim framework app. However, there is one specific image (attached) that is causing an issue. When the backend attempts to send back a ...

Retrieve and substitute attributes using preg_replace

I'm looking to add tabs to all the properties listed here, but I am having trouble isolating the properties as $1 is not working in this case. A small tweak would solve this issue... Thank you! $css = <<<EOF body { padding: 0px; ...