WEBLEB
Accueil
Éditeur
Chat
Connexion
Pro
Français
English
Français
Español
Règles de mot de passe + bascule des composants Web
2,532
0
Champs et interrupteurs
Andev.web
Suivre
0
Remixer
Ouvrir dans l'éditeur
Plein écran
Discuter
Publiez votre code
0
Recommandé
1 June 2025
Galerie de défilement infini CSS CodePen Home
19 October 2026
Animation de chargement circulaire avec HTML et CSS
29 May 2026
Exemple de lien de bouton HTML
HTML
Copy
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
CSS
Copy
.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; } }
JS
Copy
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);
Comments
0
Log in to join the discussion
…