Himanshu SharmaSoftware engineer
Let’s talk

jQuery · Lesson 8 of 45

Moving sideways: siblings, next and prev

Reach the elements next to one you already have with jQuery's .siblings(), .next(), .prev(), .nextAll(), .prevAll(), .nextUntil() and .index().

11 minSelecting elementsUpdated 23 October 2026

By the end of this lessonMove between neighbouring elements to build tabs, accordions and "show more" controls, and find an element's position among its siblings.

Siblings

Elements that share the same parent are siblings. Moving between them is how you build tabs, accordions, step-by-step forms and "one item selected at a time" lists.

html
<ul>
  <li>Home</li>
  <li id="shop">Shop</li>
  <li>Blog</li>
  <li class="special">Offers</li>
  <li>Contact</li>
</ul>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  const $shop = $("#shop");
  console.log("siblings  ", $shop.siblings().length, $shop.siblings().text());
  console.log("next      ", $shop.next().text());
  console.log("prev      ", $shop.prev().text());
  console.log("nextAll   ", $shop.nextAll().text());
  console.log("prevAll   ", $shop.prevAll().text());
  console.log("nextUntil ", $shop.nextUntil(".special").text());
  console.log("index     ", $shop.index());
</script>
result
siblings   4 HomeBlogOffersContact
next       Blog
prev       Home
nextAll    BlogOffersContact
prevAll    Home
nextUntil  Blog
index      1
  • .siblings() returns every other child of the same parent. The element itself is never included.
  • .next() and .prev() return the one neighbour directly after or before.
  • .nextAll() and .prevAll() return all siblings in that direction.
  • .nextUntil(".special") collects siblings up to, but not including, the first match. .prevUntil() works the other way.
  • .index() tells you the element's position among its siblings, counting from 0.

This catches many people:

html
<h3>Question</h3>
<p class="note">A note between them.</p>
<p class="answer">The answer.</p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  console.log(".next('.answer')       :", $("h3").next(".answer").length);
  console.log(".nextAll('.answer')    :", $("h3").nextAll(".answer").first().text());
</script>
result
.next('.answer')       : 0
.nextAll('.answer')    : The answer.

.next(".answer") looks only at the immediate next sibling (the note) and keeps it if it matches. It does not, so the result is empty. To find the first following .answer, use .nextAll(".answer").first().

One selected at a time

The most common sibling pattern: highlight the item that was clicked and remove the highlight from the others.

html
<style>
  li { cursor: pointer; padding: 4px 8px; }
  li.active { background: #fde68a; font-weight: bold; }
</style>
<ul>
  <li class="active">Small</li>
  <li>Medium</li>
  <li>Large</li>
</ul>
<p>Selected size: <span id="size">Small</span></p>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("li").on("click", function () {
    $(this).addClass("active").siblings().removeClass("active");
    $("#size").text($(this).text());
    console.log("selected index", $(this).index());
  });
</script>
result
selected index 2

One chained line does the work: add active to the clicked item, move to its siblings, remove active from them.

A simple accordion

.next() connects a heading to the panel that follows it:

html
<style>
  .panel { display: none; padding: 0 12px; }
  .open + .panel { display: block; }
  h4 { cursor: pointer; margin: 8px 0; }
</style>
<h4 id="q1">What is jQuery?</h4>
<div class="panel">A JavaScript library.</div>
<h4 id="q2">Is it free?</h4>
<div class="panel">Yes, it is open source under the MIT licence.</div>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("h4").on("click", function () {
    $(this).toggleClass("open");
    console.log($(this).next(".panel").text());
  });
</script>
result
Yes, it is open source under the MIT licence.

The CSS shows a panel when the heading before it has the open class, and jQuery only toggles that class. Keeping the look in CSS and the behaviour in jQuery is a clean split; the effects section shows animated versions.

Tabs with .index() and .eq()

.index() and .eq() work well together: find the position of the clicked tab, then show the panel at the same position.

html
<style>
  .tab.on { font-weight: bold; text-decoration: underline; }
  .pane { display: none; } .pane.on { display: block; }
</style>
<div id="tabs"><button class="tab on">Description</button><button class="tab">Reviews</button><button class="tab">Shipping</button></div>
<div class="pane on">A solid oak desk.</div>
<div class="pane">4.5 stars from 30 reviews.</div>
<div class="pane">Ships in 2 days.</div>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $(".tab").on("click", function () {
    const i = $(this).index();
    $(this).addClass("on").siblings().removeClass("on");
    $(".pane").removeClass("on").eq(i).addClass("on");
  });
</script>
result
DescriptionReviewsShipping
4.5 stars from 30 reviews.

After clicking the second tab, only the second panel is visible.

Notice that .index() is measured among the tab's own siblings, the buttons inside #tabs, not among every element on the page. That is why the tabs sit in their own container. If you add an unrelated element inside #tabs, such as a heading before the first button, every index shifts by one and the wrong panel opens. To protect against that, call .index() with a selection: $(".tab").index(this) returns the position of the clicked tab among the .tab elements only, whatever else shares the container.

Common mistakes

  • Expecting .siblings() to include the element. It never does.
  • Using .next(selector) to search ahead. Use .nextAll(selector).first().
  • Forgetting that whitespace and comments are skipped. jQuery's sibling methods only count elements, so line breaks in your HTML do not matter.
  • Linking tabs and panels by position when the HTML order can change. For larger widgets, use data- attributes or aria-controls to connect them by name.

Exercise

Build a list of three colour names. When one is clicked, make it bold and make all the other items gray, using .siblings().

Show one possible answer
html
<ul><li>Red</li><li>Green</li><li>Blue</li></ul>

<script src="https://code.jquery.com/jquery-4.0.0.min.js"></script>
<script>
  $("li").on("click", function () {
    $(this).css({ fontWeight: "bold", color: "" })
      .siblings().css({ fontWeight: "", color: "gray" });
  });
</script>

Setting a style to an empty string removes it, so an item that was gray goes back to normal when clicked.

Key points

  • Siblings share the same parent; .siblings() returns all of them except the element itself.
  • .next() and .prev() return the single neighbour after or before; .nextAll() and .prevAll() return every one in that direction.
  • .nextUntil(selector) and .prevUntil(selector) stop just before a matching element.
  • .index() returns an element's position among its siblings, counting from 0.

Check yourself

1. Does .siblings() include the element itself?
2. What does .next(".answer") return if the very next sibling is not .answer?
3. What does $("li.active").index() return when the active item is the third of five?
4. Which method is best for the 'one open item' pattern: open this one, close the others?