【JavaScript】超シンプルなTODOアプリを作って解説してみた
おはようございます。タカヒデです。
本日はJavaScriptで「超シンプルなTODOアプリ」を作ってみました。
STEP形式で解説しているので、「まずは何かを作ってみたい」という初心者の方の参考になれば幸いです。
- プログラミング初心者
- 何から始めればよいか分からない
- まずは簡単なアプリを作って興味を持ってみたい
なお、このTODOアプリは下記のUdemy講座を参考にアレンジを加えたアプリです。
当然、講座の方が分かりやすい解説をしていますし、Reactでの実装方法も解説されているので興味のある方はそちらをご覧ください。

「TODOアプリ」完成イメージ
まずは、「TODOアプリ」完成後の最終的なコードと完成イメージです。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO App</title>
<style>
body {
font-family: sans-serif;
color: #4a5a6a;
}
input {
border: none;
padding: 6px 16px;
}
button {
border: none;
padding: 4px 16px;
margin: 0px 2px;
}
button:hover {
background-color: #4a90e2;
color: #ffffff;
cursor: pointer;
}
.input-area {
background-color: #d6e9f8;
width: 400px;
height: 30px;
padding: 8px;
margin: 8px;
display: flex;
align-items: center;
}
.todo-area {
background-color: #eef5fb;
width: 400px;
min-height: 200px;
padding: 8px;
margin: 8px;
}
.list-row {
display: flex;
align-items: center;
}
.todo-item {
margin: 6px;
}
.error-message {
margin: 6px;
font-size: 12px;
color: #d64545;
}
</style>
</head>
<body>
<div class="input-area">
<input id="add-text" placeholder="TODOを入力">
<button id="add-button">追加</button>
<div id="error-message" class="error-message" aria-live="polite"></div>
</div>
<div class="todo-area">
<ul id="todo-list"></ul>
</div>
<script src="./todo.js"></script>
</body>
</html>const showError = (message) => {
document.getElementById("error-message").innerText = message;
}
const clearError = () => {
document.getElementById("error-message").innerText = "";
}
const addTodo = () => {
const input = document.getElementById("add-text");
const inputText = input.value.trim();
if (inputText === "") {
showError("※入力してください");
input.focus();
return;
}
clearError();
input.value = ""
createTodo(inputText);
};
const createTodo = (todo) => {
const todoItem = document.createElement("li");
const todoRow = document.createElement("div");
todoRow.className = "list-row";
const todoText = document.createElement("p");
todoText.className = "todo-item";
todoText.innerText = todo;
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除"
deleteButton.addEventListener("click", () => {
const deleteTarget = deleteButton.closest("li");
deleteTarget.remove();
});
todoRow.appendChild(todoText);
todoRow.appendChild(deleteButton);
todoItem.appendChild(todoRow);
document.getElementById("todo-list").appendChild(todoItem);
};
document.getElementById("add-button").addEventListener("click", addTodo);
document.getElementById("add-text").addEventListener("keydown", (e) => {
if (e.key === "Enter") {
addTodo();
}
});こんなアプリが作れます。

本当にシンプルですね。
入力した内容をTODO一覧に表示して削除ボタンを実装しているだけのアプリです。
STEP1:HTMLでアプリ画面を作る
まずは、HTMLでTODOアプリの画面を作ります。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>TODO App</title>
<style>
body {
font-family: sans-serif;
color: #4a5a6a;
}
input {
border: none;
padding: 6px 16px;
}
button {
border: none;
padding: 4px 16px;
margin: 0px 2px;
}
button:hover {
background-color: #4a90e2;
color: #ffffff;
cursor: pointer;
}
.input-area {
background-color: #d6e9f8;
width: 400px;
height: 30px;
padding: 8px;
margin: 8px;
display: flex;
align-items: center;
}
.todo-area {
background-color: #eef5fb;
width: 400px;
min-height: 200px;
padding: 8px;
margin: 8px;
}
.list-row {
display: flex;
align-items: center;
}
.todo-item {
margin: 6px;
}
.error-message {
margin: 6px;
font-size: 12px;
color: #d64545;
}
</style>
</head>
<body>
<div class="input-area">
<input id="add-text" placeholder="TODOを入力">
<button id="add-button">追加</button>
<div id="error-message" class="error-message" aria-live="polite"></div>
</div>
<div class="todo-area">
<ul id="todo-list"></ul>
</div>
<script src="./todo.js"></script>
</body>
</html>手順①:入力エリアを作る
<div class="input-area">
<input id="add-text" placeholder="TODOを入力">
<button id="add-button">追加</button>
<div id="error-message" class="error-message" aria-live="polite"></div>
</div>
このブロックは、ユーザーがTODOを入力するためのエリアです。
- input
- TODOの内容入力欄
- button
- 追加ボタン
- div id=”error-message”
- 入力が空だったとき用のエラー文表示欄
手順②:TODO一覧の表示エリアを作る
<div class="todo-area">
<ul id="todo-list"></ul>
</div>ここは、追加したTODOを並べて表示するためのエリアです。
- ul
- 箇条書きリスト
「id=”todo-list”」を付けておくことで、後でJavaScriptから操作できるようします。
手順③:CSSで見た目を整える
<style>
body {
font-family: sans-serif;
color: #4a5a6a;
}
・・・
</style>この部分はCSSの<style>で見た目を整える設定です。
一つ一つのスタイルの解説はしません。
ここは本質ではないので面倒くさかったらコピペでもOKです。
ここまでで実行するとTODOアプリの画面ができていることは分かります。
ただし、まだ追加ボタンなどを押しても何も起こりません。

STEP2:TODOをリストに追加する
このSTEPでは、入力欄に入れたTODOを取得し、一覧に表示できるようにします。
「入力→追加ボタン→リストに1件増える」までが動けば、このSTEPはOKです。
ここからはHTMLは変更しないので、JavaScriptのみ記載していきます。
//STEP2追加
const addTodo = () => {
const input = document.getElementById("add-text");
const inputText = input.value;
input.value = "";
createTodo(inputText);
};
//STEP2追加
const createTodo = (todo) => {
const todoItem = document.createElement("li");
todoItem.innerText = todo;
document.getElementById("todo-list").appendChild(todoItem);
};
//STEP2追加
document.getElementById("add-button").addEventListener("click", addTodo);手順①:追加ボタン押下時の関数を用意する
const addTodo = () => {
const input = document.getElementById("add-text");
const inputText = input.value;
input.value = "";
createTodo(inputText);
};
追加ボタンが押されたときに動く「addTodoメソッド」を作ります。
- const input = document.getElementById(“add-text”);
- HTMLの「id=”add-text”」を持つ入力欄を探す
- const inputText = input.value;
- ユーザーが入力したTODOの内容が入る
- input.value = “”
- 入力欄のテキストをクリアする
手順②:追加ボタンと「addTodoメソッド」をつなぐ
document.getElementById("add-button").addEventListener("click", addTodo);
先ほど作成した「addTodo」メソッドと、追加ボタンに設定された「add-button」idをつなぐことで、ボタン押下時に処理が実行できるようにします。
手順③:TODO一覧に入力内容を表示する
const createTodo = (todo) => {
const todoItem = document.createElement("li");
todoItem.innerText = todo;
document.getElementById("todo-list").appendChild(todoItem);
};「createTodo」メソッドでTODO一覧に入力内容を表示します。
- document.createElement(“li”)
- 新しい箇条書きの1行を作成
- todoItem.innerText = todo;
- 箇条書きに表示する文字を入れる
- document.getElementById(“todo-list”).appendChild(todoItem);
- 箇条書きをHTMLの「ul」に追加する
これで実行してみましょう。
入力した内容がTODOリストとして表示されることが分かります。
ただ、現時点では空欄でも追加できてしまうので、次のSTEPでここを直していきましょう。

STEP3:TODOが空欄では追加できないようする
このSTEPでは、入力が空のときはTODOを追加せず、エラーメッセージを表示するようにします。
//STEP3追加
const showError = (message) => {
document.getElementById("error-message").innerText = message;
}
//STEP3追加
const clearError = () => {
document.getElementById("error-message").innerText = "";
}
const addTodo = () => {
const input = document.getElementById("add-text");
//STEP3変更
const inputText = input.value.trim();
//STEP3追加
if (inputText === "") {
showError("※入力してください");
input.focus();
return;
}
//STEP3追加
clearError();
input.value = ""
createTodo(inputText);
};
const createTodo = (todo) => {
const todoItem = document.createElement("li");
todoItem.innerText = todo;
document.getElementById("todo-list").appendChild(todoItem);
};
document.getElementById("add-button").addEventListener("click", addTodo);
手順①:エラー表示用の関数を用意
const showError = (message) => {
document.getElementById("error-message").innerText = message;
}
「showError」は、エラーメッセージ欄に文字を表示するための処理です。
- document.getElementById(“error-message”)
- HTMLの「エラー表示欄」を取得
- innerText = message
- 表示したい文章を入れる
手順②:エラーを消す関数を用意
const clearError = () => {
document.getElementById("error-message").innerText = "";
}
このままでは、正しい入力をした場合にもエラーが残ってしまいます。
そこで、「clearError」メソッドにより正常に追加できるときはエラー表示を消すようにします。
「innerText」を空文字にすることで、画面上の表示が消えます。
手順③:追加ボタン押下時に空欄をチェックし処理を止める
const inputText = input.value.trim();
if (inputText === "") {
showError("※入力してください");
input.focus();
return;
}
「addTodo」メソッドで、空欄の際にリスト追加しないように処理を止めます。
- trim()
- 文字の前後にある空白を取り除く
- if (inputText === “”)
- 入力が空かどうかを判定
- input.focus()
- カーソルを入力欄に戻す
これで実行すると、空欄では追加できなくなっているはずです。
正しくエラーになるか確認してみてください。

STEP4:Enterキーでも追加できるようにする
このSTEPでは、入力欄でEnterキーを押したときにも、追加ボタンと同じ処理が動くようにします。
いちいち追加ボタンを押さなくてもEnterで処理できればユーザーにやさしいアプリが作れます。
const showError = (message) => {
document.getElementById("error-message").innerText = message;
}
const clearError = () => {
document.getElementById("error-message").innerText = "";
}
const addTodo = () => {
const input = document.getElementById("add-text");
const inputText = input.value.trim();
if (inputText === "") {
showError("※入力してください");
input.focus();
return;
}
clearError();
input.value = ""
createTodo(inputText);
};
const createTodo = (todo) => {
const todoItem = document.createElement("li");
todoItem.innerText = todo;
document.getElementById("todo-list").appendChild(todoItem);
};
document.getElementById("add-button").addEventListener("click", addTodo);
//STEP4追加
document.getElementById("add-text").addEventListener("keydown", (e) => {
if (e.key === "Enter") {
addTodo();
}
});手順①:入力欄に「keydownイベント」を設定する
document.getElementById("add-text").addEventListener("keydown", (e) => {
if (e.key === "Enter") {
addTodo();
}
});
ここでの処理はこれだけです。
入力欄(id=”add-text”)に対してイベントを設定しています。
- keydown
- キーが押されたときに発生するイベント
- e.key === “Enter”
- Enterが押されたときに処理する
これで実行してみてください。
わざわざ追加ボタンを押さなくてもEnterで追加できるので楽ちんアプリになってます。

STEP5:削除ボタンを付けて、TODOを消せるようにする
これが最後のSTEPです。
追加したTODOの右側に削除ボタンを付け、そのTODOが消えるようにします。
const showError = (message) => {
document.getElementById("error-message").innerText = message;
}
const clearError = () => {
document.getElementById("error-message").innerText = "";
}
const addTodo = () => {
const input = document.getElementById("add-text");
const inputText = input.value.trim();
if (inputText === "") {
showError("※入力してください");
input.focus();
return;
}
clearError();
input.value = ""
createTodo(inputText);
};
const createTodo = (todo) => {
const todoItem = document.createElement("li");
//STEP5追加
const todoRow = document.createElement("div");
todoRow.className = "list-row";
//STEP5追加
const todoText = document.createElement("p");
todoText.className = "todo-item";
todoText.innerText = todo;
//STEP5追加
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除"
deleteButton.addEventListener("click", () => {
const deleteTarget = deleteButton.closest("li");
deleteTarget.remove();
});
//STEP5追加
todoRow.appendChild(todoText);
todoRow.appendChild(deleteButton);
todoItem.appendChild(todoRow);
document.getElementById("todo-list").appendChild(todoItem);
};
document.getElementById("add-button").addEventListener("click", addTodo);
document.getElementById("add-text").addEventListener("keydown", (e) => {
if (e.key === "Enter") {
addTodo();
}
});
手順①:TODO1件分の行を作る
const todoRow = document.createElement("div");
todoRow.className = "list-row";
const todoText = document.createElement("p");
todoText.className = "todo-item";
todoText.innerText = todo;
STEP5までは「li」タグに直接文字を入れていました。
ただ、削除ボタンも一緒に表示したい場合、文字とボタンを横並びにする必要があります。
そこで、「li」の中に「div」タグや「p」タグを作り、その中に「文字」と「ボタン」を入れる形にします。
手順②:「削除」ボタンを作り、クリックで行を消す
const deleteButton = document.createElement("button");
deleteButton.innerText = "削除"
deleteButton.addEventListener("click", () => {
const deleteTarget = deleteButton.closest("li");
deleteTarget.remove();
});
「deleteButton」で削除ボタンを作り、クリックされたときに消す処理を入れています。
- addEventListener(“click”, …)
- クリック時に動く処理を設定
- closest(“li”)
- このボタンに一番近い親要素の li を探す
- remove()
- その要素を画面から削除
手順③:作った要素を正しい順番で組み立てる
todoRow.appendChild(todoText);
todoRow.appendChild(deleteButton);
todoItem.appendChild(todoRow);
document.getElementById("todo-list").appendChild(todoItem);
DOM操作は「部品を作る」だけでは画面に出ません。
最後に「どの箱に入れるか」を決めて、順番に組み立てる必要があります。
今回の組み立て順は以下です。
- 「todoText」と「deleteButton」を「todoRow」に入れる
- 「todoRow」を「todoItem(li)」に入れる
- 「todoItem」を「todo-list(ul)」に入れる
この順番を守ると、1行が「文字+削除ボタン」の形になり、リストに追加されます。
これで、TODOアプリとして「追加」と「削除」が両方できる状態になっています。
完成
以上でJavaScriptで作る「TODOアプリ」の完成です。
ぜひ、コードをコピペするのではなく、実際にコードを打って作ってみてください。

お疲れさまでした。
