What is a jQuery Selector?
jQuery is a query syntax that finds HTML page elements matching specific criteria. It is analogous to the more complex SQL that queries databases, and conceptually similar to using filters in Excel. However, the specific data that jQuery operates over is the webpage Document Object Model (DOM), which is basically just a technical way of saying the structure of the webpage. The DOM is the set of all “nested” elements on the webpage. To understand jQuery selectors, we need a clear understanding of HTML. Don’t worry, it’s much simpler than it appears!
What is an element?
HTML elements have a well defined syntax and consistent, nested structure. The basic structure of an HTML element is like this:
<tagName attributeName=attributeValue(s) …> … elementContents … </tagName>
</tagName> “closes” the element. An HTML “tag” is just the opening or closing entity. For example: <p> and </p> are called HTML tags
An HTML element encompasses the opening tag, optional content, and the closing tag:
<p>This is the content</p> : This complete thing is called a HTML element
Attributes are properties of an element, they are name/value pairs specified in the opening tag. Elements can have any number of attributes including zero.
<article class=’category-food’ id=’the_article’ data-source=’wordpress’>
elementContents can be anything, including more elements. Elements are nested inside other elements as part of a hierarchy. Example:
If you understand this, then you already know pretty much everything you need to know about HTML to effectively use jQuery, but you can find more detail about HTML elements here.
The most basic Selector is a simple tag name:
This is basically saying “select (find and return) all elements on the page with tag name p”. P tags happen to be paragraphs, but it doesn’t matter to jQuery what the tag means in the context of an HTML page. These are all simple tag-based selectors:
divtablearticlebodysomethingsomething: Find elements with tag name somethingsomething
jQuery Selectors always return a list of 0, 1, or more elements. A typical use of a jQuery selector is essentially to ask “is there at least one element that matches the selector?”
jQuery and Element Attributes
Attributes are name/value pairs inside the opening tag of the HTML element. You can write jQuery selectors that find elements with a certain attribute and/or attribute value.
[data-category=’blogpost’]: Find all elements with attribute name data-category = blogpost[data-category]: Elements with data-category attribute of any valuediv[data-category]: Div elements with data-category attribute of any value[data-categories*=’ecom’]: Elements with data-categories containingcharacters ‘ecom’body[type~=’post’]: Body element with type attribute containing whole word ‘post’
Note that class and id attributes are considered special attributes in jQuery with their own syntax:
.bodytext: Find all elements of class bodytextarticle.diy_category: Find all article elements of class diy_category
Note the dot before the class name. This syntax is just shorthand equivalent to these selectors:
[class~=’bodytext’]: Find all elements with class attribute containing word ‘bodytext’article[class~=’diy_category’]: article tag elements with class attribute word ‘diy_category’
Similarly, # is used as jQuery shorthand for the id= attribute. These are equivalent:
#email_form: Find the element with id=email_form[id=’email_form’]: Find the element with attribute name id and value ‘email_form’
Note that in HTML, element id values are supposed to be unique, so generally you don’t need to narrow the selector. For example, while div#email_form is perfectly valid jQuery, in practice it is probably redundant to include the div as there will only be 0 or 1 elements with id=email_form on the page. More detailed info on matching operators for attribute selectors is here.
jQuery and Element Hierarchy
Returning to and extending our previous example HTML:
<body><article class=’category-food’>…</article><div id=’recommended_articles’><article class=’category-drink’> …<article class=’category-food’> …
Here, the first article element is a direct child of the body element, and the other articles are direct children of div#recommended_articles. In Audience Development, we are often using jQuery to look for HTML that uniquely identifies a page as having some characteristic, for targeting specialized widgets. So in this example, the page’s main article has category food, and there are two articles (probably not full articles) in a recommended section, one food and one drink.
If we wanted to target a Drinks category specific email capture widget to category-drink pages, we might write a simple jQuery selector as follows:
However, this is problematical, because in the example above it will match as TRUE (>0 elements) for the article in the recommended section, whereas the main article is category-food.
What we really want to detect is when the main article is category-drink, and we can do this by requiring a specific hierarchy using “>”:
body > article.category-drink: Find child article elements of body with class category-drink
body > .category-drink: Find any child elements of body with class category-drink
This will avoid matching articles in the recommended_articles div, and correctly be FALSE in the example above, because the recommended articles are not direct children of the body element. If you actually wanted to match a recommended article you could chain the child syntax:
body > div#recommended_articles > .category-drink
body > div > .category-drink
In general, we want to be as specific as we need to be, but no more. Very long selectors give you more specific results, but are also more fragile: if the page structure or attributes change over time, very long selectors that require a specific hierarchy of elements and attributes are more likely to become invalid.
jQuery AND and OR logic
jQuery does have the concepts of logical AND and OR, but it is not very explicit. Essentially, you can specify AND logic by chaining together selector expressions without spaces. This is AND logic applied in the context of a single element. That is, to be returned, a single element must have all selector expressions be matches:
.category-drink.category-food: true if exists an element with both food AND drink class
You can mix and match selector types:
#the_article.category-food: true for element id=the_article AND class=category-food
You can chain attribute syntax:
[id=the_article][class~=category-food]: equivalent to above example
jQuery OR logic is significantly different from AND logic, note that it does not require the selector to match on the same element.
.category-drink, .category-food: true if exists drink element or food element
As an aside here, note that it is possible to implement OR logic matching on a single element, you just need to be more specific with your selector, narrowing it down to a single element while using OR. For example:
.category-drink, .category-food: will match the same or any two elements
If you wanted to match on food OR drink but only on a single element, you need to narrow down to that element on both sides of the OR expression, ideally using a unique element id, like this:
jQuery Filters (Advanced)
We have seen how to select elements based on tags, attributes, and hierarchy. There is another useful aspect to jQuery called filters that goes beyond this. The way to think of filters is that they take a set of elements found by a selector, and further filter it down. There are many available filters, you can recognize them by their colon (:) syntax.
The most useful filter is contains:
<p>This is the content</p>p:contains(‘the content’): find p elements containing ‘the content’
jQuery in Practice
Chrome Inspector is the starting point for all jQuery work. On any web page, simply right click and choose “Inspect”. Inspector is a powerful and complicated tool for website developers, but for jQuery work we only need the Elements tab.
In the Elements tab, hitting Ctrl+F it opens the find feature, where you can search for page elements that might be useful for jQuery rules. Note that the find feature supports jQuery syntax in addition to straight text search, to a point. Specifically, it does not support jQuery filters (:).
Another useful tool for jQuery testing is SelectorGadget, a Chrome Extension available in the Chrome Web Store. SelectorGadget works even without Inspector Open, simply click the icon in the extensions tray (top right of Chrome) and the jQuery search box appears.
It will highlight page elements on the page with colored overlays, and you can click to see a selector. Note that SelectorGadget is not good at suggesting unique selectors (a selector that will return exactly the one element you clicked on), in the example above there are 230 matching elements!
Use SelectorGadget in combination with the Inspector Elements panel, where you can right click and “Copy Selector”, which will be a unique selector.
SelectorGadget is better than the find elements feature for testing selectors because it supports filters like :contains(…).
The actual selector is the part in double quotes.
Links to useful resources for jQuery reference and learning:
Practice by going to any web page and picking an element at random. Then try to write a selector for it that will find that and only that element. Compare to the selector returned by right-click, Copy CSS Selector if you need help.