Deep Tech Point
first stop in your tech adventure
QuerySelector multiple classes and other rules in JavaScript and CSS
May 10, 2021 | Javascript

We already wrote about querySelector(s) in the article where we compared querySelector to getElementById. In that article, we covered the basics, but there is so much more to querySelectors in JavaScript. They are a superpowerful tool, so we really want to introduce you to some basic and a bit more complex QuerySelector rules in JavaScript.

Let’s repeat what we have learned so far.
JavaScript querySelector() and querySelectorAll() are methods that will help you find elements based on CSS selectors. Both methods can be called on the document or HTML element.

querySelector() will help you find the first element that matches specified CSS selectors.

let firstElement = document.querySelector(selector);

While querySelectorAll() will list all elements matching CSS selectors that were specified in a query.

let listAllElements = document.querySelectorAll(selector);

In the syntax presented above, a selector is a CSS selector, and the selector can also be a group of CSS selectors that match the descendant elements of the document.

In cases when the selector is not presented with a valid CSS syntax, the querySelector method will raise a SyntaxError exception, and when there is no element that matches the CSS selectors that the method specified, the querySelector() will return null or in case of the querySelectorAll() method an empty listAllElements. Remember that a listAllElements is an array-like object, but not an array object. However, just like in the array object, you can use the forEach() method, and with the Array.from() method you can convert listAllElements to an array.

Basic QuerySelector rules in JavaScript and CSS

1. Universal selector

The universal selector matches every single element in the document tree. It makes sense to use it with querySelectorAll and here is an example of how to use it:

let allDOMElements = document.querySelectorAll('*'); // will list all elements in the document
let allH1DescendetEls = document.querySelectorAll('h1 *'); // will list all elements that are descendants of all h1 elements

2. Type selector

When you want to select elements by their node name, you can use the type selector. For example, when you want to have listed all h1 elements from the document, you would use:

let allHeading1 = document.querySelectorAll('h1');

3. Class selector

When you want to select an element with a specific class attribute, you should use apply the class selector syntax by adding .theNameOfAClass

An example below demonstrates how you can find the first element in the ‘class1’ class:

let class1Element = document.querySelector('.class1');

And this example shows how you can find all elements in the ‘class1’ class:

let class1Elements = document.querySelectorAll('.class1');

At this point it makes sense bringing up you can group and combine different selectors. Therefore, just for the sake of a simple class naming syntax (class1 and class2), let’s take a peek at a few examples of how does combining different selectors look like:

let selectBothClasses = document.querySelectorAll('.class1.class2'); // the method will list elements with both classes - class1 and class2

let selectAtLeastOneClass = document.querySelectorAll(‘.class1,.class2’); // the method will list elements with at least one class

let OneClassButNotTheOther = document.querySelectorAll(‘.class1:not(.class2),.class2:not(.class1)’); // the method will list elements with one class but not the other

let notBothClasses = document.querySelectorAll(‘:not(.class1),:not(.class2)’); // the method will not list elements with both classes

let notAnyOfTheTwoClasses = document.querySelectorAll(‘:not(.class1):not(.class2)’); // the method will not list any of the two classes

4. Grouping selectors

We already demonstrated with a few examples above how nicely selectors can be grouped. So, when you want to group multiple selectors, you can simply use the following syntax, document.querySelectorAll(‘selector, selector’).

The method will list defined selectors and the selector will complement any element that contains one of the selectors in the defined group.

// The example below will search for all elements that contain div and h5 elements:
let groupingSelectorsEls = document.querySelectorAll('div, h5');

5. ID Selector

getElementByID is known to have an ID as a selecting parameter. However, querySelector() has an option to select an element based on the value of its id, and if you want to do that with a querySelector, you would use the id selector syntax:

let selectElementWithId = document.querySelector('#id');

At this point, we should bring out that id is always unique in the document, for this reason, it makes no sense to use the querySelectorAll() with the ID selector.

6. Attribute selector

Attribute selector enables you to select elements that have a specific attribute. But first, let’s clarify what an attribute is. For example, the name attribute identifies a name for an HTML element and can be used to reference an element in JavaScript code.

When using querySelector you can use one of the following attribute selector syntaxes:

let elByAttribute = document.querySelector('[attrib]'); // Finds the first element with an attribute name of attrib
let elByAttribute = document.querySelector('[attrib=value]'); // Finds the first element with an attribute name of attrib whose value is exactly value
let elByAttribute = document.querySelector('[attrib~=value]'); // Finds the first element with an attribute name of attrib whose value is a whitespace-separated list of words, one of which is exactly value.
let elByAttribute = document.querySelector('[attrib|=value]'); // Finds the first element with an attribute name of attrib whose value can be exactly value or can begin with value immediately followed by a hyphen
let elByAttribute = document.querySelector('[attrib^=value]'); // Finds the first element with an attribute name of attrib whose value is preceded by value.
let elByAttribute = document.querySelector('[attrib$=value]'); // Finds the first element with an attribute name of attrib whose value is followed by value.
let elByAttribute = document.querySelector('[attrib*=value]'); // Finds the first element with an attribute name of attrib whose value contains at least one occurrence of value within the string.

7. Selector combinators

We’ve already taken a look at a few examples of how combining selectors looks in the Class selector paragraph, but pay a little more attention to selector combinators.

When you want to find the first descendant of a specific node, you should use the space descendant combinator syntax, like so:

let descendantElement = document.querySelector('selector selector');

let element = document.querySelectorAll('div h1'); //'div h1' will match all h1 elements inside the div element

The child combinator ( > ) will select all elements that are direct children of the first element:

let childElement = document.querySelector('selector > selector');

let liInsideDiv = document.querySelectorAll('div > li'); // finds all li elements that are directly inside a
div element
let liInsideDivClass = document.querySelectorAll('div.class1 > li'); //finds all li elements that are inside a
div element with a class named class1

The general sibling combinator (~) selects siblings that have the same parent:

let generalSiblingCombinator = document.querySelector('selector ~ selector');

let generalSiblingCombinator = document.querySelectorAll('div ~ h1');
// div ~ h1 will match all h1 elements that follow the div element - h1 can follow div immediately or not

The adjacent sibling combinator (+) selects adjacent siblings:

let adjacentSiblingCombinator = document.querySelector('selector + selector');

let adjacentSiblingCombinator = document.querySelectorAll('div + h1');
// div + h1 will match all h1 elements that directly follow the div element

8. Pseudo selectors

Pseudo-class is a keyword added to a selector that specifies a special state of the selected element(s), therefore it matches elements based on their states. The syntax is following:

let pseudoSelectors = document.querySelector('element:state');

let hoverButton = document.querySelectorAll('button:hover'); //:hover can be used to change a button's color when the user's pointer mouse over it

In contrast to pseudo-classes used to style an element based on its state, pseudo-elements (::) are added as keywords to a selector and they enable styling a specific part of the selected element(s). This method accepts two parameters:

  1. the first parameter is the DOM element whose pseudo-element we need
  2. the second parameter specifies the pseudo-element to match, such as ::after, ::backdrop, ::before, ::first-letter, ::first-line, ::selection etc. Only one pseudo-element can be used in a selector and it must appear after the simple selectors in the statement.

However, when we want to select pseudo-elements with the querySelector method, we must work with the getComputedStyle() and getPropertyValue() methods, which is a bit more complex. Nevertheless, just for the sake of an example let’s take a look at how to get a DOM element ::before content, which was set by CSS like this:

h1::before {
  content: 'Breaking News: ';
}

We will apply all three methods querySelector(), the getComputedStyle() and the getPropertyValue(). We need to pass ‘:before’ as the second parameter to window.getComputedStyle():

let beforeValue = getComputedStyle(document.querySelector('h1'), ':before').getPropertyValue('content'));

The syntax of pseudo-elements looks like this:

element::pseudo-element {
    property: value;
}

And in an example, ::first-line can be used to change the font color and case of the first line of every p element:

p::first-line {
    color: blue;
    text-transform: uppercase;
}

To get the current CSS rules of any pseudo-element, the window.getComputedStyle() method is used, which returns all CSS properties of the element as an object.

let pElement = document.querySelector('p');

let firstLinePElement = window.getComputedStyle(pElement, ':first-line');

If this second parameter is ignored, then the CSS properties of the DOM element specified in the first parameter will be returned.