はじめに (対象読者・この記事でわかること)

このページは、Webフロントエンドの実装経験がある程度ある方(HTML/CSSの基礎、JavaScriptの変数・関数レベルの知識がある方)を対象にしています。
この記事を読むと、以下のことができるようになります。

  1. ユーザーが「名前」と「ニックネーム」を最大3回まで入力できるシンプルなフォームを作成できる
  2. 入力回数が上限に達したときに「追加」ボタンを自動で非表示にし、以降の追記を防止できる
  3. 実装過程でよくある「クリックイベントが二度発火する」「カウントが正しく管理できない」等の落とし穴とその対処法を理解できる

この要件は、アンケートや簡易メモ帳など、入力回数に制限を設けたい場面で汎用的に活用できます。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。
- HTML/CSS の基本的な知識(要素の構造とスタイル指定ができる)
- JavaScript の基本構文(変数、関数、配列・オブジェクトの操作)が理解できていること
- ブラウザのデベロッパーツールでコンソール出力や要素検証ができること

背景と概要:なぜ入力回数を制限するのか

Web アプリケーションでは、ユーザーが無制限にデータを追加できると、UI が乱れたり、意図しない大量データがサーバーへ送信されるリスクがあります。
特に「名前」と「ニックネーム」のような短いテキスト入力は、たとえばユーザー情報の登録や簡易プロフィール作成の場面で頻繁に利用されます。

3 回という上限は、以下のようなシナリオで有用です。

  • UI の一貫性保持:リストが伸びすぎてページレイアウトが崩れないようにする
  • データバリデーションの簡素化:サーバー側で受信データ数をチェックする手間を削減
  • ユーザー体験の向上:入力項目が多すぎるとユーザーが戸惑うため、適度に制限する

このブログでは、純粋なフロントエンド(HTML+CSS+Vanilla JavaScript)だけで、「追加ボタンが3回クリックされたら自動で非表示になる」 機能を実装する手順を詳しく解説します。外部ライブラリは使用せず、ブラウザ標準の API だけで完結させるので、どのプロジェクトにも簡単に組み込めます。

実装手順:名前とニックネームを3回まで追加できるフォームの作り方

ステップ 1:HTML の骨子を作る

まずは、ユーザーが入力できるフォームと、追加結果を表示するリスト領域、そして「追加」ボタンを用意します。以下は最小構成のサンプルです。

Html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>名前・ニックネーム入力制限サンプル</title> <style> body { font-family: sans-serif; margin: 2rem; } #addBtn.hidden { display: none; } .entry { margin: 0.5rem 0; } </style> </head> <body> <h1>名前とニックネームを追加</h1> <label> 名前: <input type="text" id="nameInput" placeholder="例: 山田太郎"> </label> <br> <label> ニックネーム: <input type="text" id="nickInput" placeholder="例: タロウ"> </label> <br><br> <button id="addBtn">追加</button> <h2>入力されたデータ</h2> <ul id="list"></ul> <script src="app.js"></script> </body> </html>

ポイントは次の通りです。

  • #addBtnhidden クラスを付与すると CSS で非表示になるように設定
  • 入力欄はそれぞれ id を付与し、後述の JavaScript から取得しやすくしている
  • 結果表示は <ul> 要素に id="list" を設定し、<li> 要素で追加項目を列挙

ステップ 2:JavaScript でロジックを組む

次に、app.js に以下のロジックを書き込みます。

Js
// app.js (() => { // DOM 要素の取得 const nameInput = document.getElementById('nameInput'); const nickInput = document.getElementById('nickInput'); const addBtn = document.getElementById('addBtn'); const list = document.getElementById('list'); // 追加回数を管理するカウンタ let count = 0; const MAX_COUNT = 3; // 入力内容を検証するユーティリティ関数 const isValid = (name, nick) => { if (!name.trim()) { alert('名前を入力してください。'); return false; } if (!nick.trim()) { alert('ニックネームを入力してください。'); return false; } return true; }; // 追加ボタンのクリックハンドラ const addEntry = () => { const name = nameInput.value; const nick = nickInput.value; // バリデーション if (!isValid(name, nick)) return; // カウントチェック if (count >= MAX_COUNT) { // ここに来ることは基本的に無いが、万が一の保険として hideButton(); return; } // <li> 要素を生成してリストに追加 const li = document.createElement('li'); li.className = 'entry'; li.textContent = `名前: ${name} / ニックネーム: ${nick}`; list.appendChild(li); // カウントを更新 count++; // 入力欄をリセット nameInput.value = ''; nickInput.value = ''; nameInput.focus(); // 上限に達したらボタンを非表示に if (count >= MAX_COUNT) hideButton(); }; // ボタン非表示関数 const hideButton = () => { addBtn.classList.add('hidden'); addBtn.disabled = true; // クリックできなくする保険 }; // イベントリスナー登録 addBtn.addEventListener('click', addEntry); // Enter キーでも登録できるようにする(ユーザビリティ向上) [nameInput, nickInput].forEach(elem => { elem.addEventListener('keydown', e => { if (e.key === 'Enter') { e.preventDefault(); // フォーム送信を防止 addEntry(); } }); }); })();

コードのポイント解説

行/ブロック 内容 解説
let count = 0; 追加回数を保持 グローバル変数にしないために IIFE(即時関数)で閉じ込めている
const MAX_COUNT = 3; 上限定数 変更があればこの一行だけで調整可能
isValid 関数 入力の必須チェック 空文字や空白だけの場合に警告を出す
addEntry 関数 クリック時の主要ロジック バリデーション → カウント確認 → DOM 生成 → カウントインクリメント → ボタン非表示判定 の順序で実装
hideButton 関数 ボタンを隠す & 無効化 CSS の hidden クラスで表示/非表示を切り替え、disabled でも二重に防御
addBtn.addEventListener('click', addEntry); イベントバインド クリックだけでなく、Enter キーでも登録できるように keydown リスナを付与
e.preventDefault(); フォーム送信防止 <button> がデフォルトで type="submit" になるケースに備える

ステップ 3:上限超過時の UI/UX デザイン

上限に達したときは単にボタンが消えるだけでなく、ユーザーに「これ以上追加できません」というフィードバックを出すと親切です。以下のようにメッセージ要素を追加しましょう。

Html
<p id="limitMsg" class="hidden" style="color: red;">追加できる回数は3回までです。</p>
Js
const limitMsg = document.getElementById('limitMsg'); const hideButton = () => { addBtn.classList.add('hidden'); addBtn.disabled = true; limitMsg.classList.remove('hidden'); };

これにより、ボタンが消えた瞬間に赤字で注意喚起が表示されます。

ハマった点やエラー解決

発生した問題 原因 解決策
クリックが二度発火 button がデフォルトで type="submit" になり、フォーム送信と同時にページリロードが走った <button type="button" id="addBtn"> と明示的に type を指定、または e.preventDefault() を追加
カウントが正しくリセットされない count をローカル変数にしてしまい、ページ遷移やリロードでリセットされなかった let count をスクリプト全体で保持し、リロード時は 0 に初期化。必要に応じて localStorage に保存して永続化
Enter キーでの追加が失敗 keydown イベントで e.key 判定を忘れていた if (e.key === 'Enter') を追加し、preventDefault でフォーム送信を防止
ボタンが非表示になるが、タブキーでフォーカスが当たる display:none だけでは要素がキーボード操作対象になることがある disabled = true だけでなく、tabindex="-1" を設定してフォーカス遷移からも除外

さらに発展させるアイデア

  • ローカルストレージで永続化localStorage.setItem('entryCount', count) でページ再読み込み後も上限を保持
  • 削除機能:各 <li> に削除ボタンを付け、削除時に count-- して再度追加可能にする
  • サーバー連携fetch API でバックエンドにデータ送信し、サーバー側でも上限チェックを行う(二重保護)

まとめ

本記事では、名前とニックネームを最大3回まで入力できるフォームを、ボタンの自動非表示とユーザーへのフィードバック付きで実装する方法 を紹介しました。

  • 入力回数のカウント管理上限判定ロジック をシンプルに実装
  • DOM 操作とイベントハンドリング による UI の動的変化を実現
  • ハマりやすいポイント(二度発火、Enter キー、フォーカス問題)への具体的対策を提示

この実装をベースに、ローカルストレージでの永続化削除機能の追加、さらには バックエンドとの連携 へと拡張すれば、より実用的な入力制御システムが完成します。ぜひ自身のプロジェクトで試してみてください。

参考資料