Password Input — パスワード入力(表示切替・強度インジケーター)
このコンポーネントについて
パスワード入力フィールドに必須の2つのUIパターンを提供します。 Pattern 1は目のアイコンボタンをクリックするだけでパスワードの表示/非表示を切り替えるシンプルな実装です。
Pattern 2はPattern 1の表示切替機能に加え、入力内容をリアルタイムで判定して強度(弱い〜非常に強い)をバーとラベルで表示します。 条件チェックリスト(文字数・大文字・数字・記号)も同時表示するため、ユーザーがどの条件を満たせばよいか一目でわかります。 会員登録・パスワード変更フォームに組み込むことで、強いパスワード設定を自然に促せます。
- 表示/非表示切替 — 目アイコンをクリックして
type="password"↔type="text"を切り替え。アイコンは開閉状態に応じてSVGで表示変更 - 強度バー(4段階) — 入力内容に応じて「弱い(赤)/ 普通(黄)/ 強い(緑)/ 非常に強い(深緑)」を表示
- 条件チェックリスト — 「8文字以上 / 大文字を含む / 数字を含む / 記号を含む」の4条件を満たすとチェックが入る
- ライブラリなし — 外部ライブラリ不使用。バニラJSとインラインSVGのみで実装
実装のポイント・注意点
パスワードの表示/非表示切替は input.type を "text" と "password" で切り替えるだけで実現できます。
目のアイコンはSVGをHTMLにインラインで記述し、CSSの display 切り替えで表示状態に応じたアイコンを出し分けます。
外部アイコンライブラリが不要なため、ページの読み込みを余分に増やさずに済みます。
強度判定は正規表現で4条件(8文字以上・大文字・数字・記号)をチェックし、達成数をスコアとして扱います。
スコアに応じてバーの幅(style.width)と色(style.backgroundColor)をJSで直接変更しています。
transition をCSSに設定しておくと、バーが滑らかにアニメーションします。
autocomplete 属性はブラウザのパスワードマネージャーへのヒントになります。
ログインフォームは autocomplete="current-password"、新規登録・変更フォームは autocomplete="new-password" を使い分けてください。
HTML・CSS・バニラJavaScriptのみで実装しており、フレームワーク不要でコピペすぐに動きます。
デモ
Pattern 1 — 表示/非表示切替
Pattern 2 — 強度インジケーター付き
- 8文字以上
- 大文字を含む(A〜Z)
- 数字を含む(0〜9)
- 記号を含む(!@#$ など)
サンプルソース
3つのファイルを同じフォルダに保存し、index.html をブラウザで開くとすぐに動作確認できます。
ファイル名:index.html / style.css / script.js
— 保存時の文字コードは UTF-8 を指定してください(Shift-JISだと日本語が文字化けします)。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>パスワード入力 サンプル</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- Pattern 1: 表示/非表示切替のみ -->
<div class="pw-section">
<p class="pw-section-label">Pattern 1 — 表示/非表示切替</p>
<div class="pw-field-wrapper">
<input type="password" id="pw1" class="pw-input"
placeholder="パスワードを入力" autocomplete="current-password">
<button type="button" class="pw-toggle-btn" id="toggleBtn1" aria-label="パスワードを表示">
<!-- 目を開くアイコン(非表示モード時に表示) -->
<svg class="pw-icon pw-icon--show" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
<circle cx="12" cy="12" r="3"/>
</svg>
<!-- 目を閉じるアイコン(表示モード時に表示) -->
<svg class="pw-icon pw-icon--hide" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/>
<path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/>
<line x1="1" y1="1" x2="23" y2="23"/>
</svg>
</button>
</div>
</div>
<!-- Pattern 2: 強度インジケーター付き -->
<div class="pw-section">
<p class="pw-section-label">Pattern 2 — 強度インジケーター付き</p>
<div class="pw-field-wrapper">
<input type="password" id="pw2" class="pw-input"
placeholder="パスワードを入力" autocomplete="new-password">
<button type="button" class="pw-toggle-btn" id="toggleBtn2" aria-label="パスワードを表示">
<svg class="pw-icon pw-icon--show" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
<circle cx="12" cy="12" r="3"/>
</svg>
<svg class="pw-icon pw-icon--hide" xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M17.94 17.94A10.07 10.07 0 0 1 12 20c-7 0-11-8-11-8a18.45 18.45 0 0 1 5.06-5.94"/>
<path d="M9.9 4.24A9.12 9.12 0 0 1 12 4c7 0 11 8 11 8a18.5 18.5 0 0 1-2.16 3.19"/>
<line x1="1" y1="1" x2="23" y2="23"/>
</svg>
</button>
</div>
<div class="pw-strength-row">
<div class="pw-strength-bar-track">
<div class="pw-strength-bar-fill" id="strengthBar"></div>
</div>
<span class="pw-strength-label" id="strengthLabel">—</span>
</div>
<ul class="pw-criteria-list">
<li class="pw-criteria-item" id="crit-length">8文字以上</li>
<li class="pw-criteria-item" id="crit-upper">大文字を含む(A〜Z)</li>
<li class="pw-criteria-item" id="crit-digit">数字を含む(0〜9)</li>
<li class="pw-criteria-item" id="crit-symbol">記号を含む(!@#$ など)</li>
</ul>
</div>
<script src="./script.js"></script>
</body>
</html>
/* === パスワード入力 ===
色を変えたいときは :root の変数を書き換えるだけでOKです */
:root {
--color-primary: #2B7FE8; /* フォーカスリングなどの強調色 */
--color-border: #D0D7E0; /* 通常時のボーダー色 */
--color-muted: #9AA5B4; /* 未達成の条件テキスト色 */
--color-met: #22C55E; /* 達成済みの条件テキスト色(緑) */
}
*, *::before, *::after { box-sizing: border-box; }
body {
font-family: sans-serif;
padding: 24px;
max-width: 400px;
margin: 0 auto;
display: flex;
flex-direction: column;
gap: 32px;
}
/* パターンのラベル */
.pw-section-label {
margin: 0 0 10px;
font-size: 12px;
font-weight: 700;
color: var(--color-primary);
letter-spacing: 0.04em;
}
/* inputとボタンを重ねるコンテナ */
.pw-field-wrapper {
position: relative;
display: flex;
align-items: center;
}
.pw-input {
width: 100%;
padding: 10px 44px 10px 12px; /* 右側にボタン分のスペースを確保 */
font-size: 14px;
font-family: sans-serif;
color: #1A2332;
border: 1.5px solid var(--color-border);
border-radius: 8px;
outline: none;
transition: border-color 0.15s, box-shadow 0.15s;
}
.pw-input:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(43, 127, 232, 0.12);
}
/* 目アイコンボタン */
.pw-toggle-btn {
position: absolute;
right: 10px;
display: flex;
align-items: center;
justify-content: center;
background: none;
border: none;
cursor: pointer;
color: #8A9BAE;
line-height: 0;
padding: 4px;
border-radius: 4px;
transition: color 0.15s;
}
.pw-toggle-btn:hover { color: #5A6A7A; }
/* 初期状態: 目を閉じるアイコンは非表示 */
.pw-icon--hide { display: none; }
/* .is-visible クラスが付いたときアイコンを入れ替える */
.pw-toggle-btn.is-visible .pw-icon--show { display: none; }
.pw-toggle-btn.is-visible .pw-icon--hide { display: block; }
/* === 強度インジケーター === */
.pw-strength-row {
display: flex;
align-items: center;
gap: 10px;
margin-top: 10px;
}
.pw-strength-bar-track {
flex: 1;
height: 6px;
background: var(--color-border);
border-radius: 3px;
overflow: hidden;
}
/* 幅と色はJSで動的に変更する */
.pw-strength-bar-fill {
height: 100%;
width: 0;
border-radius: 3px;
transition: width 0.3s, background-color 0.3s;
}
.pw-strength-label {
font-size: 12px;
font-weight: 700;
min-width: 60px;
color: #5A6A7A;
}
/* === 条件チェックリスト === */
.pw-criteria-list {
list-style: none;
margin: 10px 0 0;
padding: 0;
display: flex;
flex-direction: column;
gap: 4px;
}
/* 未達成: グレー。::before でアイコンを表示 */
.pw-criteria-item {
font-size: 13px;
color: var(--color-muted);
padding-left: 18px;
position: relative;
}
.pw-criteria-item::before {
content: '○';
position: absolute;
left: 0;
font-size: 11px;
}
/* 達成済み: 緑 + チェックマーク */
.pw-criteria-item.met {
color: var(--color-met);
}
.pw-criteria-item.met::before {
content: '✓';
font-weight: 700;
}
@media (max-width: 480px) {
body { padding: 16px; }
}
// ===== 表示/非表示切替(両パターン共通の処理) =====
function setupToggle(inputId, btnId) {
var input = document.getElementById(inputId);
var btn = document.getElementById(btnId);
btn.addEventListener('click', function () {
var isVisible = btn.classList.toggle('is-visible');
// type を切り替えて表示/非表示を制御する
input.type = isVisible ? 'text' : 'password';
// スクリーンリーダー向けにラベルも更新する
btn.setAttribute('aria-label', isVisible ? 'パスワードを非表示' : 'パスワードを表示');
});
}
setupToggle('pw1', 'toggleBtn1');
setupToggle('pw2', 'toggleBtn2');
// ===== Pattern 2: 強度インジケーター =====
var pw2 = document.getElementById('pw2');
var strengthBar = document.getElementById('strengthBar');
var strengthLabel = document.getElementById('strengthLabel');
// 強度スコアごとのバー幅・色・ラベルテキスト
var STRENGTH_LEVELS = [
{ width: '0%', color: '', label: '—' },
{ width: '25%', color: '#EF4444', label: '弱い' },
{ width: '50%', color: '#F59E0B', label: '普通' },
{ width: '75%', color: '#22C55E', label: '強い' },
{ width: '100%', color: '#16A34A', label: '非常に強い' }
];
// 4つの条件: 要素IDと判定関数のペア
var CRITERIA = [
{ id: 'crit-length', test: function (v) { return v.length >= 8; } },
{ id: 'crit-upper', test: function (v) { return /[A-Z]/.test(v); } },
{ id: 'crit-digit', test: function (v) { return /[0-9]/.test(v); } },
{ id: 'crit-symbol', test: function (v) { return /[^A-Za-z0-9]/.test(v); } }
];
pw2.addEventListener('input', function () {
var value = pw2.value;
var score = 0;
// 各条件を判定してクラスを付け外し、スコアを集計する
CRITERIA.forEach(function (crit) {
var el = document.getElementById(crit.id);
var met = crit.test(value);
el.classList.toggle('met', met);
if (met) score++;
});
// 未入力のときはスコアを 0 扱いにしてバーをリセットする
if (value === '') score = 0;
var level = STRENGTH_LEVELS[score];
strengthBar.style.width = level.width;
strengthBar.style.backgroundColor = level.color;
strengthLabel.textContent = level.label;
});
AI用プロンプト
各パターンのプロンプトをコピーしてAIに渡すと、同様のコンポーネントを生成できます。
ChatGPTやClaudeにこのプロンプトを渡すと、同様のコンポーネントをゼロから生成・カスタマイズできます。条件の追加や色の変更など、要件を追記して使うのがおすすめです。
※ このプロンプトを使ってもデモとまったく同じ動作にならない場合があります。AIの解釈や生成タイミングによって差が出ることをご了承ください。
💡 jQuery・Vue・React など特定のライブラリで実装したい場合は、プロンプトの末尾に「〇〇を使って実装してください」と追記してください。
Pattern 1 — 表示/非表示切替
# パスワード表示/非表示切替 作成依頼
## 概要
パスワード入力フィールドに目のアイコンボタンを付け、クリックでパスワードの表示/非表示を切り替えるUIを作成してください。
## 要件
- パスワードフィールドの右端に目のアイコンボタンを配置する
- ボタンクリックでtype="password"とtype="text"をトグルする
- アイコンは表示状態・非表示状態でSVGを切り替える(外部画像・外部ライブラリ不使用)
- アクセシビリティ対応としてaria-labelを「パスワードを表示」「パスワードを非表示」で切り替える
## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要
## 動作詳細
inputとボタンをposition: relativeのコンテナに入れ、ボタンはposition: absoluteで右端に配置します。SVGアイコンは「目を開く」「斜線で目を閉じる」の2つをHTMLに埋め込み、CSSのdisplay切り替えで表示を変えます。
## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。
Pattern 2 — 強度インジケーター付き
# パスワード強度インジケーター 作成依頼
## 概要
パスワード入力フィールドに強度インジケーター(バー+ラベル)と条件チェックリストを付けた、安全なパスワード入力フォームを作成してください。表示/非表示の目アイコン機能も含みます。
## 要件
- パスワードフィールドに目のアイコンボタンを付け、表示/非表示をトグルできる
- 入力中にリアルタイムで強度を判定し、バーとラベルで表示する
- 強度は「弱い / 普通 / 強い / 非常に強い」の4段階
- バーの幅と色が段階に応じて変化する(アニメーション付き)
- 以下4条件をチェックリストで表示し、条件を満たしたらチェックマーク付きに変わる
- 8文字以上
- 大文字を含む(A〜Z)
- 数字を含む(0〜9)
- 記号を含む(!@#$ など)
## 技術仕様
- HTML / CSS / バニラJavaScript で実装
- 外部ライブラリ:なし
- レスポンシブ対応:必要
## 動作詳細
inputイベントで4条件(length>=8 / [A-Z] / [0-9] / [^A-Za-z0-9])を判定し、達成数をスコアとしてバー幅・色・ラベルを更新します。未入力時はバーをリセットして「—」を表示してください(「弱い」と表示しない)。条件要素にはCSSクラスの付け外しでチェック表示を切り替えます。テキストの更新はすべてtextContentを使用し、innerHTMLは使わないでください。
## 出力形式
HTML・CSS・JavaScriptを分けて出力してください。
各ファイルは単独でコピー&ペーストして使えるよう記述してください。