Traversing the tree
It is often easier to find one element and move from it to the ones you need: to nested elements, to the parent, to neighbors. This is called traversing the DOM tree. Each traversal method returns a new jQuery object.
Down: find and children
find() searches by selector at any depth inside the elements of the set. children() takes only direct children, the tags one level down:
<div id="app">
<ul id="tasks">
<li>Buy bread</li>
<li>Call Oleg</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
console.log($('#app').find('li').length); // 2
console.log($('#app').children().length); // 1, only the ul
console.log($('#tasks').children().length); // 2
</script>#app has one direct child, the list, and the items sit deeper, so only find() reaches them.
Up: parent and closest
parent() returns the immediate parent. closest() goes up starting from the element itself and stops at the first one that matches the selector:
<ul id="tasks">
<li>Buy bread <button>Delete</button></li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
const $button = $('button');
console.log($button.parent().prop('tagName')); // LI
console.log($button.closest('ul').attr('id')); // tasks
</script>closest() is especially useful in handlers: from a clicked "Delete" button it finds the list item to remove.
Sideways: siblings, next, prev
<ul>
<li>Buy bread</li>
<li id="current">Call Oleg</li>
<li>Write the report</li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
const $item = $('#current');
console.log($item.siblings().length); // 2
console.log($item.next().text()); // Write the report
console.log($item.prev().text()); // Buy bread
</script>siblings() returns all elements with the same parent, except the element itself.
Picking from a set
| Method | What it keeps |
|---|---|
first() | The first element |
last() | The last element |
eq(1) | The element at index 1 (the second), eq(-1) is the last |
filter('.done') | Elements matching the selector |
not('.done') | Elements not matching the selector |
<ul>
<li class="done">Buy bread</li>
<li>Call Oleg</li>
<li>Write the report</li>
</ul>
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
console.log($('li').eq(1).text()); // Call Oleg
console.log($('li').not('.done').length); // 2
$('li').first().css('color', 'gray');
</script>The first item turns gray, and the console shows the second item and the number of unfinished tasks.
The same in plain JavaScript
find() corresponds to element.querySelectorAll(), parent() to element.parentElement, closest() to element.closest(), next() to element.nextElementSibling.
Common mistake
Mixing up parent() and closest(). If the item markup later gets wrapped in one more tag, $button.parent() returns that wrapper instead of the li, and the code breaks. $button.closest('li') finds the item at any nesting depth.