WEBLEB
Home
Editor
Login
Pro
English
English
Français
Español
Português
Deutsch
Italiano
हिंदी
HTML
CSS
JS
Andev Web
Password
Toggle password visibility
Longer than 8 characters
Includes a lowercase letter
Includes an uppercase letter
Includes a number
Includes a special character
.password-rules__meter { display: flex; align-items: center; gap: 0.25rem; max-inline-size: 10rem; } .password-rules__meter > :where(span) { width: 100%; height: 0.25em; background-color: lightgray; border-radius: 360px; transition: background-color 100ms ease-out; } password-rules[data-score="1"] .password-rules__meter :first-child, password-rules[data-score="2"] .password-rules__meter :nth-child(-n + 2), password-rules[data-score="3"] .password-rules__meter :nth-child(-n + 3), password-rules[data-score="4"] .password-rules__meter :nth-child(-n + 4) { background-color: dodgerblue; } password-rules[data-score="5"] .password-rules__meter :nth-child(-n + 5) { background-color: mediumseagreen; } .password-rules__score::before { display: block; counter-reset: score var(--score, 0) total var(--total, 5); content: counter(score) "/" counter(total); font-feature-settings: "tnum"; font-size: 0.8em; } .password-rules__checklist { --flow: 0.3rem; -webkit-padding-start: 1.2em; padding-inline-start: 1.2em; } .password-rules__checklist li { position: relative; list-style-type: circle; } .password-rules__checklist .is-match::before { content: "✅"; position: absolute; top: 0; right: calc(100% + 0.25em); font-size: 0.9em; } .password-input-wrapper { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; } .password-input-wrapper button { display: grid; place-items: center; } .password-input-wrapper button svg:last-of-type { display: none; } .password-input-wrapper button[aria-pressed="true"] { svg:first-of-type { display: none; } svg:last-of-type { display: block; } } /* Base elements */ body { font-family: system-ui, sans-serif; color: CanvasText; background: Canvas; } form { width: min(30rem, 100% - 1rem); margin-inline: auto; margin-block: 4rem; } input { box-sizing: border-box; padding-inline: 0.5rem; width: 100%; border: 1px solid lightgray; border-radius: 0.25rem; box-shadow: 0 2px 6px -4px rgba(0 0 0 / 0.2); } button { all: unset; outline: revert; padding-inline: 1rem; background: linear-gradient(white, whitesmoke); &:active { translate: 0 1px; box-shadow: none; } } :is(input, button) { font: inherit; padding-block: 0.5rem; border: 1px solid lightgray; border-radius: 0.25rem; box-shadow: 0 2px 6px -4px rgba(0 0 0 / 0.2); } /* Utils */ .flow > * + * { -webkit-margin-before: var(--flow, 1rem); margin-block-start: var(--flow, 1rem); } .visually-hidden { clip: rect(0 0 0 0); -webkit-clip-path: inset(50%); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } .input-wrapper { display: grid; gap: 0.4rem; label { justify-self: start; } }
class PasswordRules extends HTMLElement { connectedCallback() { this.input = document.getElementById(this.dataset.inputId); if (!this.input) return; this.rules = []; this.setupRules(); this.input.addEventListener("input", this); } handleEvent(e) { this.score = 0; for (let [index, rule] of this.rules.entries()) { const match = e.target.value.match(rule); if (match) this.score++; this.toggleMatchedRuleClass(index, match); } this.setAttributes("score", this.score); } setAttributes(name, value) { this.dataset[name] = value; this.style.setProperty(`--${name}`, value); } setupRules() { const rules = this.dataset.rules; if (!rules) return; rules.split(this.dataset.separator || ",").forEach((match) => { this.rules.push(new RegExp(match.trim())); }); this.setAttributes("total", this.rules.length); } toggleMatchedRuleClass(index, value) { const el = this.querySelector(`[data-rule-index="${index}"]`); if (!el) return; el.classList.toggle("is-match", value); } } class PasswordToggle extends HTMLElement { connectedCallback() { this.input = document.getElementById(this.dataset.inputId); this.status = document.getElementById(this.dataset.statusId); this.btn = this.querySelector("button"); if (!this.input || !this.btn) return; this.btn.ariaPressed = false; this.btn.ariaLabel = "Show password"; this.btn.setAttribute("aria-controls", this.dataset.inputId); this.btn.addEventListener("click", this); } handleEvent(e) { if (this.input.type === "password") { this.btn.ariaPressed = true; this.btn.ariaLabel = "Hide password"; this.input.type = "text"; if (this.status) this.status.textContent = "Password is showing"; } else { this.btn.ariaPressed = false; this.btn.ariaLabel = "Show password"; this.input.type = "password"; if (this.status) this.status.textContent = "Password is hidden"; } } } customElements.define("password-rules", PasswordRules); customElements.define("password-toggle", PasswordToggle);
Validating your code, please wait...
HTML
CSS
JS
Andev Web
Password
Toggle password visibility
Longer than 8 characters
Includes a lowercase letter
Includes an uppercase letter
Includes a number
Includes a special character
.password-rules__meter { display: flex; align-items: center; gap: 0.25rem; max-inline-size: 10rem; } .password-rules__meter > :where(span) { width: 100%; height: 0.25em; background-color: lightgray; border-radius: 360px; transition: background-color 100ms ease-out; } password-rules[data-score="1"] .password-rules__meter :first-child, password-rules[data-score="2"] .password-rules__meter :nth-child(-n + 2), password-rules[data-score="3"] .password-rules__meter :nth-child(-n + 3), password-rules[data-score="4"] .password-rules__meter :nth-child(-n + 4) { background-color: dodgerblue; } password-rules[data-score="5"] .password-rules__meter :nth-child(-n + 5) { background-color: mediumseagreen; } .password-rules__score::before { display: block; counter-reset: score var(--score, 0) total var(--total, 5); content: counter(score) "/" counter(total); font-feature-settings: "tnum"; font-size: 0.8em; } .password-rules__checklist { --flow: 0.3rem; -webkit-padding-start: 1.2em; padding-inline-start: 1.2em; } .password-rules__checklist li { position: relative; list-style-type: circle; } .password-rules__checklist .is-match::before { content: "✅"; position: absolute; top: 0; right: calc(100% + 0.25em); font-size: 0.9em; } .password-input-wrapper { display: grid; grid-template-columns: 1fr auto; gap: 0.5rem; } .password-input-wrapper button { display: grid; place-items: center; } .password-input-wrapper button svg:last-of-type { display: none; } .password-input-wrapper button[aria-pressed="true"] { svg:first-of-type { display: none; } svg:last-of-type { display: block; } } /* Base elements */ body { font-family: system-ui, sans-serif; color: CanvasText; background: Canvas; } form { width: min(30rem, 100% - 1rem); margin-inline: auto; margin-block: 4rem; } input { box-sizing: border-box; padding-inline: 0.5rem; width: 100%; border: 1px solid lightgray; border-radius: 0.25rem; box-shadow: 0 2px 6px -4px rgba(0 0 0 / 0.2); } button { all: unset; outline: revert; padding-inline: 1rem; background: linear-gradient(white, whitesmoke); &:active { translate: 0 1px; box-shadow: none; } } :is(input, button) { font: inherit; padding-block: 0.5rem; border: 1px solid lightgray; border-radius: 0.25rem; box-shadow: 0 2px 6px -4px rgba(0 0 0 / 0.2); } /* Utils */ .flow > * + * { -webkit-margin-before: var(--flow, 1rem); margin-block-start: var(--flow, 1rem); } .visually-hidden { clip: rect(0 0 0 0); -webkit-clip-path: inset(50%); clip-path: inset(50%); height: 1px; overflow: hidden; position: absolute; white-space: nowrap; width: 1px; } .input-wrapper { display: grid; gap: 0.4rem; label { justify-self: start; } }
class PasswordRules extends HTMLElement { connectedCallback() { this.input = document.getElementById(this.dataset.inputId); if (!this.input) return; this.rules = []; this.setupRules(); this.input.addEventListener("input", this); } handleEvent(e) { this.score = 0; for (let [index, rule] of this.rules.entries()) { const match = e.target.value.match(rule); if (match) this.score++; this.toggleMatchedRuleClass(index, match); } this.setAttributes("score", this.score); } setAttributes(name, value) { this.dataset[name] = value; this.style.setProperty(`--${name}`, value); } setupRules() { const rules = this.dataset.rules; if (!rules) return; rules.split(this.dataset.separator || ",").forEach((match) => { this.rules.push(new RegExp(match.trim())); }); this.setAttributes("total", this.rules.length); } toggleMatchedRuleClass(index, value) { const el = this.querySelector(`[data-rule-index="${index}"]`); if (!el) return; el.classList.toggle("is-match", value); } } class PasswordToggle extends HTMLElement { connectedCallback() { this.input = document.getElementById(this.dataset.inputId); this.status = document.getElementById(this.dataset.statusId); this.btn = this.querySelector("button"); if (!this.input || !this.btn) return; this.btn.ariaPressed = false; this.btn.ariaLabel = "Show password"; this.btn.setAttribute("aria-controls", this.dataset.inputId); this.btn.addEventListener("click", this); } handleEvent(e) { if (this.input.type === "password") { this.btn.ariaPressed = true; this.btn.ariaLabel = "Hide password"; this.input.type = "text"; if (this.status) this.status.textContent = "Password is showing"; } else { this.btn.ariaPressed = false; this.btn.ariaLabel = "Show password"; this.input.type = "password"; if (this.status) this.status.textContent = "Password is hidden"; } } } customElements.define("password-rules", PasswordRules); customElements.define("password-toggle", PasswordToggle);