skip to Main Content

I have a navbar with Bootstrap icon inside the anchor tags

Here’s my code:

<li class="nav-item">
    <a href="#" class="nav-link">
        <i class="bi bi-house"></i>
    </a>
</li>
<li class="nav-item">
    <a href="#" class="nav-link">
        <i class="bi bi-heart"></i>
    </a>
</li>
<li class="nav-item">
    <a href="#" class="nav-link">
        <i class="bi bi-envelope"></i>
    </a>
</li>

I want to add -fill if it clicked, and remove it when clicking on another navigation. I’ve tried classList.toggle, but is seems just adding new class without appending it.

<li class="nav-item">
    <a href="#" class="nav-link">
        <i class="bi bi-house-fill"></i>
    </a>
</li>
<li class="nav-item">
    <a href="#" class="nav-link">
        <i class="bi bi-heart"></i>
    </a>
</li>
<li class="nav-item">
    <a href="#" class="nav-link">
        <i class="bi bi-envelope"></i>
    </a>
</li>

2

Answers


  1. The issue with your current approach is that classList.toggle only adds the class if it’s not present and removes it if it is. This means it will only switch between the original class and the class with "-fill" appended, not allowing multiple elements to have the "-fill" class simultaneously.

    Here’s how you can achieve the desired behavior:

    1. Remove existing "-fill" classes:

    Before adding the "-fill" class to the clicked element, you need to remove it from any other element that might have it. This ensures only one element has the active state at a time.

    // Select all anchor elements within the navigation
    const navLinks = document.querySelectorAll('.nav-link');
    
    navLinks.forEach(link => {
      // Remove any existing "-fill" class
      link.classList.remove('bi-house-fill', 'bi-heart-fill', 'bi-envelope-fill');
    });
    

    2. Add "-fill" class to the clicked element:

    Now, when an anchor element is clicked, you can use classList.toggle to add the "-fill" class specific to the clicked icon.

    navLinks.forEach(link => {
      link.addEventListener('click', () => {
        const icon = link.querySelector('i');
        const iconClass = icon.classList[1]; // Get the second class (e.g., "bi-house")
        icon.classList.toggle(`${iconClass}-fill`);
      });
    });
    

    Explanation:

    1. We use querySelectorAll to select all anchor elements with the class nav-link.
    2. We loop through each link using forEach.
    3. Inside the loop, we use classList.remove to remove any existing "-fill" classes from the icon within the link. This ensures only one element has the active state.
    4. We add an event listener to each link for the click event.
    5. When a link is clicked, we use querySelector to get the icon element within the link.
    6. We then access the second class name of the icon using classList[1]. This assumes the icon class is the second class on the element.
    7. Finally, we use classList.toggle with a template literal to dynamically construct the class name to be toggled. This ensures the appropriate "-fill" class is added or removed based on the clicked icon.

    This approach ensures that only the clicked icon has the "-fill" class, providing the desired visual feedback for the active navigation item.

    Login or Signup to reply.
  2. To achieve the behaviour you’re looking for, you’ll need to add event listeners to your anchor tags. When an icon is clicked, you should add -fill to its class if it’s not already there, and for all other icons, you should remove -fill if it’s present.

    For this purpose, you should do as follows:

    1. You have to assign a click event to each navigation item (or alternatively use event delegation approach)
    2. Use Array#forEach to map through your navlinks, get the <i> classes, and replace the -fill with an empty string.
    3. Finally, add the -fill to the clicked element if it already doesn’t have it.

    Here is a working example:

    const navLinks = document.querySelectorAll('.nav-link');
    
    navLinks.forEach(link => {
      link.addEventListener('click', function() {
        // Remove '-fill' from all icons
        navLinks.forEach(otherLink => {
          const icon = otherLink.querySelector('i');
          icon.className = icon.className.replace('-fill', '');
        });
    
        // Add '-fill' to the clicked icon
        const icon = this.querySelector('i');
        if (!icon.className.includes('-fill')) {
          icon.className = icon.className + '-fill';
        }
      });
    });
    <link href="https://cdn.jsdelivr.net/npm/bootstrap-icons/font/bootstrap-icons.css" rel="stylesheet">
    
    
    <ul class="nav">
      <li class="nav-item">
        <a href="#" class="nav-link">
          <i class="bi bi-house"></i>
        </a>
      </li>
      <li class="nav-item">
        <a href="#" class="nav-link">
          <i class="bi bi-heart"></i>
        </a>
      </li>
      <li class="nav-item">
        <a href="#" class="nav-link">
          <i class="bi bi-envelope"></i>
        </a>
      </li>
    </ul>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search