子要素の最初や最後を取得するプロパティがいくつかあります。firstChild / lastChild と firstElementChild / lastElementChild の違いを理解しましょう。
4つのプロパティ
| プロパティ | 取得対象 |
|---|---|
| firstChild | 最初の子ノード(テキスト含む) |
| lastChild | 最後の子ノード(テキスト含む) |
| firstElementChild | 最初の子要素(Element のみ) |
| lastElementChild | 最後の子要素(Element のみ) |
違いの例
<ul id="list"> <li>項目1</li> <li>項目2</li> <li>項目3</li> </ul>
const list = document.getElementById('list'); // firstChild は改行のテキストノード console.log(list.firstChild); // #text console.log(list.firstChild.nodeType); // 3(Text) // firstElementChild は最初の li 要素 console.log(list.firstElementChild); // <li>項目1</li> console.log(list.firstElementChild.nodeType); // 1(Element)
実際に動かしてみよう
HTML
CSS
JavaScript
<ul id="list"> <li>最初の項目</li> <li>真ん中の項目</li> <li>最後の項目</li> </ul> <button id="firstBtn">最初を強調</button> <button id="lastBtn">最後を強調</button>
#list li { padding: 8px; } .highlight { background: #ffeb3b; }
const list = document.getElementById('list'); document.getElementById('firstBtn').addEventListener('click', () => { list.querySelectorAll('li').forEach(li => li.classList.remove('highlight')); list.firstElementChild.classList.add('highlight'); }); document.getElementById('lastBtn').addEventListener('click', () => { list.querySelectorAll('li').forEach(li => li.classList.remove('highlight')); list.lastElementChild.classList.add('highlight'); });
子要素がない場合
子要素が存在しない場合は null を返します。
const empty = document.getElementById('empty-div'); console.log(empty.firstElementChild); // null
childNodes / children との関係
const list = document.getElementById('list'); // 同じ結果 list.firstElementChild === list.children[0] // true list.lastElementChild === list.children[list.children.length - 1] // true // childNodes でも取れるが面倒 list.childNodes[0] // テキストノードかもしれない
どれを使うべきか
Element を取得したい場合がほとんどなので、firstElementChild / lastElementChild を使いましょう。
firstChild / lastChild
テキストノードも含む。特別な理由がなければ使わない
firstElementChild / lastElementChild
Element だけを返す。通常はこちらを使う
テキストノードを操作したい特殊なケース以外は、firstElementChild / lastElementChild で十分です。