jQuery eq vs nth-child Zero-Based Indexing

When manipulating the DOM with jQuery, selecting elements by their position is a common requirement, typically achieved using either the :eq() selector or the CSS-standard :nth-child() pseudo-class. The primary technical difference between them lies in how they count positions: jQuery's :eq() relies on a zero-based index targeting an element's position within a matched set, whereas :nth-child() relies on a one-based index evaluating an element's position relative to its sibling elements inside a parent container. Understanding this distinction prevents common off-by-one errors and unintended DOM selections.

Zero-Based vs. One-Based Counting

The most direct difference between the two selectors is the starting number of their indexing systems:

  • :eq(index) (Zero-Based): Borrowing from standard programming arrays and JavaScript conventions, counting starts at 0. Therefore, :eq(0) selects the very first element in the matched set, :eq(1) selects the second, and :eq(2) selects the third.
  • :nth-child(n) (One-Based): Borrowing from natural human language and standard CSS specifications, counting starts at 1. Therefore, :nth-child(1) targets the first child of a parent, :nth-child(2) targets the second, and :nth-child(0) matches nothing because zero does not represent a valid position in CSS counting.

Collection Indexing vs. Sibling Indexing

Beyond starting at 0 versus 1, these selectors calculate positional context differently across the DOM:

jQuery :eq()

The :eq() selector evaluates the entire matched set returned by the initial query as a flat array. It does not care about parent-child relationships or the HTML tree structure.

// Selects the second <li> found on the entire page, 
// regardless of which <ul> or <ol> it belongs to.
$("li:eq(1)");

If you have two separate lists with three <li> items each, $("li") matches six elements (indexed 0 through 5). Calling $("li:eq(3)") returns the first <li> of the second list because it is the fourth element in the flattened selection.

CSS :nth-child()

The :nth-child() selector evaluates elements based on their exact position among siblings sharing the same parent.

// Selects every <li> that is the first child of its respective parent list.
$("li:nth-child(1)");

Using the same example of two separate lists, $("li:nth-child(1)") will match two elements: the first item of the first list and the first item of the second list, because both hold position 1 under their respective parents.

Negative Index Support

The two selectors also handle reverse counting differently:

  • :eq(): Supports negative integers natively in jQuery. Passing a negative number counts backward from the end of the matched set. For instance, $("p:eq(-1)") selects the last paragraph in the selection.
  • :nth-child(): Does not accept negative numbers. To count backward from the end of a parent container using CSS rules, you must use the distinct :nth-last-child() selector, which also uses a 1-based index (e.g., :nth-last-child(1) selects the final child).

Comparison Summary

Feature :eq() :nth-child()
Index Base Zero-based (0 is the first element) One-based (1 is the first element)
Origin jQuery-specific selector CSS3 specification
Evaluation Scope Flat collection of matched elements Sibling position inside the parent
Negative Values Counts backward from the end (:eq(-1)) Invalid (requires :nth-last-child())
Performance Slower (cannot use native querySelectorAll) Faster (delegates to browser CSS engine)