DOM操作入門:JavaScriptでWebページの中身を書き換える基本

13 min 111 views
JS

「ボタンを押したら文字が変わる」「タブをクリックしたら別の内容が表示される」「エラーメッセージがその場で出る」。
こういう“動くWebページ”は、すべてJavaScriptが画面の中身(HTML)を書き換えて実現しています。

この「画面の中身にアクセスして、書き換える」ための仕組みが DOM(Document Object Model) です。

この記事では、初心者の方でもわかるように

  • DOMってそもそも何者?
  • ページの中から特定の要素をどうやって取ってくるの?
  • テキストや属性をどうやって書き換えるの?
  • 新しいHTMLをどうやって追加・削除するの?

という基本を順番に解説します。
1つずつ読めば、jQueryなしでも自分で画面をいじれるようになります。

が、記事が少し長くなりすぎました。ちょっとずつ読んでください。

目次

1. DOMってなに?ざっくりイメージでOK

ブラウザは、HTMLをそのまま文字列として持っているわけではありません。
HTMLを読み込んだとき、ブラウザの中ではそれが「ツリー構造のオブジェクト」として整理されます。

このツリー構造こそが DOM(Document Object Model) です。

  • document … ページ全体を表す一番上の親
  • その下に <html> 要素
  • <html> の下に <head><body>
  • <body> の下に <div>, <p>, <ul>… とどんどん子どもがつながっていく

木(ツリー)で考えるとわかりやすいです。
親がいて、子どもがいて、兄弟がいる。DOMは「HTMLをオブジェクトとして扱いやすくした家系図」だと思ってください。

DOMをさわる=この家系図の中から特定の要素を見つけて、読んだり、書き換えたり、増やしたり、消したりすることです。

2. document って何者?

JavaScript から DOM にアクセスするときの入口が document です。

// ページ全体にアクセスするための入り口オブジェクト
console.log(document);

document はブラウザが自動で用意してくれるオブジェクトなので、自分で作る必要はありません。
ここから「特定の要素を探す」「中身を変える」などをやっていきます。

3. 要素を「取得する」基本パターン

まずは「ページの中から目的のパーツをひっぱってくる」ことができないと何も始まりません。
ここがDOM操作の第1歩です。

 3-1. getElementById:idで1つだけ取る

HTML側で id が付いている要素は、JavaScriptからピンポイントで取得できます。

HTML例:

<div id="mainArea">
  <p>ようこそ!</p>
</div>

JavaScript例:

// id="mainArea" の要素を取得
const mainBox = document.getElementById("mainArea");

// コンソールに表示して中身を確認
console.log(mainBox);

id は基本的に1ページ内でユニーク(かぶらない)であるべきなので、戻ってくるのは「1個の要素」です。
もし同じidを複数つけていたら、最初に見つかったものだけ返ってきます。

これは初心者がハマりがちなポイントです。

 3-2. getElementsByTagName:タグ名でまとめて取る

特定のタグ(例:<li> だけ)をぜんぶ取りたいときはこれ。

HTML例:

<ul id="menuList">
  <li>ホーム</li>
  <li>ブログ</li>
  <li>お問い合わせ</li>
</ul>

JavaScript例:

// ページ全体から <li> を全部集める
const allItems = document.getElementsByTagName("li");

// 何件取れたか
console.log(`liは全部で ${allItems.length} 個あります`);

// 1つずつ中身を表示
let index = 0;
for (const item of allItems) {
  console.log(`li[${index}] のテキストは「${item.textContent}」です`);
  index++;
}

ここで返ってくるのは HTMLCollection という”配列っぽい集合”です。length で数えられるし、for-ofで回せます。

さらに応用として「特定エリアの中だけで探す」こともできます。

たとえば、上の <ul id="menuList"> の中だけを検索する場合:

const menu = document.getElementById("menuList");
const menuItems = menu.getElementsByTagName("li");

console.log(`menuListの中のliは ${menuItems.length} 個です`);

ポイント:

  • document.getElementsByTagName(...) → ページ全体が対象
  • ある要素.getElementsByTagName(...) → その要素の「内側だけ」が対象

これ、DOMを扱ううえですごく大事です。「どこから探すか」で結果が変わります。

 3-3. getElementsByClassName:クラス名でまとめて取る

class="highlight" のようなクラスは、複数の要素に同じクラスを付けられます。
だから戻り値も複数セット(HTMLCollection)です。

HTML例:

<div class="article highlight">
  <h2 class="sectionTitle">DOMって何?</h2>
  <p>説明テキスト...</p>
</div>

<div class="article">
  <h2 class="sectionTitle highlight">要素を探す方法</h2>
  <p>説明テキスト...</p>
</div>

JavaScript例:

// "highlight" クラスがついている要素をぜんぶ取得
const markedList = document.getElementsByClassName("highlight");

console.log(`highlight付きの要素は ${markedList.length} 個あります`);

for (const box of markedList) {
  console.log(box);
}

// 複数クラスで絞り込みもできる(スペース区切り)
const specialList = document.getElementsByClassName("article highlight");
console.log(
  `article かつ highlight の要素は ${specialList.length} 個あります`
);

複数クラスでの検索は "classA classB" のようにスペースでつなげます。
書かれている順番は関係ありません(class="article highlight" でも class="highlight article" でもヒットします)。

 3-4. getElementsByName:name 属性で取得する

主にフォーム要素(<input>など)で使います。

戻り値は NodeList という”これも配列っぽいもの”です。

HTML例:

<form>
  <label>
    <input type="checkbox" name="osGroup" value="win"> Windows
  </label>
  <label>
    <input type="checkbox" name="osGroup" value="mac"> macOS
  </label>
  <label>
    <input type="checkbox" name="osGroup" value="linux"> Linux
  </label>
</form>

JavaScript例:

// name="osGroup" がついた要素をまとめて取得
const osOptions = document.getElementsByName("osGroup");

console.log(`OSの選択肢は ${osOptions.length} 個あります`);

for (const opt of osOptions) {
  console.log(opt); // <input ...> 要素が順番に出てくる
}

NodeListfor...of で回せますし、length で数えられます。

 3-5. いま主流はこれ:querySelector / querySelectorAll

正直、現場だとまずこれを使います。

  • querySelector(セレクタ)
    → CSSセレクタで指定した「最初の1個だけ」を返す
  • querySelectorAll(セレクタ)
    → CSSセレクタで指定した「すべて」を返す(NodeList)

セレクタは普段CSSで書くやつと同じです。
#id名, .class名, input[type="text"], div > p みたいな指定ができます。

HTML例(フォーム):

<form id="userForm">
  <div class="formRow">
    <label for="userName">お名前</label>
    <input type="text" id="userName" name="userName" />
  </div>

  <div class="formRow">
    <label for="userCity">住所</label>
    <input type="text" id="userCity" name="userCity" />
  </div>

  <div class="formRow">
    <input type="checkbox" id="optWin" class="osCheck" name="osType" />
    <label for="optWin">Windows</label>
  </div>

  <div class="formRow">
    <input type="checkbox" id="optMac" class="osCheck" name="osType" />
    <label for="optMac">macOS</label>
  </div>
</form>

JavaScript例(1つだけ欲しいとき):

// 最初の <input> 要素を1つだけ取る
const firstInput = document.querySelector("input");
console.log(firstInput);

// id指定(#〜)
const macCheckbox = document.querySelector("#optMac");
console.log(macCheckbox);

// class指定(.〜)
const anyOsCheck = document.querySelector(".osCheck");
console.log(anyOsCheck);

// 属性指定([type="text"])
const firstTextField = document.querySelector('input[type="text"]');
console.log(firstTextField);

JavaScript例(全部ほしいとき):

// .osCheck クラスがついたチェックボックスを全部取得
const allOsChecks = document.querySelectorAll(".osCheck");

console.log(`.osCheck は ${allOsChecks.length} 個あります`);

for (const checkbox of allOsChecks) {
  console.log(checkbox.id); // optWin / optMac ...
}

覚えておきたいこと

  • querySelector は「1個だけ」(先頭のもの)
  • querySelectorAll は「全部」(NodeList)
  • CSSセレクタで書けるので、これだけでほぼ何でも取れる
    → 正直これさえ使えれば、上の getElementById などは「レガシーを読むとき用+一部高速にしたいとき用」くらいの感覚になってきています。

4. 取得した要素の中身を読む・書き換える

要素を取ってこれたら、次は「中身をいじる」ことができます。

ここが一番ワクワクするところです。

 4-1. テキストを書き換える:textContent

textContent は、その要素のテキストだけを読み書きできます(HTMLタグはそのまま文字として扱われます)。

HTML例:

<p id="statusMessage">このメッセージは最初の表示です。</p>
<p id="resultMessage"></p>

JavaScript例:

const msg = document.getElementById("statusMessage");

// 読み取り
console.log(msg.textContent); // "このメッセージは最初の表示です。"

// 書き換え
const output = document.getElementById("resultMessage");
output.textContent = "JavaScriptからメッセージを書き込みました!";
  • textContentテキスト専用。タグは解釈しないので安全。
  • 実務では textContent を使うことが多いです。innerText はブラウザによるレイアウトの影響を受けたりするので、まずは textContent から覚えてOKです。

 4-2. HTMLごと差し込む:innerHTML

「太字にしたい」「リンクを入れたい」など、HTMLタグもまとめて差し込みたいときは innerHTML を使います。

HTML例:

<div id="infoBox"></div>

JavaScript例:

const box = document.getElementById("infoBox");

// HTMLごと差し込む
box.innerHTML = `
  <strong>お知らせ:</strong>
  <span class="warn">メンテナンスは本日23時からです。</span>
`;
  • innerHTML は、その要素“の中身だけ”を置き換えます
  • つまり <div id="infoBox"> ...ここが丸ごと上書きされる... </div> の「…」の部分に注入されるイメージです

注意点:


ユーザーから入力された文字列などをそのまま innerHTML に入れると、XSS(スクリプト埋め込み)みたいなセキュリティリスクになる場合があります。

信頼できない文字列は textContent で入れるのが安全です。

 4-3. 要素ごと取得/置き換えたいとき:outerHTML

outerHTML は「その要素自身を含めたHTML丸ごと」を読み書きします。

<p id="replaceTarget">ここは最初の文章です。</p>
const target = document.getElementById("replaceTarget");

// いまのHTMLを確認
console.log(target.outerHTML);

// この<p>自体を別の要素に置き換える
target.outerHTML = `<div class="updated">このブロックは差し替え済みです。</div>`;

これを使うと、元の要素そのものが別のタグにすり替わります。

最初は「へぇ、こういうこともできるんだ」くらいでOKです。

5. 属性(id, class, type など)を読む・変更する

フォームやボタンを操作するときによく使います。

ここからが「ちょっとだけ開発者っぽい」感じになります。

 5-1. 属性を読む:getAttribute / .属性名

<input type="text" id="userEmail" class="inputField large" />
const emailInput = document.getElementById("userEmail");

// ① どのtypeか?
console.log(emailInput.getAttribute("type")); // "text"

// ② class名は?
console.log(emailInput.getAttribute("class")); // "inputField large"

// プロパティとして読むことも可能
console.log(emailInput.id); // "userEmail"
console.log(emailInput.type); // "text"
  • element.getAttribute("属性名")
  • もしくは element.属性名 で読めるものも多い(id, className, type など)

 5-2. 属性を書き換える:setAttribute / 代入

// classを追加・変更
emailInput.setAttribute("class", "inputField large is-error");

// idを変える(あまり多用はしないけど可能)
emailInput.id = "userEmailField";

// data属性など自由な属性も設定できる
emailInput.setAttribute("data-role", "login-email");

 5-3. 属性を削除する:removeAttribute

// class属性そのものを消す
emailInput.removeAttribute("class");

 5-4. すべての属性を確認する

開発・デバッグのときに便利です。

const emailInput = document.getElementById("userEmail");

// すべての属性名を配列でもらう
const attrNames = emailInput.getAttributeNames();

for (const name of attrNames) {
  const value = emailInput.getAttribute(name);
  console.log(`属性名: ${name} / 属性値: ${value}`);
}

6. 新しい要素を作って、ページに追加する

ここからいよいよ「動的なWebサイト」の入口です。


「ボタンを押したら新しい行を追加する」とか「エラーメッセージを下に出す」とか、全部これ。

 6-1. 要素を新しく作る:document.createElement()

// <li> を新しく作る
const newItem = document.createElement("li");

// 中身のテキストをセット
newItem.textContent = "新しく追加されたメニューです";

ここまでだと、まだメモリの中にあるだけで、画面には出ていません。
次に「どこに差し込むか」を決めて追加します。

 6-2. 子要素として追加する(末尾に):append / appendChild

HTML例:

<ul id="menuArea">
  <li>ホーム</li>
  <li>ブログ</li>
</ul>

JavaScript例:

const menuArea = document.getElementById("menuArea");

const extraItem = document.createElement("li");
extraItem.textContent = "お問い合わせ";

// リストの一番最後に追加
menuArea.append(extraItem); // または menuArea.appendChild(extraItem);

append は複数まとめて追加できたり、テキストも渡せたりする「今っぽい」メソッドです。
appendChild は昔からあるメソッドで、基本は1個ずつ要素ノードを追加します。

 6-3. 先頭に入れたいとき:prepend

const topItem = document.createElement("li");
topItem.textContent = "👑 イチオシ";

menuArea.prepend(topItem); // リストの先頭に差し込む

 6-4. 特定の要素の「前」や「後ろ」に差し込む:before / after

const note = document.createElement("p");
note.textContent = "この下のメニューは随時更新されます。";

menuArea.before(note); // <ul> の直前に差し込む

after を使えば直後に置けます。

7. 要素を削除する・置き換える

更新UIには削除も置換もよく使います。(例えば「通知を閉じる」)

 7-1. 消す:remove()

<p id="alertBox" class="notice">
  メールアドレスを入力してください
</p>
const alertBox = document.getElementById("alertBox");

// この<p>自体を削除
alertBox.remove();

 7-2. 子どもを消す:removeChild()

<ul id="todoList">
  <li>牛乳を買う</li>
  <li>レポートを提出</li>
</ul>
const todoList = document.getElementById("todoList");

// 2つ目の<li>を取得して削除
const secondTask = todoList.querySelectorAll("li")[1];
todoList.removeChild(secondTask);

 7-3. 置き換える:replaceWith

<p id="oldMessage">このメッセージは古いです</p>
const oldMsg = document.getElementById("oldMessage");

// 新しい要素を作る
const newMsg = document.createElement("div");
newMsg.className = "updatedInfo";
newMsg.textContent = "このエリアは最新の内容に置き換わりました。";

// 置換
oldMsg.replaceWith(newMsg);

これで <p id="oldMessage">…</p><div class="updatedInfo">…</div> にまるごと入れ替わります。

8. よくある「初心者がつまづくポイント」

最後に、実務ですごくありがちな勘違いも一緒にまとめます。

ここ、共感してもらえると思います。

 8-1. 「HTMLを書き換えたのに反映されない」

console.log でしか確認してない、というパターンが多いです。
console.log はあくまで“今その瞬間のオブジェクトの状態”を見るもの。
実際に textContent = "..."append(...) をして、ブラウザ画面側が変わるところまでやって初めて「画面が更新」されます。

 8-2. innerHTML と textContent の違いがわからない

  • textContent = "<strong>太字</strong>"
    → そのまま「<strong>太字</strong>」という文字になる(タグは効かない)
  • innerHTML = "<strong>太字</strong>"
    <strong> として認識され、実際に太字になる

安全性と見た目、どっちを優先したいかで使い分けます。

 8-3. querySelectorAll の結果を直接 .textContent = … しようとしてエラー

querySelectorAll は“複数”をまとめたNodeListです。

個別にアクセスするときはループで回すか、[0] のように一つ指定してから操作します。

const items = document.querySelectorAll(".newsItem");
// items.textContent = "更新しました" ← これはエラー
items[0].textContent = "更新しました"; // こうならOK

9. まとめ

  • DOMは「ブラウザがHTMLをオブジェクト化したもの」。木のような親子関係を持つ。
  • document はDOMにアクセスする入り口。
  • 要素の取得は querySelector / querySelectorAll がいまの主流。
    それ以外(getElementByIdなど)も読む力として覚えておくと◎
  • textContent / innerHTML / outerHTML で中身や構造を書き換えられる。
  • setAttribute / removeAttribute で属性(class, id, typeなど)を操作できる。
  • createElement + append / prepend / before / after で新しい要素を差し込める。
  • remove()replaceWith() で要素ごと消したり置き換えたりできる。

ここまで理解できれば、もう「静的なHTMLしか作れない人」ではなくなります。
小さなインタラクション(エラーメッセージの表示、タブ切り替え、モーダルの表示/非表示)なら自力で書ける入口に立っています。

次のステップとしては、「イベント」(クリックされたら実行する、入力されたら実行する)を学ぶと、一気に“動くサイトを作れる人”に近づきます。

そこに進む準備として、今ここで覚えた「要素を見つける力」と「中身を書き換える力」はめちゃくちゃ重要です。あなたはもう、その一歩をちゃんと踏み出せていますよ。

関連記事