Is it possible to get all elements with class a
or b
using getElementsByClassName()
only once? I'd prefer vanilla JavaScript.

- 113,687
- 23
- 165
- 188

- 5,414
- 13
- 52
- 100
-
Did not found anything but chaining like parent.getElementsByClassName("Bottom")[0].getElementsByClassName("Left")[0] (using getElementsByClassName). – Jan Apr 06 '23 at 08:21
4 Answers
You can't do it with getElementsByClassName()
method instead use querySelectorAll()
method with comma separated class selectors.
document.querySelectorAll('.a,.b')

- 113,687
- 23
- 165
- 188
-
2This is the right answer, but note that the support for IE8 is only for CSS2 selectors, and there is no support for IE <= 7, so in that case you will need to do two selections by class. – zoubida13 May 16 '16 at 13:46
-
1I see your edit but getElementsByClassName won't work either in IE <= 7, I'm posting an alternative answer just to complete this but yours should be voted as best answer by OP. – zoubida13 May 16 '16 at 13:55
-
1
-
3@zoubida13 : I don't think there is people who still using `IE <= 7` :) ;) – Pranav C Balan May 17 '16 at 05:14
-
7even microsoft doesn't support IE7 anymore. Why companies or devs still do, I can't understand! – sertsedat May 17 '16 at 13:42
-
You can pass more than one class name to getElementsByClassName()
by separating them with spaces:
var elems = document.getElementsByClassName("class1 class2 class3");
Now, this differs from the .querySelectorAll(".class1,.class2,.class3")
approach in that it applies a conjunction, not a disjunction — "and" instead of "or". Thus
var elems = document.getElementsByClassName("class1 class2 class3");
is like
var elems = document.querySelectorAll(".class1.class2.class3");
Sometimes you want one, sometimes you want the other. It's definitely true that .querySelectorAll()
gives you much more flexibility.

- 405,095
- 59
- 585
- 614
-
9This is not right. It will search for elements that have all three classes – Unknown developer May 16 '16 at 13:42
-
7
-
2
-
2This answer doesn't work. It will only return elements with all of the specified classes. – Kelderic May 16 '16 at 15:38
-
6It's an answer in which answers the wrong question, the provided information isn't exactly relevant to the asked question. And more than likely is something the OP already knows. Hence this is mostly noise. – Spencer Wieczorek May 16 '16 at 16:11
-
1@Bitterblue it does not force an order of classes; it's the same as using `.c1.c2.c3` with `querySelectorAll()`. – Pointy Dec 17 '19 at 14:06
No, you can't achieve that with only one document.getElementsByClassName()
call. That function returns elements which have all of the classes specified in the first argument as a space-separated string.
There are two possible solution. First is to use document.querySelectorAll()
instead, which uses CSS selectors.
document.querySelectorAll(".a, .b")
The second solution is to call document.getElementsByClassName()
twice, turn the results into arrays using Array.from()
and merge them using Array.prototype.concat()
. To avoid duplicates (for example when element has both a
and b
class), you have to create a new Set from that array, and then turn it back to array using Array.from()
.
const classA = Array.from(document.getElementsByClassName("a"))
,classB = Array.from(document.getElementsByClassName("b"))
,result = Array.from(new Set(classA.concat(classB)))
See demo below:
console.log("first solution", document.querySelectorAll(".a, .b"))
const classA = Array.from(document.getElementsByClassName("a"))
,classB = Array.from(document.getElementsByClassName("b"))
,result = Array.from(new Set(classA.concat(classB)))
console.log("second solution", result)
<div class="a"></div>
<div class="b"></div>
<div class="a b"></div>
<div class="c"></div>
Note that the first solution gives an array-like NodeList
object, whereas the second gives just an array.

- 2,979
- 5
- 28
- 38

- 88,409
- 26
- 156
- 177
-
3It is pointless to use Set, because it is unsupported in those browsers, what do not support querySelectorAll. – Somnium May 16 '16 at 19:51
-
3@Somnium It's not as pointless as it looks like. Babel supports Set, but doesn't support `document.querySelectorAll()` (because it's not part of ECMAScript, but of Web APIs). If you use Babel to compile your code, the second solution will work in all browser. And frankly, I wrote the second solution rather for fun, than as a real solution. – Michał Perłakowski May 16 '16 at 19:59
-
Just to add a bit more support, here is a version that is compatible with older versions of IE and uses pure vanilla js :
function getElementsByClassNameOr(root, classNameString) // classNameString like '.a, .b' don't forget the comma separator
{
var arr = [],
rx = new RegExp('(^|[ \n\r\t\f])' + classNameString + '([ \n\r\t\f]|$)'),
elements = root.getElementsByTagName("*");
var elem;
for (i=0 ; i < elements.length ; i++) {
elem = elements[i];
if (rx.test(elem.className)) {
arr.push(elem);
}
}
return arr; // will contain all the elements that have one of the classes in ClassNameString, root can be document or a div.
}

- 1,738
- 12
- 20
-
1This will be very inefficient. Note that by supporting older browsers, one is targeting `much slower` browsers. Performance is in this situation critical, I suggest using multiple calls to `Element.getElementsByClassName` and make use of a concatenated array of the results. – Tim May 16 '16 at 15:40
-
1@Tim you are right about performance, although the fact that performance is critical in this situation is entirely down to your interpretation. And your suggestion is neither valid nor detailed. getElementsByClassName is not fully supported in IE < 9. – zoubida13 May 16 '16 at 15:44
-
1@zoubida13 You are completely right. There seems to be no other way than this answer with better performance. – Tim May 16 '16 at 15:48
-
1@Blender I replaced a comma with a semicolon it was indeed a typo yes. – zoubida13 May 16 '16 at 15:56
-
1@zoubida13: Your code assumes that the class names are right next to one another, so it won't work for `class="a b c"` when you search with `'a c'`. – Blender May 16 '16 at 15:57
-
1This code is quite insecure. Class names can take special chars, like `.[]{}()`. You need to escape those first. Also, the performance can be quite bad in no time. Instead of `(^|[ \n\r\t\f])`, use `(?:^|\s)` and instead of `([ \n\r\t\f]|$)`, use `(?:\s|$)`. Also, change `for (i=0 ; i < elements.length ; i++)` into `for (var i = 0, length = elements.length; i < length ; i++)`. – Ismael Miguel May 16 '16 at 17:22
-
1Doesn't `classNameString` need to be something like `(?:a|b)` instead of `.a, .b`??? – Bergi May 16 '16 at 20:56