DOMとは何か?
DOM(ドム)とは、ブラウザがHTMLやXMLなどの静的な文章をプログラムで動的に操作するための仕組みです。
HTMLやXMLを読みこんで理解し操作するために、各要素をモノ(オブジェクト)として扱います。それらをツリー構造として表現することで、JavaScriptなどの言語がDOMを通してページの要素の読込み・追加・削除などの操作ができるようになります。
簡単に言うと、HTMLだけのWEBページの中のテキストや値などは動的に変更できませんが、その動かない要素をJavaScriptで動かせるのはDOMがあるからです。
この説明だけ聞いてもよくわからないかと思うので、以下で由来(起源)や実例を交えて解説します。
DOMは、Document Object Modelの略です。
Document Object Modelとは、ドキュメント(紙などの動かない文章)を、モノとして扱うモデルという意味です。
DOMの由来(起源)
DOMを理解するためには、なぜDOMが生まれたのか?を理解するとわかりやすくなります。
1990年代などWEBがまだ生まれたばかりの頃は、ブラウザは静的なHTMLを読み込んで表示することしかできませんでした。
WEBがより一般化していく中で、JavaScriptなどを使って見た目を動的に操作する技術が使われるようになりました。
しかし、動かし方はブラウザごとに別々だったため、あるブラウザでは動くが、他のブラウザでは動かないということがありました。
この問題を解決するために共通する標準的な基準としてW3Cという組織が作ったのが「DOM」です。
つまり、DOMはブラウザ上で静的なコンテンツを動かすために、ブラウザ間の非互換性の問題を解決し、標準化するために生み出された技術(仕組み)です。
実例で見るDOM
例えば、静的なコードであるHTMLは以下のように記述されます。
<!doctype html>
<html>
<head>...</head>
<body>
<h1 id="title">やることリスト</h1>
<ul id="todo-list">
<li>買い物</li>
<li>メール確認</li>
</ul>
</body>
</html>
これをDOMにすると、以下のような「ツリー構造」になります。
Document
└─ html
├─ head
└─ body
├─ h1#title
└─ ul#todo-list
├─ li("買い物")
└─ li("メール確認")
DOMで表現することで、JavaScriptなどで「どこのどの要素を取得しどのように変える」といった操作をすることが可能になります。
ツリー構造と階層構造は違うの?
「ツリー構造」という言葉は私たち日本人にとってあまり馴染みがありません。なんとなく木のようになっているのかな?と想像ができるぐらいです。
どちらかといえば「階層構造」と言われる方が会社の組織図などをイメージしやすくわかりやすいかと思います。
本質的には「ツリー構造 = 階層構造」と捉えていただいて問題ありません。
ただし、DOMでは各要素をツリー(木)になぞらえた呼び方をするので、やはり呼び名としては「ツリー構造」が適切です。
木は土の中の根っこ(根は英語で「ルート(root)」)からぐんぐんと伸び、各枝に分岐(ブランチ(branch))し、葉っぱ(リーフ(leaf))へと伸びていきます。
DOMの各要素もこの構造を模倣してネーミングがされています。

DOMの各要素の名前
DOMの各要素には名前がついています。Gitなどコンピューター業界で広く使われているため、これらの名前を聞いたことがある人も多いのではないのでしょうか?
- ツリー(tree): 全体的な階層構造
- ルート(root): ツリーの一番上の要素
- ブランチ(branch): 枝分かれしている部分
- ノード(node): ツリーを構成する個々の要素
- リーフ(leaf): 枝の末端の要素
↓ これをDOMの各要素で表すと以下のようになります。
- ツリー(tree): 全体的な階層構造
→ Documentタグ - ルート(root): ツリーの一番上の要素
→ htmlタグ - ブランチ(branch): 枝分かれしている部分
→ 子ノードを持つ親ノード(htmlやbody, divなど中に要素を持つタグ)
- ノード(node): ツリーを構成する個々の要素
→ ツリーを構成する全ての要素(Documentやhtmlも含みます) - リーフ(leaf): 枝の末端の要素
→ 子ノードを持たないノード(テキストやbrタグなど)
先ほどのHTMLをDOMで表現したもので解説すると以下のようになります。
Document ← ツリー
└─ html ← ルート
├─ head ← リーフ
└─ body ← ブランチ
├─ h1#title ← リーフ
└─ ul#todo-list ← ブランチ
├─ li("買い物") ← リーフ
└─ li("メール確認") ← リーフ
そして、上記の各要素の全てが「ノード」です。
ノードの呼び名(ルートノード、親ノード、子ノード、兄弟ノード、リーフノード)
各要素がどこにあるかでノードの呼び名が変わります。
例えばノードには以下のような呼び名があります。
- ルートノード (Root Node)
ツリーの一番上にあるノード。htmlをルートと呼ぶのが一般的(厳密にはDocumentがルートノード) - 親ノード (Parent Node)
子ノードを一つ以上持つノード。 - 子ノード (Child Node)
親ノードに直接含まれるノード。 - 兄弟ノード (Sibling Node)
同じ親ノードを持つノード同士のこと。 - リーフノード (Leaf Node)
ツリーの末端に位置し、子ノードを持たないノード。
以下でそれぞれの実例を用いて解説します。
ルートノード (Root Node)
ツリーの一番上にあるノードのことです。
厳密にはDocumentがルートノードですが、htmlをルートと呼ぶのが一般的です。
ルートノードはDOMツリー全体の基点となります。documentElementプロパティで取得しますが、その際取得できるノードはhtmlタグです。
// htmlノードを取得
const rootNode = document.documentElement;
console.log(rootNode.nodeName); // "HTML"※document.documentElementはhtmlタグを取得する特別なプロパティです。
親ノード (Parent Node) と子ノード (Child Node)
親ノードは子ノードを一つ以上持つノード。子ノードは親ノードに直接含まれるノードです。
<div id="parent">
<p id="child">これは子ノードです。</p>
</div>const childNode = document.getElementById('child');
// 親ノードにアクセス
const parentNode = childNode.parentNode;
console.log(parentNode.id); // "parent"
// 子ノードにアクセス
const parentElement = document.getElementById('parent');
console.log(parentElement.firstChild.id); // "child"parentNodeプロパティは、常に親ノードを返します。
firstChildやlastChildなどのプロパティで、最初や最後の子ノードにアクセスできます。
兄弟ノード (Sibling Node)
同じ親ノードを持つノード同士を指します。
<div>
<p id="first">1番目の兄弟ノード</p>
<p id="second">2番目の兄弟ノード</p>
</div>const firstNode = document.getElementById('first');
// 次の兄弟ノードにアクセス
const nextSiblingNode = firstNode.nextSibling;
console.log(nextSiblingNode.id); // "second"
// 前の兄弟ノードにアクセス
const secondNode = document.getElementById('second');
const previousSiblingNode = secondNode.previousSibling;
console.log(previousSiblingNode.id); // "first"nextSiblingやpreviousSiblingは、次の・前の兄弟ノードにアクセスするプロパティです。
リーフノード (Leaf Node)
ツリーの末端に位置し、子ノードを持たないノードのことです。
<p>これはテキストです。</p>const pElement = document.querySelector('p');
// 子ノードがあるかどうかを確認
console.log(pElement.hasChildNodes()); // true (テキストノードを子として持つため)
// p要素の子ノードはテキストノード
const textNode = pElement.firstChild;
// テキストノードは子を持たないので、falseを返す
console.log(textNode.hasChildNodes()); // falsehasChildNodes()メソッドで、子ノードの有無を確認できます。
その他のノード
ノードは種類によっても細かく分類されます。
- 要素ノード (Element Node)
<h1>、<p>、<div>など、HTMLタグのことです。最も一般的に操作するノードです。 - テキストノード (Text Node)
要素タグの中にある文字列(例:<h1>見出し</h1>の「見出し」の部分)のことです。 - 属性ノード (Attribute Node)
タグの属性(例:<div **id="main"**>のid="main")のことです。 - コメントノード (Comment Node)
HTMLのコメントのことです。
これらのノードの種類は、nodeTypeプロパティで判別できます。
<div id="main">
<p>こんにちは</p>
</div>const divElement = document.getElementById('main');
const children = divElement.childNodes;
console.log(children[0].nodeType); // 8 (コメントノード)
console.log(children[1].nodeType); // 3 (テキストノード)
console.log(children[2].nodeType); // 1 (要素ノード)DOMの基本操作の例(取得・追加・削除・イベント)
DOMがあることで実行できる「取得・追加・削除・イベント」などの動的な基本操作を実例で解説します。
ここから先は少し専門的なので、興味のある方のみご参考ください。
ToDoリスト
例えば以下のようなHTMLとJavaScriptがあるとします。
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
<title>DOM 入門デモ</title>
<style>
body { font-family: sans-serif; padding: 20px; }
.done { text-decoration: line-through; color: gray; }
button.delete { margin-left: 8px; }
</style>
</head>
<body>
<h1 id="title">ToDoリスト</h1>
<form id="todo-form">
<input id="new-todo" placeholder="新しいタスクを入力" />
<button type="submit">追加</button>
</form>
<ul id="todo-list"></ul>
<script>
// DOM が読み込まれてから処理する(安全)
document.addEventListener('DOMContentLoaded', () => {
const form = document.getElementById('todo-form'); // 要素を取得
const input = document.getElementById('new-todo');
const ul = document.getElementById('todo-list');
// フォーム送信で新しい li を作って追加する
form.addEventListener('submit', (e) => {
e.preventDefault();
const text = input.value.trim();
if (!text) return;
const li = document.createElement('li'); // 要素を作る
li.textContent = text; // テキストを入れる(安全)
const del = document.createElement('button');
del.textContent = '削除';
del.className = 'delete';
li.appendChild(del);
ul.appendChild(li); // DOM に追加
input.value = '';
});
// イベントの委任(event delegation):ul にまとめてクリックを監視
ul.addEventListener('click', (e) => {
if (e.target.classList.contains('delete')) {
// 「削除」ボタンが押されたら、その親 li を消す
e.target.parentElement.remove();
} else if (e.target.tagName === 'LI') {
// li 自体がクリックされたら完了(クラス toggle)
e.target.classList.toggle('done');
}
});
});
</script>
</body>
</html>
このコードを使うと、超簡単なToDoリストを作成し、追加や削除処理をすることができます。
ToDoリスト
DOM操作でよく使うメソッドとプロパティ
上記のコードでは、DOM操作でよく使うメソッドやプロパティを使用しています。
■要素の取得
・document.getElementById(‘id’) : 指定したidと一致するノードを取得
・document.querySelector(‘.class’): 最初に一致したノードを取得
・document.querySelectorAll(‘li’): 一致する全要素を NodeList で取得
■要素作成 / 挿入 / 削除
・document.createElement(‘div’):指定したタグを作成
・parent.appendChild(node):親ノード(parent)に指定した子ノードを追加
・parent.insertBefore(node, ref):親ノードの中の指定したノード(ref)の前に指定したノードを追
・node.remove():ノードを親から取り除く
■内容の操作
・el.textContent:指定した要素のテキストのみを取得。イコールでつなぐと指定したテキストを代入(テキストのみ、安全)
・el.innerHTML:指定した要素を全て取得。イコールで置き換える。(HTML を解釈;外部入力は危険)
■属性の操作
・el.getAttribute(‘href’):指定した属性が付いたノードを取得する。
・el.setAttribute(‘data-id’,’123′):指定したノードに指定した属性名と値をセットする(例: data-id=”123″)
■クラスの操作
・el.classList.add(‘クラス名’):指定したクラスを追加
・el.classList.remove(‘クラス名’):指定したクラスを削除
・el.classList.toggle(‘クラス名’):指定したクラスがあれば削除、なければ追加
■ノードの違い
・el.childNodes :子の全て。テキストノードも含む(空白なども)
・el.children :子要素のみ。要素ノードのみ
■イベント
・el.addEventListener(‘click’, handler):クリックしたときに実行するイベントを設定
まとめ
DOM (Document Object Model) は、HTML文書をJavaScriptなどのプログラムで動的に変化させるための仕組みです。
HTMLの各要素(タグ)を「オブジェクト(モノ)」として扱うことができ、取得、追加、変更、削除などができます。


