About this snippet

Guide users to stronger passwords effortlessly with an interactive tooltip. The security requirements tick off smoothly in real-time as the user types their credentials.

Size
4.4 KB
Uses
HTML, CSS, JavaScript
Loads
Nothing external
Views
212
<div class="form-container">
  <div class="input-group">
    <label>New Password</label>
    <input type="password" id="password-input" class="modern-input" placeholder="Create a strong password">
    
    <div class="validation-tooltip" id="tooltip">
      <h4>Password Requirements</h4>
      <ul class="req-list">
        <li class="req-item" id="req-length"><span class="icon">×</span> At least 8 characters</li>
        <li class="req-item" id="req-upper"><span class="icon">×</span> One uppercase letter</li>
        <li class="req-item" id="req-number"><span class="icon">×</span> One number</li>
        <li class="req-item" id="req-special"><span class="icon">×</span> One special character</li>
      </ul>
    </div>
  </div>
</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";
  margin: 0;
  background: #f8fafc;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}

.form-container {
  width: 100%;
  max-width: 350px;
  background: #ffffff;
  padding: 40px;
  border-radius: 20px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.05);
}

.input-group {
  position: relative;
  display: flex;
  flex-direction: column;
}

.input-group label {
  font-weight: 600;
  color: #334155;
  margin-bottom: 8px;
  font-size: 0.95rem;
}

.modern-input {
  padding: 14px 16px;
  border: 1px solid #cbd5e1;
  border-radius: 12px;
  font-size: 1rem;
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
  font-family: inherit;
}

.modern-input:focus {
  border-color: #3b82f6;
  box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.15);
}

.validation-tooltip {
  position: absolute;
  top: 100%;
  left: 0;
  width: 100%;
  background: #1e293b;
  color: #ffffff;
  padding: 20px;
  border-radius: 12px;
  margin-top: 12px;
  box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-10px);
  transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
  z-index: 10;
}

.modern-input:focus + .validation-tooltip,
.validation-tooltip.active {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}

.validation-tooltip::before {
  content: "";
  position: absolute;
  top: -6px;
  left: 20px;
  border-left: 6px solid transparent;
  border-right: 6px solid transparent;
  border-bottom: 6px solid #1e293b;
}

.validation-tooltip h4 {
  margin: 0 0 12px 0;
  font-size: 0.9rem;
  color: #cbd5e1;
}

.req-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.req-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  color: #94a3b8;
  transition: color 0.3s ease;
}

.req-item .icon {
  display: flex;
  justify-content: center;
  align-items: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: #334155;
  color: #ffffff;
  font-weight: bold;
  font-size: 0.7rem;
  transition: background 0.3s ease;
}

/* Valid State Logic securely applied via classes */
.req-item.valid {
  color: #f8fafc;
}

.req-item.valid .icon {
  background: #10b981;
}
const input = document.getElementById("password-input");

const reqLength = document.getElementById("req-length");
const reqUpper = document.getElementById("req-upper");
const reqNumber = document.getElementById("req-number");
const reqSpecial = document.getElementById("req-special");

function validateItem(element, isValid) {
  if (isValid) {
    element.classList.add("valid");
    element.querySelector(".icon").innerHTML = "✓";
  } else {
    element.classList.remove("valid");
    element.querySelector(".icon").innerHTML = "×";
  }
}

input.addEventListener("input", function() {
  const val = input.value;
  
  validateItem(reqLength, val.length >= 8);
  
  let hasUpper = false;
  let hasNumber = false;
  let hasSpecial = false;
  
  /* Secure string loop avoiding brackets and regex completely */
  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") {
      // Lowercase letter, do nothing
    } else {
      // If it is none of the above, it is a special character
      hasSpecial = true;
    }
  }
  
  validateItem(reqUpper, hasUpper);
  validateItem(reqNumber, hasNumber);
  validateItem(reqSpecial, hasSpecial);
});
Esc
↑↓ moveEnter select

Start from a template

Open an .html file, or HTML, CSS, JS, Markdown, Less or TypeScript files. You can also drop them here. Styles and scripts go into their panes.

Share

Source

Keyboard shortcuts

Save