WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

JavaScriptでDOM操作をマスターする入門ガイド|要素の取得・変更・イベント処理を基礎から実践まで解説

目次

この記事の結論

DOM(Document Object Model)とは、HTMLの構造をJavaScriptから操作するためのインターフェースで、ブラウザがHTMLを内部でツリー状のオブジェクトに変換したものです。DOM操作は「要素を取得する→内容を変更する→スタイルやクラスを操作する→イベントを処理する」という流れが基本で、getElementByIdやquerySelectorで要素を取得し、textContentやclassList、addEventListenerを使ってページを動的に書き換えます。この感覚をつかめば、ボタン操作での表示切り替えやフォームバリデーションなど、あらゆるインタラクティブなUIを実装できます。

生徒

JavaScriptってHTMLをどうやって変えるんですか?CSSとの違いもよくわからなくて、DOM操作というワードが出てくるたびに止まってしまいます…。

ペン博士

DOM操作はJavaScriptの核心です!この記事では「要素の取得→内容の変更→クラス操作→イベント処理」という4ステップで、実際に動くコードを使いながら完全に理解できるよう解説しますよ。

「JavaScriptは書けるけどDOM操作になると途端に手が止まる」——Web制作を学びはじめた方からよく聞く悩みです。この記事では、DOMとは何かという基礎概念から、要素の取得・テキスト・スタイル・クラスの変更、そしてクリックやフォーム入力などのイベント処理まで、実際にブラウザで動くコード例を軸にステップごとに解説します。読み終えた後には「JavaScriptでページを動かす」という感覚が具体的につかめるはずです。HTML・CSSの基礎は学んだもののJavaScriptの実践的な使い方が曖昧な方に特に役立つ内容です。


DOM(ドキュメントオブジェクトモデル)とは何か

DOM(Document Object Model)とは、HTMLの構造をJavaScriptから操作するためのインターフェース(仕組み)です。ブラウザはHTMLファイルを読み込むと、内部で「ツリー状のオブジェクト」に変換します。この木構造のデータがDOMです。

たとえば以下のようなHTMLがあるとします。

<!DOCTYPE html>
<html>
  <body>
    <h1 id="title">はじめてのDOM</h1>
    <p class="description">JavaScriptで操作できます。</p>
  </body>
</html>

ブラウザはこれをツリーとして内部管理しており、JavaScriptはdocumentオブジェクトを通じてどの要素にもアクセスできます。CSSが「見た目を静的に定義する」のに対し、JavaScriptのDOM操作は「ページを動的に書き換える」ためのものです。ボタンを押したら文字が変わる・スクロールで要素が現れる・フォームのバリデーションをする、これらすべてDOMを介して実現されています。

DOMツリーの基本構造

DOMツリーは以下のような階層構造を持ちます。

  • document:ページ全体の入口となるオブジェクト。すべての操作はここから始まる
  • 要素ノード(Element Node):<h1><p>などのHTMLタグに対応
  • テキストノード(Text Node):タグの中に書かれたテキスト内容
  • 属性ノード(Attribute Node):idclassなどの属性情報

JavaScriptのDOM操作では、まず「どの要素を操作するか」を取得し、次に「何を変えるか」を指定するという2段階の流れが基本になります。この感覚さえつかめれば、あとは応用するだけです。


ステップ1:要素を取得する4つの方法

DOM操作の第一歩は「操作したい要素を取得すること」です。JavaScriptにはいくつかの取得メソッドが用意されています。現場でよく使われる4つを押さえておきましょう。

① getElementById(IDで1つ取得)

const title = document.getElementById('title');
console.log(title); // <h1 id="title">はじめてのDOM</h1>

ページ内に1つしか存在しないIDを持つ要素を取得するときに使います。最もシンプルで高速なメソッドです。

② querySelector(CSSセレクターで1つ取得)

const desc = document.querySelector('.description');
const firstLi = document.querySelector('ul li:first-child');

querySelector はCSSセレクターをそのまま使えるため、最も柔軟性が高く現場でも頻繁に使われます。クラス・タグ・属性・擬似クラスなど、CSSで書けるセレクターはすべて指定可能です。

③ querySelectorAll(CSSセレクターで複数取得)

const items = document.querySelectorAll('.list-item');
items.forEach(item => {
  console.log(item.textContent);
});

複数の要素をまとめて取得したい場合に使います。返り値はNodeListという配列に似たオブジェクトで、forEachでループ処理できます。

④ getElementsByClassName・getElementsByTagName

const cards = document.getElementsByClassName('card');
const paragraphs = document.getElementsByTagName('p');

クラス名やタグ名で複数要素を取得します。返り値はHTMLCollectionという「生きたコレクション」で、DOMが変化すると自動的に更新される点が特徴です。ただし現代のコードではquerySelectorAllが使われることが多いです。

メソッド取得対象返り値現場での頻度
getElementByIdID(1件)Element高い
querySelectorCSSセレクター(1件目)Element最も高い
querySelectorAllCSSセレクター(全件)NodeList最も高い
getElementsByClassNameクラス名(全件)HTMLCollection中程度
getElementsByTagNameタグ名(全件)HTMLCollection低い

ステップ2:要素の内容・テキスト・HTMLを変更する

要素を取得したら、次は「何を変えるか」です。よく使うプロパティを3つ覚えておけば、ほとんどの場面に対応できます。

textContent:テキストのみ変更

const title = document.getElementById('title');
title.textContent = '変更後のタイトル';

textContentはHTMLタグを含まない純粋なテキストを読み書きします。XSS(クロスサイトスクリプティング)対策の観点から、ユーザー入力をそのまま表示する場合は textContent を使うのが安全です。

innerHTML:HTMLごと変更

const container = document.querySelector('.container');
container.innerHTML = '<strong>太字のテキスト</strong>が追加されました';

innerHTMLはHTMLタグも含めて中身を書き換えます。動的にリストやカードを生成するときに便利ですが、ユーザー入力をそのまま渡すとXSSのリスクがあるため注意が必要です。

value:入力フォームの値を読み書き

const input = document.querySelector('#username');
const value = input.value; // 入力値を取得
input.value = 'デフォルト値'; // 値を設定

inputtextareaselectなどのフォーム要素の値を操作するにはvalueプロパティを使います。フォームバリデーションや入力補助UIを作るときに必須の知識です。


ステップ3:スタイルとクラスをJavaScriptで操作する

「ボタンを押したら色が変わる」「エラー時に赤枠が出る」——こうしたインタラクションは、スタイルやクラスをJavaScriptで動的に変更することで実現できます。

style プロパティで直接スタイルを変更

const box = document.querySelector('.box');
box.style.backgroundColor = 'tomato';
box.style.fontSize = '20px';
box.style.display = 'none'; // 非表示にする

CSSプロパティ名はキャメルケース(camelCase)で指定します(例:background-colorbackgroundColor)。インラインスタイルとして直接適用されるため、CSSの詳細度が高くなる点に注意しましょう。細かい動的変更には向いていますが、スタイルの管理はCSSクラスで行い、JavaScriptはクラスの付け外しに徹する設計が保守性の観点から推奨されます。

classList でクラスを操作する(推奨)

const btn = document.querySelector('.toggle-btn');
const menu = document.querySelector('.nav-menu');

// クラスを追加
menu.classList.add('is-open');

// クラスを削除
menu.classList.remove('is-open');

// クラスのあり/なしを切り替え(トグル)
menu.classList.toggle('is-open');

// クラスが存在するか確認
if (menu.classList.contains('is-open')) {
  console.log('メニューは開いています');
}

classListaddremovetogglecontainsの4メソッドは実務で非常に頻繁に使います。たとえばハンバーガーメニューの開閉・モーダルの表示切り替え・タブの選択状態など、ほぼすべてのインタラクションUIでこのパターンが登場します。

属性(attribute)を操作する

const link = document.querySelector('a');

// 属性を取得
const href = link.getAttribute('href');

// 属性を設定
link.setAttribute('target', '_blank');

// 属性を削除
link.removeAttribute('target');

getAttributesetAttributeremoveAttributeで任意の属性を操作できます。hrefsrcaltdisabledなど、HTMLのあらゆる属性に対応しています。


ステップ4:イベント処理でページをインタラクティブにする

DOM操作の真価を発揮するのが「イベント処理」です。ユーザーの操作(クリック・入力・スクロール・マウスオーバーなど)をトリガーにしてJavaScriptを実行する仕組みで、addEventListener メソッドを使うのが現代のスタンダードな書き方です。

addEventListener の基本構文

const button = document.querySelector('#my-button');

button.addEventListener('click', function(event) {
  console.log('ボタンがクリックされました');
  console.log(event); // イベントオブジェクト
});

第1引数にイベント名(文字列)、第2引数にコールバック関数(イベント発生時に実行される処理)を渡します。コールバック関数にはイベントオブジェクト(eventまたはe)が自動的に渡され、クリック位置・対象要素・デフォルト動作のキャンセルなどを操作できます。

よく使うイベント種類一覧

イベント名発生タイミング主な用途
click要素をクリックしたときボタン・リンクの処理
input入力値が変わるたびにリアルタイムバリデーション
change入力が確定したときセレクト・チェックボックス
submitフォーム送信時送信前のバリデーション
mouseoverマウスが要素に乗ったときホバーエフェクト
scrollスクロール中スクロール連動アニメーション
DOMContentLoadedHTML解析完了時初期化処理

実践例:クリックでテキストを切り替えるトグルボタン

const toggleBtn = document.querySelector('#toggle-btn');
const message = document.querySelector('#message');

toggleBtn.addEventListener('click', () => {
  if (message.classList.contains('is-hidden')) {
    message.classList.remove('is-hidden');
    toggleBtn.textContent = '隠す';
  } else {
    message.classList.add('is-hidden');
    toggleBtn.textContent = '表示する';
  }
});

これに対応するHTMLとCSSは次のとおりです。

<!-- HTML -->
<button id="toggle-btn">表示する</button>
<p id="message" class="is-hidden">こんにちは!</p>

<!-- CSS -->
.is-hidden {
  display: none;
}

CSSに「状態を表すクラス(.is-open・.is-hidden・.is-activeなど)」を定義しておき、JavaScriptはそのクラスの付け外しだけを担当する設計は、コードが分離されてメンテナンスしやすくなります。現場のプロも意識している設計パターンです。

実践例:フォームのリアルタイムバリデーション

const emailInput = document.querySelector('#email');
const errorMsg = document.querySelector('#email-error');

emailInput.addEventListener('input', (e) => {
  const value = e.target.value;
  const isValid = value.includes('@');

  if (isValid) {
    errorMsg.textContent = '';
    emailInput.classList.remove('is-error');
  } else {
    errorMsg.textContent = '正しいメールアドレスを入力してください';
    emailInput.classList.add('is-error');
  }
});

e.targetはイベントが発生した要素自身を参照します。フォームのバリデーションでは入力要素のvalueを取得して条件分岐する、というパターンを覚えておくと非常に役立ちます。


ステップ5:要素の追加・削除で動的なUIを作る

「ボタンを押したらリストにアイテムが増える」「削除ボタンで行が消える」——こうした動的なUI変更も、DOM操作の重要な応用です。

createElement と appendChild で要素を追加する

const list = document.querySelector('#todo-list');
const addBtn = document.querySelector('#add-btn');
const inputField = document.querySelector('#todo-input');

addBtn.addEventListener('click', () => {
  const text = inputField.value.trim();
  if (text === '') return; // 空なら処理しない

  // 新しいli要素を生成
  const li = document.createElement('li');
  li.textContent = text;

  // 削除ボタンを追加
  const deleteBtn = document.createElement('button');
  deleteBtn.textContent = '削除';
  deleteBtn.addEventListener('click', () => {
    li.remove(); // li要素ごと削除
  });

  li.appendChild(deleteBtn);
  list.appendChild(li);

  inputField.value = ''; // 入力欄をリセット
});

このコードだけでシンプルなTodoリストが完成します。createElementで要素を生成し、appendChildでDOMに追加、removeで削除という流れは、あらゆる動的UIの基礎になります。

insertAdjacentHTML で素早く挿入する

const container = document.querySelector('.card-container');

container.insertAdjacentHTML('beforeend', `
  <div class="card">
    <h3>新しいカード</h3>
    <p>動的に追加されました</p>
  </div>
`);

insertAdjacentHTMLはHTML文字列を指定の位置に挿入します。テンプレートリテラル(バッククォート)と組み合わせると、複数要素を含むHTMLブロックを一気に追加できるため、カード型UIやリスト追加処理で特に便利です。挿入位置はbeforebeginafterbeginbeforeendafterendの4種類から選べます。


よくある失敗とその対策

DOM操作を学び始めた段階でつまずきやすいポイントをまとめます。エラーが起きたときにまずここを確認してください。

① 「null」エラー:要素が取得できていない

// NG:HTMLの読み込み前にスクリプトが実行されている
const btn = document.querySelector('#btn'); // null になる

// OK1:scriptタグをbodyの末尾に置く
// OK2:DOMContentLoadedを使う
document.addEventListener('DOMContentLoaded', () => {
  const btn = document.querySelector('#btn');
  // ここで操作する
});

// OK3:scriptタグにdefer属性をつける
// <script src="main.js" defer></script>

Cannot read properties of nullというエラーは、HTMLがまだ読み込まれていない段階でJavaScriptが実行され、要素を取得できずにnullが返っているのが原因です。上のいずれかの方法で「HTMLが読み込まれてからスクリプトを動かす」ようにすれば解決します。まずは<script></body>直前に置くか、defer属性を付ける方法が手軽でおすすめです。

② innerHTMLの使いすぎでXSSの危険が生まれる

ユーザーが入力した値をinnerHTMLにそのまま入れると、悪意あるスクリプトが実行される「XSS(クロスサイトスクリプティング)」の原因になります。文字列を表示したいだけならtextContentを使い、HTMLタグとして解釈させないのが安全です。

const input = '<img src=x onerror=alert(1)>';

// NG:入力値をそのままHTMLとして挿入(スクリプトが動く)
box.innerHTML = input;

// OK:ただの文字列として安全に表示する
box.textContent = input;

③ getElementsByClassNameの結果をそのままforEachしてエラー

getElementsByClassNamegetElementsByTagNameが返すのは配列ではなく「HTMLCollection」で、forEachが使えません。querySelectorAllが返すNodeListはforEach可能ですが、確実に配列として扱いたいときはArray.from()で変換します。

// NG:HTMLCollectionにはforEachがない → エラー
document.getElementsByClassName('item').forEach(el => { ... });

// OK1:querySelectorAll(NodeList)ならforEachできる
document.querySelectorAll('.item').forEach(el => { ... });

// OK2:Array.fromで配列に変換してから回す
Array.from(document.getElementsByClassName('item')).forEach(el => { ... });

まとめ:DOM操作は「取得→変更→イベント」の3つが基本

JavaScriptのDOM操作は、①要素を取得し、②内容やスタイルを変更し、③イベントで動きをつけるという流れが基本です。この記事で扱った要素の取得方法・テキストやクラスの変更・イベント処理・要素の追加削除を押さえれば、フォームの入力チェックやボタンでの表示切り替えなど、実用的なUIはひと通り作れるようになります。

最初はうまく動かないことも多いですが、nullエラーやXSSといったつまずきポイントはこの記事の「よくある失敗」を見返せば対処できます。まずは小さなサンプルを自分の手で書いて動かし、少しずつ組み合わせていきましょう。


よくある質問(FAQ)

Q1. DOMで要素を取得するにはどのメソッドを使いますか?

A. getElementById(IDで1件)、querySelector(CSSセレクターで1件目)、querySelectorAll(CSSセレクターで全件)、getElementsByClassName・getElementsByTagName(クラス名・タグ名で全件)があります。現場ではCSSセレクターをそのまま使えて柔軟性の高いquerySelectorとquerySelectorAllが最もよく使われます。

Q2. textContentとinnerHTMLの違いは何ですか?

A. textContentはHTMLタグを含まない純粋なテキストを読み書きし、innerHTMLはHTMLタグごと中身を書き換えます。innerHTMLはユーザー入力をそのまま渡すとXSS(クロスサイトスクリプティング)のリスクがあるため、ユーザー入力を表示する場合はtextContentを使うのが安全です。

Q3. スタイルはstyleプロパティとclassListのどちらで変更すべきですか?

A. 保守性の観点からは、スタイルの管理はCSSクラスで行い、JavaScriptはclassListのadd・remove・toggle・containsでクラスの付け外しに徹する設計が推奨されます。styleプロパティによる直接変更は詳細度が高くなるため、細かい動的変更に限って使うのが望ましいです。

Q4. 「Cannot read properties of null」というエラーはなぜ起きますか?

A. HTMLがまだ読み込まれていない段階でJavaScriptが実行され、対象の要素が取得できていないことが主な原因です。DOMContentLoadedイベントを使って、HTMLの解析が完了してから処理を実行するようにすると防げます。

Q5. イベント処理はどう書くのが現代のスタンダードですか?

A. addEventListenerメソッドを使うのが現代の標準です。第1引数にイベント名、第2引数にコールバック関数を渡します。clickやinput、submit、DOMContentLoadedなど用途に応じたイベントを指定でき、コールバックにはイベントオブジェクトが自動的に渡されます。


関連記事


参考リンク(公式・一次情報)


あわせて読みたい:HTMLタグ一覧|基本タグの使い方まとめ

AIスキルで、未来の自分をアップデート!

今なら完全無料でAIを学べる!WithAI

今なら完全無料でAIを学べる!

  • 動画や実践で楽しく学べる:初心者でも安心のカリキュラム
  • スマホ・PCどちらでもOK:好きな時間に学習できる
  • 料金は一切ナシ0円でAIスキルが身につく

目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。

会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!

この記事を書いた人

WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次