This is my code:
<html>
<h1 id="hg">
<h2>11</h2>
<h2>22</h2>
<h2>33</h2>
</h1>
<script>
var h = document.getElementById("hg").getElementsByTagName("h2");
alert(h.length);
</script>
</html>
I have looked up the manual, it seems that getElementById
returns an HTMLHeadingElement
in this case, and it inherits the method getElementsByTagName
from Element
. I expect to get a 3
as the value of h.length
, but instead I get 0
. What's wrong with it?
This is my code:
<html>
<h1 id="hg">
<h2>11</h2>
<h2>22</h2>
<h2>33</h2>
</h1>
<script>
var h = document.getElementById("hg").getElementsByTagName("h2");
alert(h.length);
</script>
</html>
I have looked up the manual, it seems that getElementById
returns an HTMLHeadingElement
in this case, and it inherits the method getElementsByTagName
from Element
. I expect to get a 3
as the value of h.length
, but instead I get 0
. What's wrong with it?
- 1 It's because your HTML is invalid. Headings cannot sit inside another heading. If you check your page in a DOM inspector such as Firebug you'll see the actual HTML being rendered is quite different to that you have written. – Rory McCrossan Commented Nov 23, 2013 at 15:13
2 Answers
Reset to default 9You'll find that a <h1>
cannot contain another heading (the only valid content of an h1
, and other headings, is phrasing content, which restricts content to, very simplistically, in-line elements and text), therefore when the browser constructs the DOM it moves the h2
elements outside of the h1
, which prevents them being found, by the DOM, inside the h1
.
In Chrome, your HTML is reorganised to the following (and, I presume, similarly rearranged in other browsers):
<h1 id="hg"></h1>
<h2>11</h2>
<h2>22</h2>
<h2>33</h2>
This rescuing of the DOM to maintain validity is why we should, as developers, always strive to create valid HTML: because the automatic corrections made by browsers are undocumented and unpredictable (prior to HTML 5, which I think documents how error recovery should proceed).
Incidentally, this sounds very similar to the use-case presented for the <hgroup>
element (which seems to be in the process of being dropped from the spec). Given, however, that you appear to be presenting a list of contents I'd suggest enclosing the <h2>
elements in an <ol>
and semantically grouping them that way:
<ol id="contents">
<li><h2>11</h2></li>
<li><h2>22</h2></li>
<li><h2>33</h2></li>
</ol>
you need to change your html to this for example:
<div id="hg">
<h2>11</h2>
<h2>22</h2>
<h2>33</h2>
</div>
DEMO