この記事で学べること
- DOMとは何か、ブラウザとHTMLの関係
- 要素の取得方法(querySelector・getElementById等)
- テキスト・HTMLの書き換え方法
- クラス・属性の操作
- 要素の動的な作成・追加・削除
- イベントリスナーによるユーザー操作への対応
- 実践:タブUIとモーダルの実装
DOMとは何か
DOM(Document Object Model)とは、HTMLドキュメントをプログラムから操作するための仕組みです。ブラウザはHTMLを読み込むと、内部的にツリー構造(DOMツリー)を構築します。JavaScriptはこのDOMツリーを通じて、ページ上の要素を取得・変更・追加・削除できます。
たとえば以下のHTMLがあるとします:
<div id="app">
<h1 class="title">こんにちは</h1>
<p>JavaScriptを学ぼう</p>
</div>
このHTMLはDOMツリーでは次のように表現されます:
- document(ルート)
- └ html
- └ body
- └ div#app
- ├ h1.title(テキスト:「こんにちは」)
- └ p(テキスト:「JavaScriptを学ぼう」)
要素の取得方法
JavaScriptでDOM操作を始めるには、まず対象の要素を取得する必要があります。主な方法を紹介します。
querySelector / querySelectorAll
CSSセレクタと同じ書き方で要素を取得できる、最も汎用的な方法です。
// IDで取得
const app = document.querySelector('#app');
// クラスで取得
const title = document.querySelector('.title');
// タグで取得
const para = document.querySelector('p');
// 複数取得(NodeList)
const buttons = document.querySelectorAll('button');
buttons.forEach(btn => {
console.log(btn.textContent);
});
getElementById / getElementsByClassName
古くからある取得方法ですが、今でも広く使われています。
// IDで1つ取得(高速)
const header = document.getElementById('header');
// クラス名で複数取得(HTMLCollection)
const items = document.getElementsByClassName('item');
// タグ名で複数取得
const links = document.getElementsByTagName('a');
💡 どれを使えばいい?
基本的には
基本的には
querySelector / querySelectorAll を使えばOKです。CSSと同じ記法なので直感的で、柔軟なセレクタが使えます。パフォーマンスが最優先の場合は getElementById の方が若干高速です。
要素の内容を変更する
取得した要素のテキストやHTMLを書き換えることができます。
textContent と innerHTML
const title = document.querySelector('.title');
// テキストだけを変更(安全)
title.textContent = '新しいタイトル';
// HTMLごと変更(XSSに注意)
title.innerHTML = '<strong>太字のタイトル</strong>';
// 現在のテキストを読み取る
console.log(title.textContent); // → 太字のタイトル(タグなし)
console.log(title.innerHTML); // → <strong>太字のタイトル</strong>
⚠️ innerHTML使用時の注意
innerHTML にユーザー入力をそのまま挿入すると、XSS(クロスサイトスクリプティング)攻撃の脆弱性が生じます。ユーザー入力を扱う場合は textContent を使うか、適切なサニタイズ処理を行ってください。
クラスと属性の操作
classList によるクラス操作
要素のCSSクラスを動的に操作できます。スタイルの切り替えによく使われます。
const box = document.querySelector('.box');
// クラスを追加
box.classList.add('active');
// クラスを削除
box.classList.remove('hidden');
// クラスの有無を切り替え
box.classList.toggle('open');
// クラスが存在するか確認
if (box.classList.contains('active')) {
console.log('アクティブです');
}
// 複数のクラスをまとめて追加
box.classList.add('visible', 'animated', 'fade-in');
属性(attribute)の操作
const img = document.querySelector('img');
// 属性を取得
const src = img.getAttribute('src');
// 属性を設定
img.setAttribute('alt', '説明文');
// 属性を削除
img.removeAttribute('data-old');
// data属性はdatasetで便利に操作
const card = document.querySelector('.card');
card.dataset.id = '42'; // data-id="42" をセット
console.log(card.dataset.id); // → 42
スタイルの直接操作
const box = document.querySelector('.box');
// インラインスタイルを設定
box.style.backgroundColor = '#3fb950';
box.style.width = '200px';
box.style.display = 'none'; // 非表示
// 計算済みスタイルを取得(読み取り専用)
const computed = getComputedStyle(box);
console.log(computed.fontSize); // → '16px'
要素の作成・追加・削除
JavaScriptで新しいHTML要素を動的に生成してページに追加することができます。
// 1. 要素を作成
const newItem = document.createElement('li');
newItem.textContent = '新しいアイテム';
newItem.classList.add('item');
// 2. 親要素に追加(末尾)
const list = document.querySelector('ul');
list.appendChild(newItem);
// 3. 特定の位置に挿入(insertBefore)
const firstItem = list.firstElementChild;
list.insertBefore(newItem, firstItem); // 先頭に挿入
// 4. より柔軟なinsertAdjacentHTML
list.insertAdjacentHTML('beforeend', '<li class="item">末尾追加</li>');
list.insertAdjacentHTML('afterbegin', '<li class="item">先頭追加</li>');
// 5. 要素を削除
const oldItem = document.querySelector('.item.old');
oldItem.remove(); // 直接削除(モダンな方法)
テンプレートを使った効率的な生成
// データ配列からリストを一括生成
const fruits = ['りんご', 'バナナ', 'みかん'];
const ul = document.querySelector('#fruit-list');
// DocumentFragmentで一括追加(パフォーマンス向上)
const fragment = document.createDocumentFragment();
fruits.forEach(fruit => {
const li = document.createElement('li');
li.textContent = fruit;
fragment.appendChild(li);
});
ul.appendChild(fragment); // 1回のDOM操作で全要素を追加
イベントリスナー
ユーザーのクリック、入力、マウス操作などに反応させるにはイベントリスナーを使います。
addEventListener の基本
const btn = document.querySelector('#myButton');
// クリックイベント
btn.addEventListener('click', function(event) {
console.log('クリックされました!');
console.log(event.target); // クリックされた要素
});
// アロー関数でも書ける
btn.addEventListener('click', (e) => {
e.preventDefault(); // デフォルト動作を止める
alert('ボタンがクリックされました');
});
// イベントリスナーを削除
const handler = () => console.log('実行');
btn.addEventListener('click', handler);
btn.removeEventListener('click', handler);
主なイベント一覧
| カテゴリ | イベント名 | 説明 |
|---|---|---|
| マウス | click | クリック時 |
| マウス | dblclick | ダブルクリック時 |
| マウス | mouseover / mouseout | マウスが乗った/離れた |
| キーボード | keydown / keyup | キーを押した/離した |
| フォーム | input | 入力値が変わった時 |
| フォーム | submit | フォーム送信時 |
| フォーム | change | 値が変更・確定した時 |
| ページ | DOMContentLoaded | DOM構築完了時 |
| ページ | load | 全リソース読み込み完了 |
| スクロール | scroll | スクロール時 |
イベント委譲(Event Delegation)
動的に追加された要素にもイベントを適用するテクニックです。親要素にイベントを設定し、event.target で実際に操作された子要素を判定します。
// 親要素にイベントを設定
const list = document.querySelector('#list');
list.addEventListener('click', (e) => {
// クリックされたのがliタグかチェック
if (e.target.tagName === 'LI') {
e.target.classList.toggle('completed');
}
// closest()でより柔軟に判定
const item = e.target.closest('.item');
if (item) {
console.log('アイテム:', item.dataset.id);
}
});
実践:タブUIの実装
学んだことを活かして、タブ切り替えUIを実装してみましょう。
<!-- HTML -->
<div class="tab-container">
<div class="tab-buttons">
<button class="tab-btn active" data-tab="tab1">タブ1</button>
<button class="tab-btn" data-tab="tab2">タブ2</button>
<button class="tab-btn" data-tab="tab3">タブ3</button>
</div>
<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>
// JavaScript
const tabButtons = document.querySelectorAll('.tab-btn');
const tabContents = document.querySelectorAll('.tab-content');
tabButtons.forEach(btn => {
btn.addEventListener('click', () => {
// 全ボタンからactiveを外す
tabButtons.forEach(b => b.classList.remove('active'));
// 全コンテンツを非表示
tabContents.forEach(c => c.classList.remove('active'));
// クリックされたボタンをactiveに
btn.classList.add('active');
// 対応するコンテンツを表示
document.getElementById(btn.dataset.tab).classList.add('active');
});
});
実践:シンプルなモーダルの実装
クリックで開閉するモーダルダイアログを作ります。
<!-- HTML -->
<button id="open-modal">モーダルを開く</button>
<div id="modal" class="modal" style="display:none">
<div class="modal-overlay"></div>
<div class="modal-content">
<h2>モーダルタイトル</h2>
<p>モーダルの内容</p>
<button id="close-modal">閉じる</button>
</div>
</div>
// JavaScript
const modal = document.getElementById('modal');
const openBtn = document.getElementById('open-modal');
const closeBtn = document.getElementById('close-modal');
const overlay = modal.querySelector('.modal-overlay');
// モーダルを開く
openBtn.addEventListener('click', () => {
modal.style.display = 'flex';
document.body.style.overflow = 'hidden'; // 背景スクロール禁止
});
// モーダルを閉じる関数
function closeModal() {
modal.style.display = 'none';
document.body.style.overflow = '';
}
closeBtn.addEventListener('click', closeModal);
// オーバーレイクリックでも閉じる
overlay.addEventListener('click', closeModal);
// Escキーでも閉じる
document.addEventListener('keydown', (e) => {
if (e.key === 'Escape') closeModal();
});
まとめ
今回はJavaScript DOM操作の基礎を学びました。重要なポイントをまとめます:
- 要素の取得:
querySelector/querySelectorAllがおすすめ - 内容の変更:テキストは
textContent、HTMLはinnerHTML(XSSに注意) - クラス操作:
classList.add/remove/toggleでスタイル切り替え - 要素の作成:
createElement→appendChildの流れ - イベント:
addEventListenerでユーザー操作に反応 - パフォーマンス:
DocumentFragmentや イベント委譲で効率化
DOM操作はフロントエンド開発の基本中の基本です。Reactなどのフレームワークを使う場合でも、この知識は必ず役に立ちます。ぜひ実際にコードを書いて練習してみてください!