'Find the element before and after a specific element with pure javascript

Having a list with links like this:

<ul>
    <li><a href="#">First tab</a></li>
    <li><a href="#">Second tab</a></li>
    <li class="active"><a href="#">Active tab</a></li>
    <li><a href="#">Fourth tab</a></li>
    <li><a href="#">Fifth tab</a></li>
</ul>

How can be found element before and after the active tab? (In this case, the second and fourth tab).


I am looking for solution in pure JavaScript only, as jQuery solution is here.

Note: nextElementSibling and previousElementSibling are not supported by IE8 and FF3, so please post solutions that would be supported by those browsers as well. Thank you.



Solution 1:[1]

Assuming your <ul> element is called element:

var active, prev, next;
active = prev = next = element.querySelector('.active');

do prev = prev.previousSibling; while(prev && prev.nodeType !== 1);
do next = next.nextSibling;     while(next && next.nodeType !== 1);

This will work in Internet Explorer 8. If you're only worried about modern browsers:

var active = element.querySelector('.active');
var prev = active.previousElementSibling;
var next = active.nextElementSibling;

Solution 2:[2]

Pretty easily, given an up-to-date browser:

// here we first retrieve the currently-active element, via
// document.getElementsByClassName(), using bracket-notation
// to access a specific element-node from the HTMLCollection;
// the zeroth element is the first element in the array-like
// collection:
const activeTab = document.getElementsByClassName('active')[0],
  // from that element-node we find the previous sibling element:
  activePrevSibling = activeTab.previousElementSibling,
  // and also the next sibling element:
  activeNextSibling = activeTab.nextElementSibling;

// we then set the background-color of these elements:
activeTab.style.backgroundColor = '#0f0';
activePrevSibling.style.backgroundColor = '#f00';
activeNextSibling.style.backgroundColor = '#00f';
*,
 ::before,
 ::after {
  box-sizing: border-box;
  font-family: sans-serif;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
}

ul,
li {
  list-style-type: none;
}

ul {
  display: flex;
  gap: 0.5em;
  margin-block: 1em;
  margin-inline: auto;
  width: clamp(20em, 80vw, 600px);
}

li {
  background-color: #fff;
  border-radius: 1em;
  display: flex;
  flex-grow: 1;
  font-size: 2em;
  place-content: center;
  text-align: center;
}

a {
  background-color: #fffa;
  border-radius: 1em;
  color: #000;
  padding-block: 0.25em;
  padding-inline: 0.5em;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.01em;
  transition: all 0.3s linear;
}

a:focus-visible {
  background-color: #fffc;
  outline-color: currentColor;
  outline-offset: 0.1em;
  outline-style: solid;
  outline-width: 0.2em;
  scale: 1.2;
}

a:active,
a:hover,
a:focus {
  text-decoration-color: currentColor;
  text-underline-offset: 0.25em;
}
<ul>
  <li><a href="#">First tab</a></li>
  <li><a href="#">Second tab</a></li>
  <li class="active"><a href="#">Active tab</a></li>
  <li><a href="#">Fourth tab</a></li>
  <li><a href="#">Fifth tab</a></li>
</ul>

JS Fiddle demo (with horrible, horrible colours...).


The above edited, based on the comment left by Esailija:

document.querySelector(".active") is more supported and concise:

// exactly as above, with the exception we're now retrieving the first,
// and only, element from the document that matches the supplied CSS
// selector; bear in mind that this method will return null if no
// matching element is found; so sanity-checks should be used in
// production code:
const activeTab = document.querySelector(".active"),
  activePrevSibling = activeTab.previousElementSibling,
  activeNextSibling = activeTab.nextElementSibling;

activeTab.style.backgroundColor = '#0f0';
activePrevSibling.style.backgroundColor = '#f00';
activeNextSibling.style.backgroundColor = '#00f';
*,
 ::before,
 ::after {
  box-sizing: border-box;
  font-family: sans-serif;
  font-size: 1rem;
  font-weight: 400;
  line-height: 1.5;
}

ul,
li {
  list-style-type: none;
}

ul {
  display: flex;
  gap: 0.5em;
  margin-block: 1em;
  margin-inline: auto;
  width: clamp(20em, 80vw, 600px);
}

li {
  background-color: #fff;
  border-radius: 1em;
  display: flex;
  flex-grow: 1;
  font-size: 2em;
  place-content: center;
  text-align: center;
}

a {
  background-color: #fffa;
  border-radius: 1em;
  color: #000;
  padding-block: 0.25em;
  padding-inline: 0.5em;
  text-decoration: underline;
  text-decoration-color: transparent;
  text-underline-offset: 0.01em;
  transition: all 0.3s linear;
}

a:focus-visible {
  background-color: #fffc;
  outline-color: currentColor;
  outline-offset: 0.1em;
  outline-style: solid;
  outline-width: 0.2em;
  scale: 1.2;
}

a:active,
a:hover,
a:focus {
  text-decoration-color: currentColor;
  text-underline-offset: 0.25em;
}
<ul>
  <li><a href="#">First tab</a></li>
  <li><a href="#">Second tab</a></li>
  <li class="active"><a href="#">Active tab</a></li>
  <li><a href="#">Fourth tab</a></li>
  <li><a href="#">Fifth tab</a></li>
</ul>

JS Fiddle demo.

References:

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Ry-
Solution 2