6 Ways to select HTML Elements with Javascript

Javascript Selectors Graphic

In this article

This is meant to be an overview for relative newcomers to Javascript. It’s part of a series of similar tutorials, on the basics.

The process of targeting different elements is all part of traversing the DOM (see Document Object Model). Being able to access and manipulate HTML elements with precision and dexterity is key to using Javascript.

There are quite a few ways to target HTML elements using vanilla Javascript. We’ll be looking at the most common ones.

This is the code we’ll be working with:

<div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
/*
We’ll put our javascript here.
*/
</script>

We have a basic div element containing an h2 and some paragraph tags. Good stuff. We’ve got some id’s some classes and a name attribute. Below that we’ve set up the script tags where we’ll write our Javascript.

Which looks like this:

Hi there!

Look at us,

we’re a group

of paragraph tags.

A Quick Note:

One thing to understand is that most Javascript selectors are based on criteria that can apply to multiple elements (a CSS class for instance), and can therefore retrieve more than one with a single query. Because of this, by default many selectors will return array-like lists that store the matching elements. With these selectors, even if there is only one matching element a list will still be returned.

This is significant because when you want to do something with an element that’s part of one of these lists, you have to specify it within the list first in order to properly target it. There are a number of ways you can do this. We’ll talk about some as we go.

The first method most people learn when starting out with Javascript is this classic. document.getElementById() as its name implies, searches the DOM for the given id and does whatever you tell it to do with it.

For instance: “Hi there!” is a perfectly fine greeting but what if we want people to think we’re cooler than we are? Well then we’d change it to something more hip.

Like this:

 <div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
    let mainHeading = document.getElementById("myHeading");
    mainHeading.innerHTML = "What up dog!";
</script>

We get the H2 by targeting its “myHeading” Id with getElementById(), and store it in our “mainHeading” variable. We then change its innerHTML to “What up dog!”, which is how cool people greet one another.

Which produces this:

What up dog!

Look at us,

we’re a group

of paragraph tags.

And just like that, we’re cool. You’re welcome.

One of the benefits of getElementById() is also its greatest limitation. The singular nature of id’s means that this type of selector is limited exclusively to one specific element. This is what you want when trying to precisely target an element on the page but it also means if you were to rely on this method alone, you’d need id’s on pretty much everything.

Ultimately getElementById() is a solid approach to selecting HTML elements but is less flexible and dynamic than others.

Much like our buddy getElementById(), this method will retrieve all elements with the given class name. Note that this method name specifies “Elements” plural. As I mentioned at the start getElementsByClassName() is one of those selectors that will return an array-like list, in this case an HTML collection.

Let’s take a look by getting all the paragraph tags with this method and logging the result to the console.

Like this:

<div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
    let allParagraphs = document.getElementsByClassName("myParagraphs");
    console.log(allParagraphs);
</script>

We gather all the elements with the “myParagraph” class into an HTML collection stored in our “allParagraphs” variable. We then log it to the console so we can see how getElementsByClassName() stores them.

Which would show something like this in the console:

HTMLCollection(3) [ p.myParagraphs, p.myParagraphs, p.myParagraphs.theLastParagraph, theLastOne: p.myParagraphs.theLastParagraph ] 

All the paragraph tags are listed. The last one is identified a second time by its name attribute.

Manipulating elements that are part of a group like this is a bit different than if we’d just targeted one. In order to change one for instance, like we did for the header tag a minute ago, we’ll need to specify that one in particular. Or if we want to style them all, we’d need to iterate through the entire group, applying our style to each with a function of some sort but that’s a bit beyond this lesson.

Targeting Individual Elements in an HTML Collection

Even though our HTML collection is not an actual array, we can still access individual values by specifying its numbered index within brackets. By doing so we can manipulate that value as we please.

Like so:

 <script>
    let allParagraphs = document.getElementsByClassName("myParagraphs")
    allParagraphs[0].innerHTML = "This is new!"
</script>

Notice we’ve added a “[0]” to the end of our allParagraphs variable. This indicates which item within the HTML collection we’re targeting. 0 of course refers to the first index (If this confuses you, learn more about javascript arrays here. ).

We get an HTML collection of our paragraph tags, which is stored in our variable. Then we tack [0] onto the end of the variable to specify the very first element within the collection, before changing its innerHTML.

And so we get this:

Hi there!

This is new!

we’re a group

of paragraph tags.

Getting a single element

In that last example if we wanted to get the last paragraph we could use allParagraphs[2] (2 being the index of the third item). 

A quick shortcut in cases where you know which element within a collection you’re going to want, is to simply append its index to the end of the initial selector. This tells Javascript to go ahead and give you that specific element instead of the whole list object.

It would look like this:

<script>
    let justTheLastOne = document.getElementsByClassName("theLastParagraph")[0];
    console.log(justTheLastOne);
</script>

Notice the [0] at the end of the initial selector.

This is what that would look like in the console:

<p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p> 

Notice how it now only shows the element, not the HTML collection containing it. This is an important distinction. We already told it which element within the HTML collection we wanted during the selection process, so it went ahead and returned that.

This one will be quick and easy because it’s nearly identical to getElementsByClassName(). The main difference is that we’re getting elements by their HTML tag type. 

Let’s take a look:

 <div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
    let allParagraphs = document.getElementsByTagName("p");
    console.log(allParagraphs);
</script>

Again we’re grabbing all the paragraph tags, only this time by their HTML tag type instead of their class.

Which will give us this in the console:

HTMLCollection(3) [ p.myParagraphs, p.myParagraphs, p.myParagraphs.theLastParagraph, theLastOne: p.myParagraphs.theLastParagraph ]

As you can see the result is identical to using getElementsByClassName(). It’s all the same paragraph elements we grabbed using the that method. We just got them by their tag type this time.

Another similar method to the class/tag approach is getElementsByName(). The “Name” refers to the HTML “name” attribute. It works the same as the others, only for the HTML attribute instead of a class or tag name. 

One difference is that instead of an HTML collection, getElementsByName returns a Node List. It’s very similar to an HTML collection with some differences we won’t get into here.

Usage would look something like this:

<div>
   <h2 id="myHeading">Hi there!</h2>
   <p class="myParagraphs">Look at us,</p>
   <p class="myParagraphs">we’re a group</p>
   <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
  let theLastOne = document.getElementsByName("theLastOne")[0];
  theLastOne.innerHTML = "I’ve been queried!";
</script>

Blamo:

Hi there!

Look at us,

we’re a group

I’ve been queried!

Usage for this may vary between developers but given the more limited application of the name attribute compared to classes or (obviously) HTML tags, it’s less likely you’ll need it as often.

The querySelector() method is similar to jQuery’s own if you’re familiar with that. It’s a streamlined and universal approach to retrieving just about anything in the DOM. It’s slightly newer than its getElementBy… counterparts but in terms of browser support, it’s perfectly useable.

Just like the previous methods, querySelector will get whatever we place between the parentheses. The difference is that it’s not limited to just one type. We can get an Id, a class, an HTML tag, pretty much whatever.

Check it out:

 <div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
    let mainHeading = document.querySelector("#myHeading");
    mainHeading.innerHTML = "I’ve been queried!";
</script>

Which gives us:

I’ve been queried!

This is new!

we’re a group

of paragraph tags.

One thing to note is that this method will retrieve only a single element (for multiple elements see the next section). In situations where there are multiple elements on the page, it will retrieve the first one. Also, since we can ask it for anything, we need to indicate classes and id’s with their respective identifiers ( . and # ). 

Like jQuery, we can also incorporate various parent or descendant elements within the query to narrow or broaden our search based on parent/child relationships.

To get our heading for instance we could use:

<script>
    let mainHeading = document.querySelector("div h2");
</script>

This would broaden our search to any h2’s inside of a div element (querySelector() would return the first one it finds).

Whereas querySelector() can only return a single element, querySelectorAll() can retrieve many. In this way it’s like getElementsByClassName() and getElementsByTagName() and is perfect in similar situations.

It features the same power and convenience of querySelector() however and can be used to get just about anything.

Let’s take it for a spin:

<div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
    let lastParagraph = document.querySelectorAll("div p.theLastParagraph");
    lastParagraph[0].innerHTML = "Now I’m different!";
</script>

Here we take advantage of the query methods’ ability to specify everything from html tags, classes, child elements etc. A bit overkill in this case but you get the idea.

This would return the paragraphs with the class of “theLastParagraph” that are descendents of a div tag. In the case above there is of course only one. It’s not necessary to specify to the degree we have, but this example shows the power of this method to be as specific as we would ever need to be.

Again notice we’re still having to extract the actual element from the list object by specifying its index before applying our innerHTML method.

It would give us this:

Hi there!

Look at us,

we’re a group

Now I’m different!

Up to this point I’ve used document as the base for all of our selectors. But I don’t want you to take that for granted. All of these selectors are methods, which are basically just functions that are associated with an object. I’m not going to get into methods here but I want you to note that up to this point the document is the object that we’ve been using these methods on.

The document is the root of the DOM. When we use document.querySelector() we’re telling javascript to look for something within the document. However, all of these selector methods ( with the exception of getElementById ) can be used on other DOM elements in order to confine your search to within only those.

Whatever element you choose to attach these methods to need to themselves be specified first. 

For instance:

<div>
    <h2 id="myHeading">Hi there!</h2>
    <p class="myParagraphs">Look at us,</p>
    <p class="myParagraphs">we’re a group</p>
    <p class="myParagraphs theLastParagraph" name="theLastOne">of paragraph tags.</p>
</div>

<script>
    let myDiv = document.querySelectorAll("div")[0];
    let lastParagraph = myDiv.querySelectorAll("p.theLastParagraph");
    lastParagraph[0].innerHTML = "Now I’m different!";
</script>

We first get our only div with querySelector(), storing it in the variable “myDiv”. We then use it as the root of our next query.

This would work exactly the same as our last example. Keep in mind that our example has only one div element. With an actual webpage there would likely be at least a few more. In which case our query would have grabbed the first one it found. 

In cases where the DOM structure is more complex, we could add a more unique identifier than just “div” to our first query. This would avoid any confusion and guarantee we’d get the correct element.

As we’ve seen, many selector methods will return HTML collections for us to do stuff with. A challenge for newcomers to Javascript is knowing how to sort through and work with, the elements they’ve been given. I mentioned a few basic ways to specify elements within groups.

In a follow-up article I’ll talk about some more sophisticated ways to filter through and work with collections of elements. I’ll link that here when I do.

Wrapping Up

And that covers the basic selectors available in vanilla Javascript. Hopefully this is helpful. If so, let me know. If there’s anything I missed reach out and share it. I’d love to hear from junior developers and seasoned veterans alike.

https://bydavidlange.com
by David Lange

David Lange is a freelance web designer and brand consultant living in Shelbyville Ky. A multi-disciplinary designer, illustrator, and web developer, he has a myriad of experience and insights into the world of web and branding. He's currently focused on helping small businesses understand and harness the web.