<div class="password-group">
<label for="pwd-input">Create Password</label>
<div class="input-wrapper">
<input type="password" id="pwd-input" placeholder="Enter a strong password">
<div class="strength-ring">
<svg viewBox="0 0 36 36" width="24" height="24">
<path class="ring-bg" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" fill="none" stroke="#e5e7eb" stroke-width="4" />
<path class="ring-progress" id="ring-progress" d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831" fill="none" stroke="#ef4444" stroke-width="4" stroke-dasharray="100, 100" stroke-dashoffset="100" />
</svg>
</div>
</div>
<p class="hint">Use at least 8 characters, numbers, and symbols.</p>
</div>
*, *::before, *::after {
box-sizing: border-box;
}
body {
font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
background: #f9fafb;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
padding: 20px;
}
.password-group {
background: #ffffff;
padding: 30px;
border-radius: 16px;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
width: 100%;
max-width: 400px;
border: 1px solid #f3f4f6;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 500;
color: #374151;
}
.input-wrapper {
position: relative;
display: flex;
align-items: center;
}
#pwd-input {
width: 100%;
padding: 12px 48px 12px 16px;
border: 1px solid #d1d5db;
border-radius: 8px;
outline: none;
transition: border-color 0.2s;
font-size: 1rem;
color: #111827;
}
#pwd-input:focus {
border-color: #3b82f6;
}
.strength-ring {
position: absolute;
right: 12px;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
}
.ring-progress {
transition: stroke-dashoffset 0.4s ease, stroke 0.4s ease;
}
.hint {
font-size: 0.875rem;
color: #6b7280;
margin-top: 12px;
margin-bottom: 0;
}
const input = document.getElementById("pwd-input");
const ring = document.getElementById("ring-progress");
input.addEventListener("input", () => {
const val = input.value;
let score = 0;
// 1. Point for length
if (val.length > 7) {
score++;
}
let hasUpper = false;
let hasNumber = false;
let hasSpecial = false;
// 2. Loop through and look at every single character using charAt()
for (let i = 0; i < val.length; i++) {
const char = val.charAt(i);
if (char >= 'A' && char <= 'Z') {
hasUpper = true;
} else if (char >= '0' && char <= '9') {
hasNumber = true;
} else if (char >= 'a' && char <= 'z') {
// It is a lowercase letter, so we just continue
} else {
// If it is not uppercase, not a number, and not lowercase, it must be a special character
hasSpecial = true;
}
}
// 3. Add points based on what we found
if (hasUpper) score++;
if (hasNumber) score++;
if (hasSpecial) score++;
// 4. Update the visual ring
let offset = 100;
let color = "#ef4444";
if (score === 1) {
offset = 75;
color = "#ef4444";
} else if (score === 2) {
offset = 50;
color = "#f59e0b";
} else if (score === 3) {
offset = 25;
color = "#3b82f6";
} else if (score >= 4) {
offset = 0;
color = "#10b981"; // Green!
}
// Reset if input is empty
if (val.length === 0) {
offset = 100;
}
ring.style.strokeDashoffset = offset;
ring.style.stroke = color;
});