22

I am trying to make a navigation menu I did all the HTML and CSS when come to javascript I am struck in the middle I am able to add a class to the element, but I am not able to remove the class remaining elements. Please help me with this.
here is my code

<!DOCTYPE html>
    <html>
    <head>
        <title>Navigation class Toggling</title>

        <style type="text/css">
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        header {
            width: 100%;
            height: auto;
            max-width: 600px;
            margin: 0 auto;
        }
        nav {
            width: 100%;
            height: 40px;
            background-color: cornflowerblue;
        }
        ul {
            list-style-type: none;
        }
        li {
            display: inline-block;
        }
        a {
            text-decoration: none;
            padding: 8px 15px;
            display: block;
            text-transform: capitalize;
            background-color: darkgray;
            color: #fff;
        }
        a.active {
            background-color: cornflowerblue;
        }
        </style>
    </head>
    <body>
    <header>
        <nav>
            <ul onclick="myFunction(event)">
                <li><a href="#">home</a></li>
                <li><a href="#">about</a></li>
                <li><a href="#">service</a></li>
                <li><a href="#">profile</a></li>
                <li><a href="#">portfolio</a></li>
                <li><a href="#">contact</a></li>
            </ul>
        </nav>
    </header>
    <script type="text/javascript">
        function myFunction(e) {
            e.target.className = "active";
        }
    </script>
    </body>
    </html>

and here is my Codepen

2

10 Answers 10

45

Use document.querySelectorAll to find the element which currently have the active class, then you can remove that class.

function myFunction(e) {
  var elems = document.querySelectorAll(".active");
  [].forEach.call(elems, function(el) {
    el.classList.remove("active");
  });
  e.target.className = "active";
}

JSFIDDLE

Instead of document.querySelectorAll you can also use document.querySelector

 function myFunction(e) {
  var elems = document.querySelector(".active");
  if(elems !==null){
   elems.classList.remove("active");
  }
 e.target.className = "active";
}

JSFIDDLE 2

Edit

Instead of iterating through the entire collection you can select the element which have a class active using document.queryselector. Also provide an id to the ul so that you can target the specific element

function myFunction(e) {
  if (document.querySelector('#navList a.active') !== null) {
    document.querySelector('#navList a.active').classList.remove('active');
  }
  e.target.className = "active";
}
<style type="text/css">* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

header {
  width: 100%;
  height: auto;
  max-width: 600px;
  margin: 0 auto;
}

nav {
  width: 100%;
  height: 40px;
  background-color: cornflowerblue;
}

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

a {
  text-decoration: none;
  padding: 8px 15px;
  display: block;
  text-transform: capitalize;
  background-color: darkgray;
  color: #fff;
}

a.active {
  background-color: cornflowerblue;
}
<title>Navigation class Toggling</title>

<header>
  <nav>
    <ul onclick="myFunction(event)" id='navList'>
      <li><a href="#">home</a></li>
      <li><a href="#">about</a></li>
      <li><a href="#">service</a></li>
      <li><a href="#">profile</a></li>
      <li><a href="#">portfolio</a></li>
      <li><a href="#">contact</a></li>
    </ul>
  </nav>
</header>

Sign up to request clarification or add additional context in comments.

1 Comment

Hello from 2020. I tried using your solutions and got them to work when there is a hashtag in the anchor href. But when I put an actual link inside to a page in the site, it doesn't work. Is there a way to add an active class based on url location?
11

You could use classList methods to add, remove, or toggle.

First remove class name from previous one:

// assuming there's only one with such class name
// otherwise you need querySelectorAll and a loop
document.querySelector('.active').classList.remove('active')

Then add it to the new element:

e.target.classList.add('active')

Comments

5

HTML

<div class="container">
 <nav>
  <ul class="nav">
    <li class="nav__item"><a class="nav__link active" href="#">Home</a></li>
    <li class="nav__item"><a class="nav__link" href="#">Item 1</a></li>
    <li class="nav__item"><a class="nav__link" href="#">Item 2</a></li>
    <li class="nav__item"><a class="nav__link" href="#">Item 3</a></li>
    <li class="nav__item"><a class="nav__link" href="#">Item 4</a></li>
    <li class="nav__item"><a class="nav__link" href="#">Item 5</a></li>
  </ul>
 </nav>
</div>

CSS

    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    *::before, *::after {
        box-sizing: border-box;
    }

    .container {
      width: 100%;
      max-width: 1024px;
      display: block;
      margin: 30px auto;
    }

    ul {
      list-style: none;
    }

    a {
      text-decoration: none;
    }

    .nav {
      display: flex;
      flex-direction: row;
      justify-content: space-around;
      align-items: center;
    }

    .nav__item {
      padding: 1rem;
    }

    .nav__link {
      display: block;
      padding: .3125rem 1.5rem;
      text-transform: uppercase;
    }

    .nav__link.active  {
      border: 1px solid #ff4b4c;
      color: #ff4b4c;
    }

JS

    document.addEventListener('DOMContentLoaded', function() {

      const selector = '.nav__link';
      const elems = Array.from(document.querySelectorAll(selector));
      const navigation = document.querySelector('nav');

      function makeActive(evt) {
        const target = evt.target;

         if (!target || !target.matches(selector)) {
           return;
         }

        elems.forEach(elem => elem.classList.remove('active'));
        evt.target.classList.add('active');
      };

      navigation.addEventListener('mousedown', makeActive);

    });

BTW: A great solution is here: https://gomakethings.com/getting-all-sibling-elements-when-a-link-or-button-is-clicked-with-vanilla-js/

1 Comment

the "elems.forEach(elem => elem.classList.remove('active')); evt.target.classList.add('active');" was exactly what I was looking for. thanks!
2

You can use "pure" JavaScript Element.classList to add and remove a class from your DOM element.

add: Add specified class values. If these classes already exist in attribute of the element, then they are ignored.

remove: Remove specified class values.

Use Document.querySelectorAll()to returnsa elements within the document that match the specified group of CSS selectors.

More info at:

https://developer.mozilla.org/en/docs/Web/API/Element/classList

https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll

Regarding your code, you can mark as active your element when User click on it using the following code:

window.myFunction = function(event) {
  // reset all menu items
  document.querySelectorAll('ul li a.active').forEach(function(item) {
  item.classList.remove('active');
})
  // mark as active selected menu item
  event.target.classList.add("active");
};
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

header {
  width: 100%;
  height: auto;
  max-width: 600px;
  margin: 0 auto;
}

nav {
  width: 100%;
  height: 40px;
  background-color: cornflowerblue;
}

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

a {
  text-decoration: none;
  padding: 8px 15px;
  display: block;
  text-transform: capitalize;
  background-color: darkgray;
  color: #fff;
}

a.active {
  background-color: cornflowerblue;
}

.active {
  ackground-color: red;
}
<header>
  <nav>
    <ul onclick="window.myFunction(event)">
      <li><a href="#">home</a></li>
      <li><a href="#">about</a></li>
      <li><a href="#">service</a></li>
      <li><a href="#">profile</a></li>
      <li><a href="#">portfolio</a></li>
      <li><a href="#">contact</a></li>
    </ul>
  </nav>
</header>

Comments

1

you can do like this in pure javascript

   function myFunction(e,ev) {
      for(var i=0;i<e.children.length;i++)
        {
         e.children[i].childNodes[0].className = "";
          
        }
        ev.target.className = "active"; 
         
        }
<!DOCTYPE html>
    <html>
    <head>
        <title>Navigation class Toggling</title>

        <style type="text/css">
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }
        header {
            width: 100%;
            height: auto;
            max-width: 600px;
            margin: 0 auto;
        }
        nav {
            width: 100%;
            height: 40px;
            background-color: cornflowerblue;
        }
        ul {
            list-style-type: none;
        }
        li {
            display: inline-block;
        }
        a {
            text-decoration: none;
            padding: 8px 15px;
            display: block;
            text-transform: capitalize;
            background-color: darkgray;
            color: #fff;
        }
        a.active {
            background-color: cornflowerblue;
        }
        </style>
    </head>
    <body>
    <header>
        <nav>
            <ul onclick="myFunction(this,event)">
                <li><a href="#">home</a></li>
                <li><a href="#">about</a></li>
                <li><a href="#">service</a></li>
                <li><a href="#">profile</a></li>
                <li><a href="#">portfolio</a></li>
                <li><a href="#">contact</a></li>
            </ul>
        </nav>
    </header>
    <script type="text/javascript">
     
    </script>
    </body>
    </html>

1 Comment

IMO the problem of using .className = ""; is that it will remove any css class applied to the DOM element, when instead using classList.remove we can remove selectively only a specific CSS class.
1

I'd personally stick with the document.querySelector method. querySelector accepts a CSS like query, which we will use to find an active class on the page. If it exists (the if statement), remove it and apply the new class on the target.

Please be aware that using className = "" will result in all classes being removed. It would be more neat to use classList for everything.

function myFunction(e) {
    var el = document.querySelector('.active');
  
    // Check if the element exists to avoid a null syntax error on the removal
    if(el) {
      el.classList.remove('active');
    }
		
    e.target.classList.add('active');
}

Comments

0

Below should help.

//Remove all classes by ID
document.getElementById("elementIdHere").className = "";
//If you wish to keep some classes on the element, use below
document.getElementById("elementIdHere").className = "keepClass";

Comments

0

JS

var targets = document.querySelectorAll('.some-class');

targets.onclick = function(evt) {
    evt.classList.toggle('{your-class}');
};

For better browser support:

targets.onclick = function(evt) {
    var el = evt.target;
    var classes = el.className.split(" ");
    var classIndex = classes.indexOf('{your-class}');

    if (classIndex >= 0) {
        classes.splice(1, classIndex);
    } else {
        classes.push('{your-clas}');
    }

    el.className = classes.join(" ");
});

Comments

0

window.myFunction = function(event) {
  var elms = document.querySelectorAll('ul li a');
  // reset all you menu items
  for (var i = 0, len = elms.length; i < len; i++) {
    elms[i].classList.remove('active');
  }
  // mark as active clicked menu item
  event.target.classList.add("active");
};
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

header {
  width: 100%;
  height: auto;
  max-width: 600px;
  margin: 0 auto;
}

nav {
  width: 100%;
  height: 40px;
  background-color: cornflowerblue;
}

ul {
  list-style-type: none;
}

li {
  display: inline-block;
}

a {
  text-decoration: none;
  padding: 8px 15px;
  display: block;
  text-transform: capitalize;
  background-color: pink;
  color: #fff;
}

a.active {
  background-color: blue;
}

.active {
  ackground-color: red;
}
<header>
  <nav>
    <ul onclick="window.myFunction(event)">
      <li><a href="#">home</a></li>
      <li><a href="#">about</a></li>
      <li><a href="#">service</a></li>
      <li><a href="#">profile</a></li>
      <li><a href="#">portfolio</a></li>
      <li><a href="#">contact</a></li>
    </ul>
  </nav>
</header>

Comments

-1

My Code:

let navLinks = document.querySelectorAll('ul li a');

function addClass() {
    navLinks.forEach((link) => {
        link.addEventListener('click', (e) => {
            e.preventDefault();
            removeClass();
            link.parentElement.classList.add('menu-open');
        });
    });
}

addClass();

function removeClass() {
    navLinks.forEach((link) => {
        link.parentElement.classList.remove('menu-open');
    });
}

2 Comments

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.
Welcome to Stack Overflow! Thank you for your answer. Please provide more details about your solution. Code snippets, high quality descriptions, or any relevant information would be great. Clear and concise answers are more helpful and easier to understand for everyone. Edit your answer with specifics to raise the quality of your answer. For more information: How To: Write good answers. Happy coding!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.