npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

a11y-password-strength-meter

v1.0.0

Published

Accessible password strength feedback for semantic password fields, built as a vanilla TypeScript plugin.

Readme

A11y Password Strength Meter

Accessible password strength feedback for semantic password fields, built as a vanilla TypeScript plugin.

The package is intentionally small. It provides visual feedback, non-visual feedback, native progress semantics, a requirement checklist, and polite live announcements without a framework, backend service, external password API, password storage, or password-strength dependency.

Installation

npm install a11y-password-strength-meter
pnpm add a11y-password-strength-meter
yarn add a11y-password-strength-meter

Usage

Author a data-root element near the password field, then initialize the meters in the current document. Importing the package does not auto-initialize the plugin.

import { initPasswordStrengthMeters } from "a11y-password-strength-meter";
import "a11y-password-strength-meter/styles.css";

initPasswordStrengthMeters();

CSS

Import the default styles when you want the packaged visual treatment:

import "a11y-password-strength-meter/styles.css";

The plugin styles use the .a11y-password-strength-meter BEM block. Public custom properties are prefixed with --a11y-password-strength-meter-*:

.a11y-password-strength-meter {
  --a11y-password-strength-meter-radius: 999px;
  --a11y-password-strength-meter-gap: 0.5rem;
  --a11y-password-strength-meter-danger: #b3261e;
  --a11y-password-strength-meter-warning: #946200;
  --a11y-password-strength-meter-good: #176b45;
  --a11y-password-strength-meter-strong: #0c492e;
}

The default CSS includes progress states for data-strength="too-weak", weak, fair, strong, and very-strong, visible checklist status text, and reduced-motion safeguards.

HTML Structure

Author the password field, helper text, visible feedback, and requirement checklist in HTML so the page remains understandable before JavaScript runs.

<label for="password">Create password</label>
<input
  id="password"
  name="password"
  type="password"
  autocomplete="new-password"
  aria-describedby="password-help password-strength-feedback"
/>

<p id="password-help">
  Use at least 12 characters with uppercase and lowercase letters, a number,
  and a symbol.
</p>

<div
  data-a11y-password-strength-meter
  data-input-id="password"
  data-feedback-id="password-strength-feedback"
>
  <p id="password-strength-feedback">Password strength: Not rated</p>
  <ul
    class="a11y-password-strength-meter__requirements"
    aria-label="Password requirements"
  >
    <li data-requirement="length" data-met="false">
      <span class="a11y-password-strength-meter__requirement-status">
        Needed
      </span>
      <span class="a11y-password-strength-meter__requirement-text">
        At least 12 characters
      </span>
    </li>
    <li data-requirement="uppercase" data-met="false">
      <span class="a11y-password-strength-meter__requirement-status">
        Needed
      </span>
      <span class="a11y-password-strength-meter__requirement-text">
        Includes an uppercase letter
      </span>
    </li>
    <li data-requirement="lowercase" data-met="false">
      <span class="a11y-password-strength-meter__requirement-status">
        Needed
      </span>
      <span class="a11y-password-strength-meter__requirement-text">
        Includes a lowercase letter
      </span>
    </li>
    <li data-requirement="number" data-met="false">
      <span class="a11y-password-strength-meter__requirement-status">
        Needed
      </span>
      <span class="a11y-password-strength-meter__requirement-text">
        Includes a number
      </span>
    </li>
    <li data-requirement="symbol" data-met="false">
      <span class="a11y-password-strength-meter__requirement-status">
        Needed
      </span>
      <span class="a11y-password-strength-meter__requirement-text">
        Includes a symbol
      </span>
    </li>
  </ul>
</div>

Supported data-requirement values are length, uppercase, lowercase, number, and symbol. For the length requirement, data-length overrides the plugin-level minLength.

API

A11yPasswordStrengthMeter

The plugin class for one [data-a11y-password-strength-meter] root. Instances expose:

  • element: the root element.
  • root: the root element.
  • messages: optional message overrides.
  • update(options?): recalculates the UI from the observed input.
  • destroy(): removes input listeners, cleans plugin-added aria-describedby values, clears initialized state, and dispatches a11y-password-strength-meter:destroy.

createPasswordStrengthMeter(root, options?)

Configures and initializes one root element. Duplicate initialization returns the existing instance.

import { createPasswordStrengthMeter } from "a11y-password-strength-meter";

const meter = document.querySelector("[data-a11y-password-strength-meter]");

if (meter instanceof HTMLElement) {
  createPasswordStrengthMeter(meter, {
    inputId: "password",
    feedbackId: "password-strength-feedback",
    minLength: 12,
    announce: true
  });
}

initPasswordStrengthMeters(options?)

Initializes every [data-a11y-password-strength-meter] root in the current document. In non-browser environments without document, it returns an empty array.

getPasswordStrength(password, options?)

Returns a local, explainable score and requirement state. Password values are not logged, stored, sent over the network, written into attributes, or included in lifecycle event detail.

PASSWORD_STRENGTH_METER_EVENTS

Exports the lifecycle event names:

  • init: a11y-password-strength-meter:init
  • change: a11y-password-strength-meter:change
  • destroy: a11y-password-strength-meter:destroy

Options And Attributes

| Option | Data attribute | Description | | --- | --- | --- | | inputId | data-input-id | ID of the password input the plugin observes. | | feedbackId | data-feedback-id | ID assigned to the visible strength feedback. Defaults to password-strength-feedback. | | minLength | data-min-length | Minimum character count for the length requirement. Defaults to 12. | | announce | data-announce | Set to false to disable polite live announcements. | | messages | localized data-* attributes | Overrides labels, templates, ARIA labels, error messages, or requirement text. |

Localized text can be customized with data attributes such as data-strength-label-fair, data-met-text, data-needed-text, data-strength-template, data-requirements-summary-template, data-live-template, data-progress-label, data-progress-value-template, data-requirements-label, data-input-unconfigured-message, and data-input-missing-message.

Localization Dev Notes

The localized demo in localized.html keeps the same scoring logic and changes only authored text plus message overrides. To achieve another locale, set the page or container lang, translate the label, helper text, feedback paragraph, and requirement text, then override the strength labels, status words, and templates with data-* attributes or the JavaScript messages option.

Keep aria-describedby connected to both helper and feedback text so assistive technologies receive the localized instructions and current strength result.

Events

Lifecycle events bubble and include the plugin instance in detail.instance.

| Event | Detail | | --- | --- | | a11y-password-strength-meter:init | { instance } | | a11y-password-strength-meter:change | { instance, label, metCount, result } | | a11y-password-strength-meter:destroy | { instance } |

Event detail never includes the password value.

Accessibility Notes

  • The password field needs a visible <label>.
  • Helper text and visible strength feedback should be connected with aria-describedby.
  • The plugin renders a native <progress> element with a visible strength label and count text.
  • The polite live region announces only when the strength label changes.
  • Color is never the only state cue; the checklist and visible text remain available.
  • Keyboard behavior uses native form controls and browser defaults.
  • Default CSS respects prefers-reduced-motion.

More detail is available in docs/accessibility-notes.md. Still test with your target browsers and assistive technologies before shipping a production form.

Security Boundaries

This package is local UI guidance only. It does not validate credentials for a backend and it is not a complete security system.

It never intentionally:

  • Stores the password.
  • Sends the password over the network.
  • Logs the password.
  • Writes password values into DOM attributes.
  • Includes password values in lifecycle event detail.

Examples And Demos

Run the local demo app with:

npm run dev

Build the published demo output with:

npm run demo:build

Build the GitHub Pages version with the project-page base path:

GITHUB_PAGES=true npm run demo:build

GitHub Pages Deployment

This repo is configured for GitHub Actions deployment. The workflow builds the Vite demo into demo-dist, adds .nojekyll, and uploads that folder to GitHub Pages.

Repository settings should use:

  • Pages source: GitHub Actions.
  • Branch trigger: main.
  • Expected URL: https://vmitsaras.github.io/a11y-password-strength-meter/.

Docs Metadata

Docs metadata is available as a named export for aggregation in Astro/Starlight or another docs site:

import { docs } from "a11y-password-strength-meter/docs";

Verification

Before release or public sharing, run:

npm run typecheck
npm run test
npm run build
npm run pack:check
npm run demo:build

Manual QA guidance is available in docs/manual-qa-script.md and docs/accessibility-test-scenarios.md.