Dom tree

Selecting DOM elements and querySelector

Selecting DOM elements and querySelector

The first element we are going to talk about here is the id attribute. Since id is a global attribute, if an element has an id it means that there is a global variable attached to the element. We can use document.getElementById or just id to access the required element. For example:


<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>

<div id="firstDiv">
</div>

<script>

  // we can access the element through the global variable of its id
  alert(firstDiv);
  
  //or
  // we can access the element through the property of the window global variable
  alert(window.firstDiv);
</script>

</body>
</html>

Output



Its really nice and helpful of the browser to mix up DOM attributes with the JavaScript namespace. This means we are using the id attribute of a DOM element as a JavaScript variable we are going to hit a snag when dealing with hyphenated ids. In DOM its legal to have an id attribute that is hyphenated but in JavaScript its illegal to have a hyphen in a variable name. This means that the code below wont work because of the hyphen:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>

<div id="first-Div">
</div>

<script>

  // a JavaScript variable cant have a hyphen 
  alert(first-Div);
  
  //or
  // a JavaScript attribute cant have a hyphen
  alert(window.first-Div);
</script>

</body>
</html>

If the variable name has a hyphen (or if its any other illegal JavaScript identifier) we have to access it as a window attribute through square brackets as shown below:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>

<div id="first-Div">
</div>

<script>

  alert(window["first-Div"]);
</script>

</body>
</html>

Of course the mixing of DOM attributes with the JavaScript namespace comes with consequences. If you later declare a variable with the same name as the id of an element, the element gets overridden and we lose access to the element.



<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>

<div id="mySpace"></div>

<script>

var mySpace = 5;

alert(mySpace); // the variable declaration overrides the element

</script>

</body>
</html>

Output



getElementById(id)

To avoid the naming conflicts mentioned above we use the special document method : document.getElementById(id) the elements. Also, the id of an element should be unique because, if there are multiple elements with the same id, the behavior of the script becomes unpredictable and may return any of them at random.

This method is callable only from the document object.


Example of using getElementById

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>

<ol id="ourList">

<li id="myItem">Mine</li>
<li id="yourItem">Yours</li>
<li id="ourItem">Ours</li>

</ol>

<script>

document.getElementById('ourList').style.color ="white";
document.getElementById('ourList').style.fontSize ="23px";
document.getElementById('ourList').style.background ="black";

document.getElementById('myItem').style.background ="blue";

document.getElementById('yourItem').style.background ="purple";

document.getElementById('ourItem').style.fontFamily ="Times";
</script>

</body>
</html>

Output



getElementsByTagName(tag)

elem.getElementsByTagName(tag) returns a collection of elements with the given tag. The tag parameter can also be a wildcard "*" for "any tags".


For example

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>

<body>
<ol id="ourList">

<li id="myItem">Mine</li>
<li id="yourItem">Yours</li>
<li id="ourItem">Ours</li>

</ol>

<script>


//get a collection of all li tags to variable items
let items = document.getElementsByTagName('li');

//set list item 2 background color gray
items[1].style.background = "gray"

//iterate through all items setting color to blue
for (let item of items){
item.style.color = "blue"
}

</script>

</body>
</html>

Output

Warning

  • Unlike getElementById, this method is callable through any DOM element. For example you can find all input tags inside a table by using table.getElementsByTagName('input').
  • Take note of the plural (s) on getElementsByTagName() and the singular (no s) in getElementById(). It’s easy to make mistakes there. getElementById is singular because it returns a single element and getElementsByTagName is plural because it returns a collection of elements.
  • document.getElementsByTagName() returns a collection of elements, so an assignation like document.getElementsByTagName('input').value = 87 wont work. We basically have to iterate over the collection or access a single element by its index, and then assign it, like
    document.getElementsByTagName('input')[3].value = 23 if its the fourth input element we want to assign a value of 23.

getElementsByClassName(className)

getElementsByClassName(className) returns a collection of elements that have the given CSS class.

querySelectorAll(query)

querySelectorAll(query) returns a collection of all elements matching the given CSS selector query.

Lets see an example on selecting the <li> elements that are last children of a <ul> list:


<!DOCTYPE html>
<html>
<head>
<title></title>
</head>

<body>

<ul>
  <li>Watch</li>
  <li>what</li>
  <li>happens</li>
  <li>to</li>
  <li>the</li>
  <li>last</li>
  <li>item</li>
  <li>on this list</li>
</ul>

<ul>
  <li>This</li>
  <li>list</li>
  <li>too</li>
</ul>
<script>

//query the last li child of every ul list
  let items = document.querySelectorAll('ul > li:last-child');


  for (let item of items) {
   item.style.color = "red";
  }
</script>


</body>
</html>

Output




<!DOCTYPE html>
<html>
<head>
<title></title>
</head>

<body>

<ul id="first">
  <li>Watch</li>
  <li>what</li>
  <li>happens</li>
  <li>to</li>
  <li>the</li>
  <li>items</li>
  <li>on this list</li>
</ul>

<ul id="second">
  <li>Not</li>
  <li>this</li>
  <li>one</li>
</ul>
<script>

//query the li children of element with id 'first'
  let items = document.querySelectorAll('#first > li');


  for (let item of items) {
   item.style.color = "red";
  }
</script>


</body>
</html>

Output



This method is a favourite for many front end web developers because any CSS selector can be used as a query.

querySelector(query)

The method querySelector(query) returns the first element for the given CSS selector query which is basically the same as querySelectorAll(query)[0] but faster because it searches specifically for one element.

matches(query)

The matches(query) merely checks if the given element matches the given CSS selector query. Its a boolean method which means it returns either true or false. We can use the method to filter elements if the method returns true.


For example:

<!DOCTYPE html>
<html>
<head>
<title></title>
</head>

<body>

<p class="greeting"> Hi, hello</p>
<p class="question"> Are enjoying this?</p>
<p class="question"> Seriously?</p>

<script>
  // get a collection of document.body.children
  for (let para of document.body.children) {
  
  //match elements with class "greeting"
    if (para.matches('.greeting')) {
    
    //if true
    para.style.background = "blue";
    para.style.color = "white";
    }
  }
</script>


</body>
</html>

Output



closest(query)

All elements directly above a given element are called its ancestors. Ancestors are, the parent, the parent of the parent, and so on, forming a chain of parents from the element back to the top.

The method elem.closest(query) looks for nearest ancestor, including the element itself, that matches the CSS-selector query.