How to get child element by class name?

498,729

Solution 1

Use doc.childNodes to iterate through each span, and then filter the one whose className equals 4:

var doc = document.getElementById("test");
var notes = null;
for (var i = 0; i < doc.childNodes.length; i++) {
    if (doc.childNodes[i].className == "4") {
      notes = doc.childNodes[i];
      break;
    }        
}

Solution 2

Use querySelector and querySelectorAll

var testContainer = document.querySelector('#test');
var fourChildNode = testContainer.querySelector('.four');

IE9 and upper

Solution 3

The accepted answer only checks immediate children. Often times we're looking for any descendants with that class name.

Also, sometimes we want any child that contains a className.

For example: <div class="img square"></div> should match a search on className "img", even though it's exact className is not "img".

Here's a solution for both of these issues:

Find the first instance of a descendant element with the class className

   function findFirstChildByClass(element, className) {
        var foundElement = null, found;
        function recurse(element, className, found) {
            for (var i = 0; i < element.childNodes.length && !found; i++) {
                var el = element.childNodes[i];
                var classes = el.className != undefined? el.className.split(" ") : [];
                for (var j = 0, jl = classes.length; j < jl; j++) {
                    if (classes[j] == className) {
                        found = true;
                        foundElement = element.childNodes[i];
                        break;
                    }
                }
                if(found)
                    break;
                recurse(element.childNodes[i], className, found);
            }
        }
        recurse(element, className, false);
        return foundElement;
    }

Solution 4

Use element.querySelector(). Lets assume: 'myElement' is the parent element you already have. 'sonClassName' is the class of the child you are looking for.

let child = myElement.querySelector('.sonClassName');

For more info, visit: https://developer.mozilla.org/en-US/docs/Web/API/Element/querySelector

Solution 5

Modern solution

const context = document.getElementById('context');
const selected = context.querySelectorAll(':scope > div');

documentation

Share:
498,729

Related videos on Youtube

spyderman4g63
Author by

spyderman4g63

I'm not a real programmer I just hack stuff together.

Updated on October 15, 2021

Comments

  • spyderman4g63
    spyderman4g63 over 2 years

    I'm trying to get the child span that has a class = 4. Here is an example element:

    <div id="test">
     <span class="one"></span>
     <span class="two"></span>
     <span class="three"></span>
     <span class="four"></span>
    </div>
    

    The tools I have available are JS and YUI2. I can do something like this:

    doc = document.getElementById('test');
    notes = doc.getElementsByClassName('four');
    
    //or
    
    doc = YAHOO.util.Dom.get('#test');
    notes = doc.getElementsByClassName('four');
    

    These do not work in IE. I get an error that the object (doc) doesn't support this method or property (getElementsByClassName). I've tried a few examples of cross browser implementations of getElementsByClassName but I could not get them to work and still got that error.

    I think what I need is a cross browser getElementsByClassName or I need to use doc.getElementsByTagName('span') and loop through until I find class 4. I'm not sure how to do that though.

    • mostar
      mostar almost 12 years
    • Prinzhorn
      Prinzhorn almost 12 years
      Funny enough, the more powerful querySelectorAll is supported by IE 8+ whereas getElementsByClassName is only supported by IE 9+. If you can drop IE 7, you are safe to use querySelectorAll('.4'). By the way, 4 is an invalid class name.
    • spyderman4g63
      spyderman4g63 almost 12 years
      @paritybit that question doesn't work because it still utilizes getElementsByClassName and older version of IE don't seem to support that. edit: I'm sorry it uses tag name. This may work.
    • spyderman4g63
      spyderman4g63 almost 12 years
      @Prinzhorn I do not have the YUI2 selector utility available in this product for some reason.
    • Prinzhorn
      Prinzhorn almost 12 years
      @spyderman4g63 I did not talk about anything YUI2 specific. document.querySelectorAll is DOM and has nothing to do with YUI
  • spyderman4g63
    spyderman4g63 almost 12 years
    The problem is that getElementsByClassName doesn't work in IE8.
  • spyderman4g63
    spyderman4g63 almost 12 years
    Sorry, that # was a typo. I can select the container div, but cannot select the child elements by tag name because that function is not working in ie8.
  • spyderman4g63
    spyderman4g63 almost 12 years
    Thanks, but there are a variable amount of child elements.
  • Guffa
    Guffa almost 12 years
    @spyderman4g63: The getElementsByTagName method works in IE 8. It is supported as far back as IE 5.5. developer.mozilla.org/en-US/docs/DOM/…
  • spyderman4g63
    spyderman4g63 almost 12 years
    Hmm. The example does work in IE8, but maybe it doesn't work in the case that you apply it to an object. In my case is set doc as a yui dom object and then use doc.getElementsByClassName. That's when it fails. edit: or maybe I don't understand how that object works and it is just a normal dom object?
  • Hank Gay
    Hank Gay almost 12 years
    @spyderman4g63 the YUI version of getElementsByClassName is a method of YAHOO.util.Dom. In your case, the call would look something like YAHOO.util.Dom.getElementsByClassName('four', 'span', 'test'). You should probably read the docs to get a more detailed understanding of what that call is doing. The short version is that it will now look for span elements with the class four underneath the DOM element with test as its id.
  • Hank Gay
    Hank Gay almost 12 years
    @spyderman4g63 Yes, the result of the get call is just a DOM element. YUI doesn't take the sort of whole-sale 'wrap everything in a framework-specific object' approach that something like jQuery does, nor does it monkey-patch native objects like Prototype does (did? I haven't messed w/ Protoype in forever). In this respect, YUI is more like Dojo.
  • Christian Jørgensen
    Christian Jørgensen almost 11 years
    To me it seemed like the question was to always get the fourth span child, thus leading to my answer. I do of course agree that a function to get whatever type of element at whatever index within an other element would be better, but I did no interpret the question like that... reading the question again I see that I totally misunderstood though :-)
  • Fran Verona
    Fran Verona over 10 years
    This code doesn't work if element has more than one class. For example: if you're looking for elements with "one" class, and your elements have "one two three" class, this function will not find them.
  • Jya
    Jya over 9 years
    question is about javascript not jQuery
  • James Poulose
    James Poulose over 9 years
    @FranVerona Just out of curiosity, wouldn't a simple "indexOf('className') > -1" solve the multiple class issue?
  • deadboy
    deadboy over 9 years
    @JamesPoulose, it wouldn't. Consider having an element set to two classes: small and bigger. thatElement.className would return a String that equals "small bigger". If you're looking for a class called big saying myElement.className.indexOf("big") will produce something unequal to negative 1 despite that not actually being a part of the class. If you have 100% control of your class names, such a fix would work, it's just not guaranteed to, especially when your'e writing code that's going to interact code you don't have total control over.
  • WebWanderer
    WebWanderer over 8 years
    You should use a regex match on the className like so: if(doc.childNode[i].className.match("\s*" + search_class + "\s*") where the variable search_class is the class name that you are looking for.
  • Paul Draper
    Paul Draper almost 8 years
    Nope. I don't want all descendants, just the child like the question asked.
  • Augie Gardner
    Augie Gardner almost 8 years
    Whelp. Your comment was necessary. Glad I helped 13 other people who (like me) often search for similar answers to solve their similar-but-perhaps-more-complex-or-general problem.
  • Jacksonkr
    Jacksonkr over 7 years
    TagName that's it! So simple.
  • Louise Eggleton
    Louise Eggleton over 7 years
    I use this technique frequently to get the first element eg document.getElementById("test").childNodes[0]
  • Boban Stojanovski
    Boban Stojanovski over 7 years
    tnx, i think this answer suits more use cases
  • Rob
    Rob over 7 years
    I was wondering if browsers finally had this functionality without requiring something like jQuery, glad to see it. If anyone is curious, looks like it's supported in most modern browsers: developer.mozilla.org/en-US/docs/Web/API/Document/…
  • Brian McCall
    Brian McCall about 6 years
    The real problem is that Typescript generates their definitions from IE so this solution doesn't work in typescript
  • Nic
    Nic about 6 years
    @WebWanderer That also fails in the same scenario described by Evin. You're thinking of either \s+ -- which fails if it's the first, last, or only class -- or \b, which would work.
  • YakovL
    YakovL almost 5 years
    @LouiseEggleton there's .firstChild and .firstChildElement though
  • malat
    malat about 4 years
    For some reason I had to use let child = myElement.querySelector('sonClassName'); in my case
  • Hamza Dahmoun
    Hamza Dahmoun about 4 years
    But you have to add the dot next to the class name querySelector('.sonClassName'), otherwise it will handle it as sonClassName is a tag name not a class name
  • SUM1
    SUM1 about 4 years
    This checks for all descendants, not just children.
  • SUM1
    SUM1 about 4 years
    For the record, I've had both use cases, descendants slightly more often, but I came here for the child use case.
  • CaseyC
    CaseyC over 3 years
    This a good answer. It will fail if the element has more than one class though. You can use String.includes('yourclass') to avoid this though. const childNode = Array.from(parentNode.childNodes).find(({ className }) => className && className.includes('four'));
  • SapuSeven
    SapuSeven over 3 years
    Check compatibility at caniuse.com
  • SapuSeven
    SapuSeven over 3 years
    @SUM1 If you don't care about IE, you can use the CSS pseudo element :scope to check for direct descendants like this: testContainer.querySelector(':scope > .four')
  • robsch
    robsch about 3 years
    On Stackoverflow this is an insufficient answer since you didn't explain anything.
  • Koyaanis
    Koyaanis about 3 years
    Sorry I'll add a small description
  • kingurr
    kingurr about 3 years
    in order to get all of the children we need to use var fourChildNode = testContainer.querySelectorAll('.four');