パスワード強度メーター
文字数・大小文字・数字・記号の条件を判定し、4段階のバーと色で強度を可視化。表示切替や条件チェックリスト付きで会員登録に最適です。
ライブデモ
使用例(お題: SaaS FlowDesk)
この技法を「SaaS FlowDesk」というテーマのダミーサイトで実際に使った例です。
HTML
<div class="fd-screen">
<div class="fd-card">
<div class="fd-brand"><span class="fd-mark">◇</span> FlowDesk</div>
<h2 class="fd-title">アカウントを作成</h2>
<p class="fd-sub">14日間の無料トライアルをはじめましょう</p>
<label class="fd-flabel" for="fd-email">仕事用メールアドレス</label>
<input id="fd-email" class="fd-input" type="email" placeholder="you@company.com" autocomplete="off">
<label class="fd-flabel" for="pw-input">パスワード</label>
<div class="pw-wrap">
<input id="pw-input" class="fd-input" type="password" placeholder="8文字以上" autocomplete="off">
<button id="pw-toggle" class="pw-toggle" type="button">表示</button>
</div>
<!-- 強度メーター(技法の主役) -->
<div class="pw-meter">
<div class="pw-bar"></div><div class="pw-bar"></div>
<div class="pw-bar"></div><div class="pw-bar"></div>
</div>
<p id="pw-level" class="pw-level">パスワードを入力してください</p>
<ul class="pw-checks">
<li data-check="len">8文字以上</li>
<li data-check="case">大文字と小文字</li>
<li data-check="num">数字を含む</li>
<li data-check="sym">記号を含む</li>
</ul>
<button class="fd-cta" type="button">無料ではじめる</button>
</div>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
background:
radial-gradient(80% 60% at 85% 0%, rgba(79, 124, 255, 0.35), transparent 60%),
#0f1b34;
color: #e8edf7;
}
.fd-card {
width: min(360px, 92vw);
padding: 26px 28px 24px;
background: #16244a;
border: 1px solid rgba(120, 150, 220, 0.22);
border-radius: 16px;
box-shadow: 0 26px 60px -24px rgba(0, 0, 0, 0.8);
}
.fd-brand {
display: flex; align-items: center; gap: 7px;
font-size: 0.82rem; font-weight: 700; letter-spacing: 0.06em; color: #9fb6f0;
}
.fd-mark { color: #4f7cff; font-size: 1rem; }
.fd-title { margin: 12px 0 4px; font-size: 1.2rem; font-weight: 800; }
.fd-sub { margin: 0 0 18px; font-size: 0.78rem; color: #8ea0c4; }
.fd-flabel { display: block; margin: 0 0 6px; font-size: 0.74rem; font-weight: 600; color: #aebcdc; }
.fd-input {
width: 100%;
padding: 11px 13px;
margin-bottom: 14px;
font-size: 0.92rem; color: #eef2fb;
background: #0f1b34;
border: 1.5px solid rgba(120, 150, 220, 0.3); border-radius: 10px;
outline: none;
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.fd-input::placeholder { color: #5f719a; }
.fd-input:focus { border-color: #4f7cff; box-shadow: 0 0 0 3px rgba(79, 124, 255, 0.25); }
.pw-wrap { position: relative; }
.pw-wrap .fd-input { margin-bottom: 10px; padding-right: 56px; }
.pw-toggle {
position: absolute; right: 8px; top: 9px;
padding: 5px 9px; font-size: 0.72rem; font-weight: 600;
color: #9fb6f0; background: rgba(79, 124, 255, 0.14);
border: none; border-radius: 7px; cursor: pointer;
}
/* 強度バー */
.pw-meter { display: flex; gap: 6px; margin: 4px 0 8px; }
.pw-bar {
flex: 1; height: 6px; border-radius: 99px;
background: rgba(120, 150, 220, 0.22);
transition: background 0.25s ease;
}
.pw-bar.on { background: var(--pw-color, #4f7cff); }
.pw-level {
margin: 0 0 12px; font-size: 0.78rem; font-weight: 700;
color: var(--pw-color, #8ea0c4);
}
/* 条件チェックリスト */
.pw-checks {
list-style: none; margin: 0 0 16px; padding: 0;
display: grid; grid-template-columns: 1fr 1fr; gap: 5px 12px;
}
.pw-checks li {
position: relative; padding-left: 20px;
font-size: 0.74rem; color: #7e8fb6;
transition: color 0.18s ease;
}
.pw-checks li::before {
content: "○"; position: absolute; left: 0; top: 0;
font-size: 0.72rem; color: #5f719a;
}
.pw-checks li.ok { color: #6ee7b7; }
.pw-checks li.ok::before { content: "✓"; color: #34d399; }
.fd-cta {
width: 100%; padding: 12px;
font-size: 0.92rem; font-weight: 700; letter-spacing: 0.03em;
color: #fff;
background: linear-gradient(135deg, #4f7cff, #2f5fe0);
border: none; border-radius: 10px; cursor: pointer;
box-shadow: 0 12px 24px -10px rgba(79, 124, 255, 0.8);
transition: transform 0.15s ease;
}
.fd-cta:hover { transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) {
.pw-bar, .pw-checks li, .fd-input, .fd-cta { transition: none; }
}
JavaScript
const input = document.getElementById("pw-input");
const toggle = document.getElementById("pw-toggle");
const levelEl = document.getElementById("pw-level");
const bars = [...document.querySelectorAll(".pw-bar")];
const checkItems = [...document.querySelectorAll(".pw-checks li")];
const cta = document.querySelector(".fd-cta");
// 強度レベルごとの色とラベル(0〜4)
const LEVELS = [
{ label: "パスワードを入力してください", color: "#8ea0c4" },
{ label: "弱い", color: "#f87171" },
{ label: "普通", color: "#fbbf24" },
{ label: "強い", color: "#34d399" },
{ label: "とても強い", color: "#22d3ee" },
];
// 各条件を判定
function evaluate(v) {
return {
len: v.length >= 8,
case: /[a-z]/.test(v) && /[A-Z]/.test(v),
num: /\d/.test(v),
sym: /[^A-Za-z0-9]/.test(v),
};
}
function update() {
if (!input) return;
const v = input.value;
const checks = evaluate(v);
// チェックリスト反映
checkItems.forEach((li) => {
const key = li.dataset.check;
li.classList.toggle("ok", !!checks[key]);
});
// スコア=満たした条件数。空なら0
const score = v.length === 0 ? 0 : Object.values(checks).filter(Boolean).length;
const level = LEVELS[score];
bars.forEach((bar, i) => {
bar.classList.toggle("on", i < score);
bar.style.setProperty("--pw-color", level.color);
});
levelEl.textContent = level.label;
levelEl.style.setProperty("--pw-color", level.color);
}
if (input) input.addEventListener("input", update);
// 表示/非表示トグル
if (toggle && input) {
toggle.addEventListener("click", () => {
const show = input.type === "password";
input.type = show ? "text" : "password";
toggle.textContent = show ? "隠す" : "表示";
});
}
// CTAは実送信せず完了表示(デモ)
if (cta) {
cta.addEventListener("click", () => {
const keep = cta.textContent;
cta.textContent = "アカウントを作成しました ✓";
setTimeout(() => (cta.textContent = keep), 1600);
});
}
update();
コード
HTML
<div class="stage">
<div class="pw-card">
<h2 class="pw-title">パスワードを設定</h2>
<div class="pw-field">
<input id="pw-input" class="pw-input" type="password" placeholder="パスワードを入力" autocomplete="new-password">
<button id="pw-toggle" class="pw-eye" type="button" aria-label="表示切替">表示</button>
</div>
<!-- 強度バー(4セグメント) -->
<div class="pw-bars" aria-hidden="true">
<span class="pw-bar"></span><span class="pw-bar"></span>
<span class="pw-bar"></span><span class="pw-bar"></span>
</div>
<p class="pw-level" id="pw-level">パスワードを入力してください</p>
<!-- 条件チェックリスト -->
<ul class="pw-checks">
<li data-check="len"><i></i>8文字以上</li>
<li data-check="case"><i></i>大文字と小文字</li>
<li data-check="num"><i></i>数字を含む</li>
<li data-check="sym"><i></i>記号を含む</li>
</ul>
</div>
</div>
CSS
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
background: linear-gradient(160deg, #0f172a, #1e1b4b 60%, #312e81);
color: #e5e7eb;
}
.stage { width: 100%; padding: 22px; display: grid; place-items: center; }
.pw-card {
width: min(360px, 92vw);
padding: 26px 24px;
background: rgba(23, 27, 46, 0.92);
border: 1px solid #2e3556;
border-radius: 16px;
box-shadow: 0 24px 56px -24px rgba(0, 0, 0, 0.7);
}
.pw-title { margin: 0 0 16px; font-size: 1.1rem; letter-spacing: 0.04em; }
.pw-field { position: relative; }
.pw-input {
width: 100%;
padding: 12px 64px 12px 14px;
font-size: 1rem;
color: #f1f5f9;
background: #11152a;
border: 1.5px solid #3a4368;
border-radius: 10px;
outline: none;
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.pw-input:focus { border-color: #818cf8; box-shadow: 0 0 0 3px rgba(129, 140, 248, 0.22); }
.pw-eye {
position: absolute;
right: 8px; top: 50%;
transform: translateY(-50%);
padding: 5px 9px;
font-size: 0.74rem;
color: #c7d2fe;
background: #2a3157;
border: none;
border-radius: 7px;
cursor: pointer;
}
.pw-eye:hover { background: #353e6e; }
/* 強度バー */
.pw-bars { display: flex; gap: 6px; margin: 16px 0 8px; }
.pw-bar {
flex: 1;
height: 6px;
border-radius: 4px;
background: #2c3454;
transition: background 0.3s ease;
}
/* スコアに応じた点灯色は変数で受け取る */
.pw-bar.on { background: var(--pw-color, #818cf8); }
.pw-level { margin: 0 0 14px; font-size: 0.82rem; color: var(--pw-color, #94a3b8); transition: color 0.3s ease; font-weight: 600; }
/* チェックリスト */
.pw-checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.pw-checks li {
display: flex; align-items: center; gap: 9px;
font-size: 0.8rem; color: #8b95b2;
transition: color 0.2s ease;
}
.pw-checks i {
width: 16px; height: 16px; flex: none;
border-radius: 50%;
border: 1.5px solid #4b5578;
position: relative;
transition: background 0.2s ease, border-color 0.2s ease;
}
.pw-checks li.ok { color: #d1fae5; }
.pw-checks li.ok i { background: #34d399; border-color: #34d399; }
/* チェックマーク */
.pw-checks li.ok i::after {
content: "";
position: absolute;
left: 4.5px; top: 1.5px;
width: 4px; height: 8px;
border: solid #0b3b2a;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
@media (prefers-reduced-motion: reduce) {
.pw-bar, .pw-level, .pw-checks li, .pw-checks i { transition: none; }
}
JavaScript
const input = document.getElementById("pw-input");
const toggle = document.getElementById("pw-toggle");
const levelEl = document.getElementById("pw-level");
const bars = [...document.querySelectorAll(".pw-bar")];
const checkItems = [...document.querySelectorAll(".pw-checks li")];
// 強度レベルごとの色とラベル(0〜4)
const LEVELS = [
{ label: "パスワードを入力してください", color: "#94a3b8" },
{ label: "弱い", color: "#f87171" },
{ label: "普通", color: "#fbbf24" },
{ label: "強い", color: "#34d399" },
{ label: "とても強い", color: "#22d3ee" },
];
// 各条件を判定
function evaluate(v) {
return {
len: v.length >= 8,
case: /[a-z]/.test(v) && /[A-Z]/.test(v),
num: /\d/.test(v),
sym: /[^A-Za-z0-9]/.test(v),
};
}
function update() {
if (!input) return;
const v = input.value;
const checks = evaluate(v);
// チェックリスト反映
checkItems.forEach((li) => {
const key = li.dataset.check;
li.classList.toggle("ok", !!checks[key]);
});
// スコア=満たした条件数。空なら0
const score = v.length === 0 ? 0 : Object.values(checks).filter(Boolean).length;
const level = LEVELS[score];
bars.forEach((bar, i) => {
const on = i < score;
bar.classList.toggle("on", on);
bar.style.setProperty("--pw-color", level.color);
});
levelEl.textContent = level.label;
levelEl.style.setProperty("--pw-color", level.color);
}
if (input) input.addEventListener("input", update);
// 表示/非表示トグル
if (toggle && input) {
toggle.addEventListener("click", () => {
const show = input.type === "password";
input.type = show ? "text" : "password";
toggle.textContent = show ? "隠す" : "表示";
});
}
update();
🤖 AIエージェント用プロンプト
このままコピーしてAIに貼り付け「追加する場所」だけ書き換えればOK
あなたは熟練のフロントエンドエンジニアです。私のWebサイトに「パスワード強度メーター」の効果を追加してください。
# 追加してほしい効果
パスワード強度メーター(フォーム & 入力)
文字数・大小文字・数字・記号の条件を判定し、4段階のバーと色で強度を可視化。表示切替や条件チェックリスト付きで会員登録に最適です。
# 追加する場所
👉【ここに対象箇所を記入:例「トップのヒーローセクション」「お問い合わせボタン」「記事カードの一覧」など】
# 参考実装(この見た目・挙動を再現してください)
【HTML】
<div class="stage">
<div class="pw-card">
<h2 class="pw-title">パスワードを設定</h2>
<div class="pw-field">
<input id="pw-input" class="pw-input" type="password" placeholder="パスワードを入力" autocomplete="new-password">
<button id="pw-toggle" class="pw-eye" type="button" aria-label="表示切替">表示</button>
</div>
<!-- 強度バー(4セグメント) -->
<div class="pw-bars" aria-hidden="true">
<span class="pw-bar"></span><span class="pw-bar"></span>
<span class="pw-bar"></span><span class="pw-bar"></span>
</div>
<p class="pw-level" id="pw-level">パスワードを入力してください</p>
<!-- 条件チェックリスト -->
<ul class="pw-checks">
<li data-check="len"><i></i>8文字以上</li>
<li data-check="case"><i></i>大文字と小文字</li>
<li data-check="num"><i></i>数字を含む</li>
<li data-check="sym"><i></i>記号を含む</li>
</ul>
</div>
</div>
【CSS】
* { box-sizing: border-box; }
body {
margin: 0;
min-height: 100vh;
display: grid;
place-items: center;
font-family: "Segoe UI", "Hiragino Kaku Gothic ProN", system-ui, sans-serif;
background: linear-gradient(160deg, #0f172a, #1e1b4b 60%, #312e81);
color: #e5e7eb;
}
.stage { width: 100%; padding: 22px; display: grid; place-items: center; }
.pw-card {
width: min(360px, 92vw);
padding: 26px 24px;
background: rgba(23, 27, 46, 0.92);
border: 1px solid #2e3556;
border-radius: 16px;
box-shadow: 0 24px 56px -24px rgba(0, 0, 0, 0.7);
}
.pw-title { margin: 0 0 16px; font-size: 1.1rem; letter-spacing: 0.04em; }
.pw-field { position: relative; }
.pw-input {
width: 100%;
padding: 12px 64px 12px 14px;
font-size: 1rem;
color: #f1f5f9;
background: #11152a;
border: 1.5px solid #3a4368;
border-radius: 10px;
outline: none;
transition: border-color 0.18s ease, box-shadow 0.18s ease;
}
.pw-input:focus { border-color: #818cf8; box-shadow: 0 0 0 3px rgba(129, 140, 248, 0.22); }
.pw-eye {
position: absolute;
right: 8px; top: 50%;
transform: translateY(-50%);
padding: 5px 9px;
font-size: 0.74rem;
color: #c7d2fe;
background: #2a3157;
border: none;
border-radius: 7px;
cursor: pointer;
}
.pw-eye:hover { background: #353e6e; }
/* 強度バー */
.pw-bars { display: flex; gap: 6px; margin: 16px 0 8px; }
.pw-bar {
flex: 1;
height: 6px;
border-radius: 4px;
background: #2c3454;
transition: background 0.3s ease;
}
/* スコアに応じた点灯色は変数で受け取る */
.pw-bar.on { background: var(--pw-color, #818cf8); }
.pw-level { margin: 0 0 14px; font-size: 0.82rem; color: var(--pw-color, #94a3b8); transition: color 0.3s ease; font-weight: 600; }
/* チェックリスト */
.pw-checks { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.pw-checks li {
display: flex; align-items: center; gap: 9px;
font-size: 0.8rem; color: #8b95b2;
transition: color 0.2s ease;
}
.pw-checks i {
width: 16px; height: 16px; flex: none;
border-radius: 50%;
border: 1.5px solid #4b5578;
position: relative;
transition: background 0.2s ease, border-color 0.2s ease;
}
.pw-checks li.ok { color: #d1fae5; }
.pw-checks li.ok i { background: #34d399; border-color: #34d399; }
/* チェックマーク */
.pw-checks li.ok i::after {
content: "";
position: absolute;
left: 4.5px; top: 1.5px;
width: 4px; height: 8px;
border: solid #0b3b2a;
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
@media (prefers-reduced-motion: reduce) {
.pw-bar, .pw-level, .pw-checks li, .pw-checks i { transition: none; }
}
【JavaScript】
const input = document.getElementById("pw-input");
const toggle = document.getElementById("pw-toggle");
const levelEl = document.getElementById("pw-level");
const bars = [...document.querySelectorAll(".pw-bar")];
const checkItems = [...document.querySelectorAll(".pw-checks li")];
// 強度レベルごとの色とラベル(0〜4)
const LEVELS = [
{ label: "パスワードを入力してください", color: "#94a3b8" },
{ label: "弱い", color: "#f87171" },
{ label: "普通", color: "#fbbf24" },
{ label: "強い", color: "#34d399" },
{ label: "とても強い", color: "#22d3ee" },
];
// 各条件を判定
function evaluate(v) {
return {
len: v.length >= 8,
case: /[a-z]/.test(v) && /[A-Z]/.test(v),
num: /\d/.test(v),
sym: /[^A-Za-z0-9]/.test(v),
};
}
function update() {
if (!input) return;
const v = input.value;
const checks = evaluate(v);
// チェックリスト反映
checkItems.forEach((li) => {
const key = li.dataset.check;
li.classList.toggle("ok", !!checks[key]);
});
// スコア=満たした条件数。空なら0
const score = v.length === 0 ? 0 : Object.values(checks).filter(Boolean).length;
const level = LEVELS[score];
bars.forEach((bar, i) => {
const on = i < score;
bar.classList.toggle("on", on);
bar.style.setProperty("--pw-color", level.color);
});
levelEl.textContent = level.label;
levelEl.style.setProperty("--pw-color", level.color);
}
if (input) input.addEventListener("input", update);
// 表示/非表示トグル
if (toggle && input) {
toggle.addEventListener("click", () => {
const show = input.type === "password";
input.type = show ? "text" : "password";
toggle.textContent = show ? "隠す" : "表示";
});
}
update();
# 外部ライブラリ
なし(追加ライブラリ不要)
# 守ってほしいこと
- 既存のHTML構造・レイアウト・デザインを壊さないこと。必要に応じてクラス名・色・サイズを私のサイトに合わせて調整してよい。
- クラス名やidが既存と衝突しないよう、必要なら接頭辞で名前空間を分けること。
- レスポンシブ対応と prefers-reduced-motion への配慮を入れること。
- 私のサイトのフレームワーク(React / Vue / 素のHTML など)に合わせて実装すること。不明な場合は素のHTML/CSS/JSで提示し、組み込み手順も説明すること。
- 変更後の確認手順も簡潔に教えてください。