子要素を取得する!JavaScriptのchildrenプロパティ入門
JavaScriptのchildrenプロパティの基本的な使い方から実践的な活用方法まで詳しく解説。DOM操作で子要素を取得・操作する方法を、初心者向けに分かりやすく説明します。
子要素を取得する!JavaScriptのchildrenプロパティ入門
みなさん、Webページの要素を操作していて「子要素だけを取りたい」と思ったことはありませんか?
「親要素の中身を操作したいけど、どうやるの?」 「childNodesとchildrenって、何が違うの?」
こんな疑問を持ったことはありませんか?
この記事では、JavaScriptのchildrenプロパティを初心者向けに分かりやすく解説します。 基本的な使い方から実際に使える応用例まで、完全なコード付きでお教えします。
一緒にDOM操作をマスターしていきましょう!
childrenプロパティって何?
簡単に言うと子要素を取得する機能
childrenプロパティは、指定した要素の子要素を取得するための機能です。 HTMLの要素だけを取得してくれる便利なプロパティです。
// 基本的な使い方let parentElement = document.getElementById("parent");let childElements = parentElement.children;
console.log(childElements); // HTMLCollectionconsole.log(childElements.length); // 子要素の数
このコードで、親要素の中にある子要素をすべて取得できます。
childNodesとの違いを理解しよう
実は、子要素を取得する方法は2つあります。 違いを知っておくと、とても役立ちます。
<div id="container"> <p>段落1</p> テキストノード <p>段落2</p> <!-- コメント --> <span>スパン</span></div>
let container = document.getElementById("container");
// childNodes: すべての子ノード(テキスト、コメント含む)console.log(container.childNodes);// NodeList(7) [text, p, text, p, text, comment, text, span, text]
// children: HTML要素のみconsole.log(container.children);// HTMLCollection(3) [p, p, span]
childNodesは改行やスペースも含めて、すべてを取得します。 childrenはHTMLタグの要素だけを取得します。
通常はchildrenを使う方が便利です。
基本的な使い方をマスターしよう
子要素にアクセスする方法
子要素を取得したら、一つずつアクセスできます。
<ul id="menu"> <li>ホーム</li> <li>サービス</li> <li>お問い合わせ</li></ul>
let menu = document.getElementById("menu");let menuItems = menu.children;
console.log(`メニュー項目数: ${menuItems.length}`);
// 各子要素にアクセスfor (let i = 0; i < menuItems.length; i++) { console.log(`${i}: ${menuItems[i].textContent}`);}
このコードで、メニューの各項目を順番に表示できます。
for文を使って、すべての子要素を処理できます。
もっと簡単な書き方もあります。
// for...of文を使った方法for (let item of menuItems) { console.log(item.textContent);}
これなら、よりシンプルに書けます。
特定の子要素を取得する方法
配列のように、インデックスで特定の子要素を取得できます。
let parent = document.getElementById("parent");
// 最初の子要素let firstChild = parent.children[0];console.log("最初の子要素:", firstChild);
// 最後の子要素let lastChild = parent.children[parent.children.length - 1];console.log("最後の子要素:", lastChild);
// 2番目の子要素let secondChild = parent.children[1];console.log("2番目の子要素:", secondChild);
配列と同じように、0から番号が始まります。
安全に要素を取得するには、存在チェックも大切です。
// 存在チェックif (parent.children.length > 2) { console.log("3番目の子要素:", parent.children[2]);} else { console.log("3番目の子要素は存在しません");}
要素が存在するかチェックしてからアクセスすれば安全です。
HTMLCollectionの特徴を知ろう
childrenプロパティが返すのは、HTMLCollectionという特別な形式です。 これは「生きている」コレクションと呼ばれます。
let parent = document.getElementById("parent");let children = parent.children;
// 最初の子要素数console.log("初期の子要素数:", children.length);
// 新しい要素を追加let newElement = document.createElement("div");newElement.textContent = "新しい要素";parent.appendChild(newElement);
// childrenは自動的に更新されるconsole.log("追加後の子要素数:", children.length);
DOM(ページの構造)が変わると、childrenも自動的に更新されます。 これが「生きている」と呼ばれる理由です。
ただし、配列のメソッドは使えません。
// 配列メソッドは使用不可// children.forEach(...); // エラー!
// 配列に変換する方法let childrenArray = Array.from(children);childrenArray.forEach(child => { console.log(child.textContent);});
配列のメソッドを使いたい場合は、Array.from()
で配列に変換します。
実際に作ってみよう
実用的なアプリケーションを作りながら、childrenプロパティの使い方を学びましょう。
ToDoリストアプリ
まずは、シンプルなToDoリストを作ってみます。
<div id="todo-container"> <h3>TODOリスト</h3> <ul id="todo-list"> <li>タスク1</li> <li>タスク2</li> <li>タスク3</li> </ul> <button id="add-task">タスク追加</button></div>
let todoList = document.getElementById("todo-list");let addButton = document.getElementById("add-task");
// タスクを追加addButton.addEventListener("click", function() { let taskNumber = todoList.children.length + 1; let newTask = document.createElement("li"); newTask.textContent = `タスク${taskNumber}`; // 削除ボタンを追加 let deleteBtn = document.createElement("button"); deleteBtn.textContent = "削除"; deleteBtn.style.marginLeft = "10px"; newTask.appendChild(deleteBtn); todoList.appendChild(newTask);});
「タスク追加」ボタンをクリックすると、新しいタスクが追加されます。
todoList.children.length
で現在のタスク数を確認して、番号を付けています。
削除機能も追加してみましょう。
// 削除ボタンのクリック処理deleteBtn.addEventListener("click", function() { todoList.removeChild(newTask); updateTaskNumbers();});
// タスク番号を更新function updateTaskNumbers() { let tasks = todoList.children; for (let i = 0; i < tasks.length; i++) { let task = tasks[i]; let textNode = task.firstChild; if (textNode.nodeType === Node.TEXT_NODE) { textNode.textContent = `タスク${i + 1}`; } }}
タスクを削除したら、番号を振り直します。
todoList.children
でリアルタイムのタスク一覧を取得できます。
タブメニューシステム
タブで画面を切り替える機能を作ってみましょう。
<div id="tab-container"> <div id="tab-headers"> <button class="tab-header active" data-tab="tab1">タブ1</button> <button class="tab-header" data-tab="tab2">タブ2</button> <button class="tab-header" data-tab="tab3">タブ3</button> </div> <div id="tab-contents"> <div id="tab1" class="tab-content active">タブ1の内容</div> <div id="tab2" class="tab-content">タブ2の内容</div> <div id="tab3" class="tab-content">タブ3の内容</div> </div></div>
let tabHeaders = document.getElementById("tab-headers");let tabContents = document.getElementById("tab-contents");
// タブヘッダーのクリックイベントtabHeaders.addEventListener("click", function(event) { if (event.target.classList.contains("tab-header")) { let targetTab = event.target.getAttribute("data-tab"); switchTab(targetTab); }});
まず、タブをクリックしたときの処理を作ります。
どのタブがクリックされたかを取得して、switchTab
関数に渡します。
次に、タブ切り替えの処理を作りましょう。
function switchTab(targetTabId) { // すべてのタブヘッダーからactiveクラスを削除 let headers = tabHeaders.children; for (let header of headers) { header.classList.remove("active"); } // すべてのタブコンテンツからactiveクラスを削除 let contents = tabContents.children; for (let content of contents) { content.classList.remove("active"); } // 選択されたタブをアクティブに let activeHeader = tabHeaders.querySelector(`[data-tab="${targetTabId}"]`); let activeContent = document.getElementById(targetTabId); if (activeHeader && activeContent) { activeHeader.classList.add("active"); activeContent.classList.add("active"); }}
tabHeaders.children
とtabContents.children
で、すべてのタブ要素を取得しています。
一度すべてを非アクティブにしてから、選択されたタブだけをアクティブにします。
画像ギャラリー
画像を切り替えるギャラリーも作ってみましょう。
<div id="gallery"> <div id="thumbnail-container"> <img src="thumb1.jpg" alt="画像1" class="thumbnail"> <img src="thumb2.jpg" alt="画像2" class="thumbnail"> <img src="thumb3.jpg" alt="画像3" class="thumbnail"> </div> <div id="main-image-container"> <img id="main-image" src="main1.jpg" alt="メイン画像"> </div> <div id="gallery-controls"> <button id="prev-btn">前へ</button> <span id="image-counter">1 / 3</span> <button id="next-btn">次へ</button> </div></div>
let thumbnailContainer = document.getElementById("thumbnail-container");let mainImage = document.getElementById("main-image");let imageCounter = document.getElementById("image-counter");let currentImageIndex = 0;
// サムネイルクリック時の処理thumbnailContainer.addEventListener("click", function(event) { if (event.target.classList.contains("thumbnail")) { let thumbnails = thumbnailContainer.children; // クリックされたサムネイルのインデックスを取得 for (let i = 0; i < thumbnails.length; i++) { if (thumbnails[i] === event.target) { currentImageIndex = i; break; } } updateMainImage(); }});
サムネイルをクリックすると、そのインデックスを取得してメイン画像を更新します。
前へ・次へボタンの処理も追加しましょう。
let prevBtn = document.getElementById("prev-btn");let nextBtn = document.getElementById("next-btn");
// 前の画像prevBtn.addEventListener("click", function() { let thumbnails = thumbnailContainer.children; currentImageIndex = (currentImageIndex - 1 + thumbnails.length) % thumbnails.length; updateMainImage();});
// 次の画像nextBtn.addEventListener("click", function() { let thumbnails = thumbnailContainer.children; currentImageIndex = (currentImageIndex + 1) % thumbnails.length; updateMainImage();});
function updateMainImage() { let thumbnails = thumbnailContainer.children; let currentThumbnail = thumbnails[currentImageIndex]; // メイン画像を更新 let mainSrc = currentThumbnail.src.replace("thumb", "main"); mainImage.src = mainSrc; // カウンターを更新 imageCounter.textContent = `${currentImageIndex + 1} / ${thumbnails.length}`;}
thumbnails.length
でサムネイルの総数を取得して、画像カウンターを更新しています。
便利なテクニック
子要素を検索・フィルタリングする
条件に合う子要素だけを取り出す方法です。
<div id="product-list"> <div class="product" data-category="electronics" data-price="1000"> <h3>商品A</h3> <p>価格: 1000円</p> </div> <div class="product" data-category="books" data-price="500"> <h3>商品B</h3> <p>価格: 500円</p> </div> <div class="product" data-category="electronics" data-price="2000"> <h3>商品C</h3> <p>価格: 2000円</p> </div></div>
let productList = document.getElementById("product-list");
// 特定のカテゴリーの商品を取得function getProductsByCategory(category) { let products = productList.children; let filteredProducts = []; for (let product of products) { if (product.getAttribute("data-category") === category) { filteredProducts.push(product); } } return filteredProducts;}
// 価格範囲で商品を取得function getProductsByPriceRange(minPrice, maxPrice) { let products = productList.children; let filteredProducts = []; for (let product of products) { let price = parseInt(product.getAttribute("data-price")); if (price >= minPrice && price <= maxPrice) { filteredProducts.push(product); } } return filteredProducts;}
productList.children
ですべての商品を取得して、条件に合うものだけを配列に入れています。
使ってみましょう。
// 使用例let electronicsProducts = getProductsByCategory("electronics");console.log("電子機器商品:", electronicsProducts);
let affordableProducts = getProductsByPriceRange(0, 1000);console.log("1000円以下の商品:", affordableProducts);
データ属性を使って、商品を分類・検索できます。
子要素を並び替える
子要素の順番を変更する方法です。
<div id="sortable-list"> <div class="item" data-name="Apple" data-price="100"> <span>Apple - 100円</span> </div> <div class="item" data-name="Banana" data-price="50"> <span>Banana - 50円</span> </div> <div class="item" data-name="Cherry" data-price="200"> <span>Cherry - 200円</span> </div></div>
let sortableList = document.getElementById("sortable-list");
// 名前でソートfunction sortByName(ascending = true) { let items = Array.from(sortableList.children); items.sort((a, b) => { let nameA = a.getAttribute("data-name").toLowerCase(); let nameB = b.getAttribute("data-name").toLowerCase(); if (ascending) { return nameA.localeCompare(nameB); } else { return nameB.localeCompare(nameA); } }); // 並び替えた順序でDOMを更新 items.forEach(item => sortableList.appendChild(item));}
Array.from()
でHTMLCollectionを配列に変換してから、ソートしています。
最後にappendChild()
で順番を変更します。
価格でソートする機能も作ってみましょう。
// 価格でソートfunction sortByPrice(ascending = true) { let items = Array.from(sortableList.children); items.sort((a, b) => { let priceA = parseInt(a.getAttribute("data-price")); let priceB = parseInt(b.getAttribute("data-price")); if (ascending) { return priceA - priceB; } else { return priceB - priceA; } }); // 並び替えた順序でDOMを更新 items.forEach(item => sortableList.appendChild(item));}
価格の場合は、数値として比較する必要があります。
注意すべきポイント
HTMLCollectionは配列ではない
よくある間違いを知っておきましょう。
let parent = document.getElementById("parent");let children = parent.children;
// 間違い:HTMLCollectionに配列メソッドを使用// children.forEach(...); // エラー!// children.map(...); // エラー!
// 正しい:配列に変換してから使用Array.from(children).forEach(child => { console.log(child);});
// または[...children].forEach(child => { console.log(child);});
配列のメソッドを使いたい場合は、必ず配列に変換してください。
要素を削除するときの注意
ループ中に要素を削除すると、問題が起こることがあります。
let parent = document.getElementById("parent");
// 間違い:ループ中に要素を削除for (let i = 0; i < parent.children.length; i++) { parent.removeChild(parent.children[i]); // インデックスが変わる!}
// 正しい:後ろから削除for (let i = parent.children.length - 1; i >= 0; i--) { parent.removeChild(parent.children[i]);}
要素を削除すると、残りの要素のインデックスが変わります。 後ろから削除するか、配列に変換してから削除しましょう。
要素の存在確認を忘れずに
要素が存在しない場合のエラーを防ぎましょう。
let parent = document.getElementById("parent");
// 間違い:存在確認なしlet firstChild = parent.children[0];firstChild.style.color = "red"; // エラーの可能性
// 正しい:存在確認if (parent.children.length > 0) { let firstChild = parent.children[0]; firstChild.style.color = "red";}
要素にアクセスする前に、存在するかチェックすると安全です。
まとめ
JavaScriptのchildrenプロパティについて詳しく解説しました。
基本的な特徴:
- HTML要素だけを取得(テキストやコメントは除外)
- HTMLCollectionを返す(「生きている」コレクション)
- 配列のような操作ができる(ただし配列メソッドは使用不可)
主な使用場面:
- ToDoリストの管理
- タブシステムの実装
- 画像ギャラリーの操作
- フォームの要素処理
実践でのポイント:
- HTMLCollectionの特性を理解する
- 配列に変換してメソッドを使用する
- 要素の存在確認を忘れない
- 削除時のインデックス変更に注意
便利なテクニック:
- 条件による子要素の検索・フィルタリング
- 子要素の並び替え
- 動的なコンテンツ管理
childrenプロパティを適切に使うことで、効率的で保守しやすいDOM操作ができるようになります。 基本的な使い方から始めて、徐々に応用的な実装にも挑戦してみてください。
次のステップ:
- より複雑なDOM操作に挑戦
- パフォーマンスを考慮した実装
- 大量要素の効率的な処理
プログラミングは実際に手を動かすことが一番大切です。 今日からこれらのテクニックを使って、インタラクティブなWebページを作ってみませんか?