Question
Do getElementsByClassName
(and similar functions like getElementsByTagName
and querySelectorAll
) work the same as getElementById
or do they return an
array of elements?
The reason I ask is because I am trying to change the style of all elements
using getElementsByClassName
. See below.
//doesn't work
document.getElementsByClassName('myElement').style.size = '100px';
//works
document.getElementById('myIdElement').style.size = '100px';
Answer
Your [getElementById
](https://developer.mozilla.org/en-
US/docs/Web/API/Document/getElementById) code works since IDs have to be
unique and thus the function always returns exactly one element (or null
if
none was found).
However, the methods
[getElementsByClassName
](https://developer.mozilla.org/en-
US/docs/Web/API/Document/getElementsByClassName),
[getElementsByName
](https://developer.mozilla.org/en-
US/docs/Web/API/Document/getElementsByName),
[getElementsByTagName
](https://developer.mozilla.org/en-
US/docs/Web/API/Document/getElementsByTagName), and
[getElementsByTagNameNS
](https://developer.mozilla.org/en-
US/docs/Web/API/Document/getElementsByTagNameNS) return an iterable collection
of elements.
The method names provide the hint: getElement
implies singular , whereas
getElements
implies plural.
The method [querySelector
](https://developer.mozilla.org/en-
US/docs/Web/API/Element/querySelectorAll) also returns a single element, and
[querySelectorAll
](https://developer.mozilla.org/en-
US/docs/Web/API/Element/querySelectorAll) returns an iterable collection.
The iterable collection can either be a
NodeList
or an
[HTMLCollection
](https://developer.mozilla.org/en-
US/docs/Web/API/HTMLCollection).
[getElementsByName
](https://html.spec.whatwg.org/multipage/dom.html#the-
document-object) and
querySelectorAll
are
both specified to return a NodeList
; the other getElementsBy*
methods are specified to
return an HTMLCollection
, but please note that some browser versions
implement this differently.
Both of these collection types don’t offer the same properties that Elements,
Nodes, or similar types offer; that’s why reading style
off of
document.getElements
…(
…)
fails. In other words: a NodeList
or an
HTMLCollection
doesn’t have a style
; only an Element
has a style
.
These “array-like” collections are lists that contain zero or more elements,
which you need to iterate over, in order to access them. While you can iterate
over them similarly to an array, note that they are
different from
[Array
s](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array).
In modern browsers, you can convert these iterables to a proper Array with
[Array.from
](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array/from); then you can use
forEach
and other [Array methods, e.g. iteration
methods](https://developer.mozilla.org/en-
US/docs/Web/JavaScript/Reference/Global_Objects/Array#instance_methods):
Array.from(document.getElementsByClassName("myElement"))
.forEach((element) => element.style.size = "100px");
In old browsers that don’t support Array.from
or the iteration methods, you
can still use
Array.prototype.slice.call
. Then you
can iterate over it like you would with a real array:
var elements = Array.prototype.slice
.call(document.getElementsByClassName("myElement"));
for(var i = 0; i < elements.length; ++i){
elements[i].style.size = "100px";
}
You can also iterate over the NodeList
or HTMLCollection
itself, but be
aware that in most circumstances, these collections are live ([MDN
docs](https://developer.mozilla.org/en-
US/docs/Web/API/NodeList#live_vs._static_nodelists), DOM
spec), i.e. they are
updated as the DOM changes. So if you insert or remove elements as you loop,
make sure to not accidentally skip over some
elements or create an infinite
loop. MDN documentation should always
note if a method returns a live collection or a static one.
For example, a NodeList
offers some iteration methods such as forEach
in
modern browsers:
document.querySelectorAll(".myElement")
.forEach((element) => element.style.size = "100px");
A simple for
loop can also be used:
var elements = document.getElementsByClassName("myElement");
for(var i = 0; i < elements.length; ++i){
elements[i].style.size = "100px";
}
Aside: [.childNodes
](https://developer.mozilla.org/en-
US/docs/Web/API/Node/childNodes) yields a live NodeList
and
[.children
](https://developer.mozilla.org/en-
US/docs/Web/API/Element/children) yields a live HTMLCollection
, so these
two getters also need to be handled carefully.
There are some libraries like jQuery which make DOM querying a bit shorter and create a layer of abstraction over “one element” and “a collection of elements”:
$(".myElement").css("size", "100px");