Categories:

W3C CSS Selectors API- The querySelector() and querySelectorAll() methods

Last updated: June 4th, 2014

The querySelector() and querySelectorAll() methods let you enter a CSS selector as a parameter and return the selected elements as DOM elements. Part of the W3C Selectors API, the difference between the two methods is merely in the number of possible elements that they return- the very first matched element versus the entire set. Apart from being far more versatile than the staple getElementById() and getElementsByTagName() methods, these two methods also benefit from some incredible lookup speed, as they take advantage of the same engine the browser uses to identify elements to style when parsing the CSS of a page.

Ok, time for the obligatory reality check here- in terms of browser support, querySelector() and querySelectorAll() is supported in Firefox 3.1+, IE8+ (only in IE8 standards mode), and Safari 3.1+.

The querySelector() method

The querySelector() method exists both on as a Document and as an Element object. This lets you query either the entire document tree, or just a specific chunk of it looking for that elusive element of yours. It accepts any CSS selector as its parameter (ie: "#mydiv img") and returns either the first matched element (if multiple exists), or null if none. For example:

document.querySelector('#myheader') //returns the element with ID="myheader"
document.querySelector('p.description') //returns the P with class="description" element

document.querySelector('#content img:nth-of-type(1)') //returns the 1st image within container "#content"
document.querySelector('#myform input[type="radio"]:checked') //selects the checked radio button within "#myform"

document.querySelector('form[action="feedback.php"]') // references form with action="feedback.php"
document.querySelector('img[src^="http"]') // selects 1st image with src beginning with "http"
document.querySelector('img[src$="blank.gif"]') // selects 1st image with src ending in "blank.gif"

document.querySelector('#biography, #gallery') //returns either element "#biography" or "#gallery", depending on which one is found first within document tree

 

Take a look at the last example above- you can enter multiple CSS selectors, each seperated by a comma (","). The comma acts like the logical OR statement here, which causes querySelector() to return the first element within the document tree that matches one of the CSS selectors entered.

Ok, time for a quick demonstration. The below HTML creates a nested DIV, with the inner DIV changing background color whenever the mouse rolls over the outer DIV itself. It makes use of querySelector() both as a document method, and element method:

<div id="outerdiv" style="padding:50px; width:100px; height:100px; border:1px solid black">
<div id="innerdiv" style="width:100%; height:100%; border:1px solid black; background:silver;">
</div>
</div>

<script type="text/javascript">

if (document.querySelector){
 var outerdiv=document.querySelector('#outerdiv')
 outerdiv.onmouseover=function(){
  this.querySelector('#innerdiv').style.background="yellow"
 }
 outerdiv.onmouseout=function(){
  this.querySelector('#innerdiv').style.background="silver"
 }
}

</script>

Demo (requires FF 3.1+, Safari 3.1+, or IE8+):

The querySelectorAll() method

The querySelectorAll() method behaves just like its more humble cousin above with the exception it returns not just a singular element that matches a CSS selector, but all of them as a staticNodeList. A staticNodeList is a static collection of elements that are not affected by any subsequent changes occurring on the document tree, such as the removal of one those elements. It supports a "length" property for you to step through each of the elements similar to in an Array. With that said:

document.querySelectorAll('.mygroup') //returns all elements with class="mygroup"
document.querySelectorAll('option[selected="selected"]') //returns the default selected option within each SELECT menu
document.querySelectorAll('#mytable tr>td:nth-of-type(1)') //returns the first cell within each table row of "mytable"

document.querySelectorAll('a[src^="http"]') // selects all links with href beginning with "http"
document.querySelectorAll('a[href*="javascriptkit"]') // selects all links with href containing sub string 'javascriptkit'

document.querySelectorAll('#biography, #gallery') //returns both elements "#biography" and "#gallery" (inclusive)

Ok, demo time! Lets use querySelectorAll() to quickly identify all checkboxes that are selected within a particular form:

<form id="myform">

<b>Your hobbies:</b><input name="hobbies" type="checkbox" value="movies" />Movies <input name="hobbies" type="checkbox" value="sports" />Sports <input name="hobbies" type="checkbox" value="reading" />Reading <input name="hobbies" type="checkbox" value="sleeping" />Sleeping
<br />
<input type="submit" />
</form>

<script type="text/javascript">
if (document.querySelector){
 document.querySelector('#myform').onsubmit=function(){
  var checkedhobbies=this.querySelectorAll('input[name="hobbies"]:checked')
  for (var i=0; i<checkedhobbies.length; i++){
   alert(checkedhobbies[i].value)
  }
  return false
 }
}
</script>

Demo (requires FF 3.1+, Safari 3.1+, or IE8+):

Your hobbies:Movies Sports Reading Sleeping

Finally, if some of the CSS selectors used above confuse you, you'll want to read up on "Overview of CSS3 Structural pseudo-classes".

IE8 restrictions

In IE8, there are several restrictions you should be aware of when using querySelector() and querySelectorAll(). They are:

  • Your document must be in IE8 standards mode in order for these two methods to work. A document becomes non standard when it contains a non strict doctype, or explicitly set to be in IE7 standards mode instead using the meta tag: <meta http-equiv="X-UA-Compatible" content="IE=7" />. For more info on IE8's "exciting" new rendering modes, see this document.
  • IE8 does not support an optional 2nd "NSResolver" parameter passed into either querySelector() and querySelectorAll() to resolve namespace prefixes in XHTML documents, as defined by the W3C.
  • For security reasons, IE8 will not return elements specified using the CSS Selectors ":visited" or ":link". This is to prevent webmasters from detecting the links on the page the user has visited.

A less versatile but simpler alternative- getElementsByClassName()

There's another new DOM method vying for your attention when it comes to easily gathering up elements on the page, and that's getElementsByClassName(). As its name suggests, this method returns a collection of element(s) based on their shared class name, for example:

//get elements with "cats" class name
document.getElementsByClassName("cats")

//get elements with "cats" or "dogs" class names (inclusive)
document.getElementsByClassName("cats dogs")

You can use this method in place of the Query Selector methods when all you want is to get elements on the page identified by a common CSS class. As a native method of the browser, it's also blazingly fast. In terms of browser support, getElementsByClassName() is recognized in FF3+, Opera 9.5+ and Safari 3+. Sadly, IE8 is not yet part of that list, which it is for the Query Selector methods.