You got me lookin' up high
You got me searchin' down low
—Devo,
"Jerkin' Back 'n' Forth"
Borrowing from CSS 1-3 and basic XPath, and then adding its own, jQuery offers a powerful set of selector expressions for matching a set of elements in a document. In this chapter, we'll examine every selector expression that jQuery makes available in turn.
The following selectors are based on the CSS 1-3, as outlined by the W3C. For more information about the specifications, visit http://www.w3.org/Style/CSS/#specs.
All elements that have a tag name of T
.
$('div')
: selects all elements with a tag name of div
in the document$('em')
: selects all elements with a tag name of em
in the documentThe unique element with an ID equal to myid
.
$('#myid')
: selects the unique element with id='myid'
, regardless of its tag name$('p#myid')
: selects a single paragraph with an id
of 'myid'
; in other words, the unique element <p id='myid'>
Each id
value must be used only once within a document. If more than one element has been assigned the same id
, queries that use that id
will only select the first matched element in the DOM.
It might not be immediately clear why someone might want to specify a tag name associated with a particular id
, since that id
needs to be unique anyway. However, some situations in which parts of the DOM are user-generated may require a more specific expression to avoid false positives. Furthermore, when the same script is run on more than one page, it might be necessary to identify the id's
element, since the pages could be associating the same id
with different elements. For example, Page A might have <h1 id='title'>
while Page B has <h2 id='title'>
.
For a plain id
selector such as example 2 above, jQuery uses the JavaScript function getElementById()
. If the script's execution speed is paramount, the plain id
selector should be used.
All elements that have a class of myclass
.
$('.myclass')
: selects all elements that have a class of myclass
$('p.myclass')
: selects all paragraphs that have a class of myclass
$('.myclass.otherclass')
: selects all elements that have a class of myclass
and otherclass
In terms of speed, example 2 is generally preferable to example 1 (if we can limit the query to a given tag name) because it first uses the native JavaScript function getElementsByTagName()
to filter its search, and then looks for the class within the matched subset of DOM elements. Conversely, there is currently no native getElementsByClassName()
for jQuery to use, so using a bare class name forces jQuery to match it against every element in the DOM. The difference in speed varies, however, with the complexity of the page and the number of DOM elements.
As always, remember that development time is typically the most valuable resource. Do not focus on optimization of selector speed unless it is clear that performance needs to be improved.
As a CSS selector, the multiple-class syntax of example 3 is supported by all modern web browsers, but not by Internet Explorer versions 6 and below, which makes the syntax especially handy for applying styles cross-browser through jQuery.
All elements matched by F
that are descendants of an element matched by E
.
$('#container p')
: selects all elements matched by <p>
that are descendants of an element that has an id of container
$('a img')
: selects all elements matched by <img>
that are descendants of an element matched by <a>
A descendant of an element could be a child, grandchild, great-grandchild, and so on, of that element. For example, in the following HTML, the <img>
element is a descendant of the <span>, <p>, <div id="inner">
, and <div id="container">
elements:
<div id="container"> <div id="inner"> <p> <span><img src="example.jpg" alt="" /></span> </p> </div> </div>
All elements matched by F
that are children of an element matched by E
.
$('li > ul')
: selects all elements matched by <ul>
that are children of an element matched by <li>
$('p > code')
: selects all elements matched by <code>
that are children of an element matched by <p>
As a CSS selector, the child combinator is supported by all modern web browsers including Safari, Mozilla/Firefox, and Internet Explorer 7, but notably not by Internet Explorer versions 6 and below. Example 1 is a handy way to select all nested unordered lists (i.e. excepting the top level).
The child combinator can be thought of as a more specific form of the (single-space) descendant combinator in that it selects only first-level descendants. Therefore, in the following HTML, the <img>
element is a child only of the <span>
element.
<div id="container"> <div id="inner"> <p> <span><img src="example.jpg" alt="" /></span> </p> </div> </div>
All elements matched by F
that immediately follow, and have the same parent as, an element matched by E
.
$('ul + p')
: selects all elements by <p>
(paragraph) that immediately follow a sibling element matched by <ul>
(unordered list)$('strong + em')
: selects all elements matched by <em>
that immediately follow a sibling element matched by <strong>
One important point to consider with both the +
combinator and the ~
combinator (covered next) is that they only select siblings. Consider the following HTML:
<div id="container"> <ul> <li></li> <li></li> </ul> <p> <img/> </p> </div>
$('ul + p')
selects <p>
because it immediately follows <ul>
and the two elements share the same parent, <div id="container">
.
$('ul + img')
selects nothing because (among other reasons)<ul>
is one level higher in the DOM tree than <img>
.
$('li + img')
selects nothing because, even though <li>
and <img>
are on the same level in the DOM tree, they do not share the same parent.
All elements matched by F
that follow, and have the same parent as, an element matched by E
.
$('p ~ ul')
: selects all elements matched by <ul>
that follow a sibling element matched by <p>
$('code ~ code')
: selects all elements matched by <code>
that follow a sibling element matched by <code>
One important point to consider with both the +
combinator and the ~
combinator is that they only select siblings. The notable difference between the two is their respective reach. While the +
combinator reaches only to the immediately following sibling element, the ~
combinator extends that reach to all following sibling elements.
Consider the following HTML:
<ul> <li class="first"></li> <li class="second"></li> <li class="third></li> </ul> <ul> <li class="fourth"></li> <li class="fifth"></li> <li class="sixth"></li> </ul>
$('li.first ~ li')
selects <li class="second">
and <li class="third">
.
$('li.first + li')
selects <li class="second">
.
Selects all elements matched by selector expressions E, F
, or G
.
$('code, em, strong')
: selects all elements matched by <code>
or <em>
or <strong>
$('p strong, .myclass')
: selects all elements matched by <strong>
that are descendants of an element matched by <p>
as well as all elements that have a class of myclass
This comma (,) combinator is an efficient way to select disparate elements. An alternative to this combinator is the .add()
method described in Chapter 3.
All elements that are the nth
child of their parent.
$('li:nth-child(2)')
: selects all elements matched by <li>
that are the second child of their parent$('p:nth-child(5)')
: selects all elements matched by <p>
that are the fifth child of their parentBecause jQuery's implementation of :nth-child(n)
is strictly derived from the CSS specification, the value of n
is 1-based, meaning that the counting starts at 1. For all other selector expressions, however, jQuery follows JavaScript's "0-based" counting. Therefore, given a single <ul>
containing two <li>s, $('li:nth-child(1)')
selects the first <li>
while $('li:nth(1)')
selects the second.
Because the two look so similar, the :nth-child(n)
pseudo-class is easily confused with :nth(n)
, even though, as we have just seen, the two can result in dramatically different matched elements. With :nth-child(n)
, all children are counted, regardless of what they are, and the specified element is selected only if it matches the selector attached to the pseudo-class. With :nth(n)
only the selector attached to the pseudo-class is counted, not limited to children of any other element, and the nth one is selected. To demonstrate this distinction, let's examine the results of a few selector expressions given the following HTML:
<div> <h2></h2> <p></p> <h2></h2> <p></p> <p></p> </div>
$('p:nth(1)')
selects the second <p>
, because numbering for :nth(n)
starts with 0
.
$('p:nth-child(1)')
selects nothing, because there is no <p>
element that is the first child of its parent.
$('p:nth(2)')
selects the third <p>
.
$('p:nth-child(2)')
selects the first <p>
, because it is the second child of its parent.
In addition to taking an integer, :nth-child(n)
can take even
or odd
. This makes it especially useful for table-row striping solutions when more than one table appears in a document. Again, given the HTML snippet above:
$('p:nth-child(even)')
selects the first and third <p>
, because they are children 2 and 4 (both even numbers) of their parent.
All elements that are the first child of their parent:
$('li:first-child')
: selects all elements matched by <li>
that are the first child of their parent$(strong:first-child')
: selects all elements matched by <strong>
that are the first child of their parentAll elements that are the last child of their parent.
$('li:last-child')
: selects all elements matched by <li>
that are the last child of their parent$('code:last-child')
: selects all elements matched by <code>
that are the last child of their parentAll elements that are the only child of their parent.
All elements that do not match selector s
.
All elements that have no children (including text nodes).
$(':empty')
: selects all elements that have no children$('p:empty')
: selects all elements matched by <p>
that have no childrenThe W3C recommends that the <p>
element have at least one child node, even if that child is merely text (see http://www.w3.org/TR/html401/struct/text.html#edef-P). Some other elements, on the other hand, are empty (i.e. have no children) by definition:<input>, <img>, <br>
, and <hr>
, for example.
One important thing to note with :empty
(and :parent
) is that child elements include text nodes.