How to build a password strength meter in React

In today’s tutorial, we will build a password strength meter in React using the zxcvbn password strength estimation library. Read on to get started!

What We’re Building

a password strength meter in react
Our finished password strength meter in React.

Try the live version of our Password Strength Meter in React.

You’ve all seen password strength meters before on app sign-up pages, hovering underneath the password input field. So, what’s their purpose?

A password strength meter’s purpose is to give the user visual feedback as to how strong their password is as they’re typing it out. Password strength meters are a vital aspect in securing your modern web app. Without it, your users will probably use ‘hello123’ as their password, or even worse, ‘password’.

So, let’s get started!

Creating a New React App

As always, let’s create a new React app using Create React App. If you don’t know what this is, head on over to the Create React App Github repository page and follow the instructions for setting up a new React project. Come back here when you have the base app up and running.

It should look something like this:

A new react app creating using Create React App.
A brand-spanking-new React App, created using Create React App.

Installing the ZXCVBN Library

The password strength estimation library, Zxcvbn, takes a single string (the password) and returns an object with a number of useful options related to the strength of that string. Dropbox uses zxcvbn on their web, mobile, and desktop apps.

To pass a string to the zxcvbn library, we can simply do the following:

zxcvbn('hello');

Navigate to the root of your new React project, open a terminal window and run the following command to install zxcvbn.

npm install --save zxcvbn

Once that’s finished installing, open up the codebase in your favorite editor (ours is Atom, hence why we created a list of our best Atom packages for front-end developers)

Creating the Base Password Strength Meter Component

Create a new JavaScript file in our root directory named PasswordStrengthMeter.js. This will be our new React class component.

Remember to use title casing for the file and component name whenever you create a new React component. It’s a standard naming convention in React!

We want our new password strength meter reac component to be a class component, so go ahead and open PasswordStrengthMeter.js and add the following code:

PasswordStrengthMeter.js
import React, { Component } from 'react'; import './PasswordStrengthMeter.css'; class PasswordStrengthMeter extends Component { render() { return ( <div className="password-strength-meter"> I'm a password strength meter </div> ); } } export default PasswordStrengthMeter;

Let’s step through the code above:

  • We’re importing React and the named export ‘Component’ from the react library. This means we can create a React class component.
  • We’re importing the .css file ./PasswordStrengthMeter.css which contains all of our styling for our component.
  • Finally, we’re defining a new class named PasswordStrengthMeter which has one method, render. This is rendering a single div with some text, just to show to us that the component is working.

Save your PasswordStrengthMeter.js, and open up App.js. This is always the example component created for us whenever a fresh Create React App has finished running for the first time.

Inside App.js, import our PasswordStrengthMeter component at the top of the file alongside the other import statements. Finally, insert the <PasswordStrengthMeter /> component tag inside the render method of App.js.

App.js

App.js
import React, { Component } from 'react'; import PasswordStrengthMeter from './PasswordStrengthMeter'; class App extends Component { constructor() { super(); } render() { return ( <div className="App"> <PasswordStrengthMeter /> </div> ); } } export default App;

Save the file, jump back to your browser and your React app should look like this:

A react app containing the words I'm a password strength meter
Our bland looking Password Strength Meter. Don’t worry, it’ll look better soon!

Passing the Password to the Strength Meter Component

Great! We’ve got a ‘working’ component that’s being rendered in our App.js component.

Before we move on, let’s stop and think about how we want to architect the password strength meter react component. I’ve seen other password strength meter libraries that are both an input element AND a password strength meter.

This is a bad approach, for two reasons:

  • You’re creating a dependency between the input field and the strength meter.
  • You’re not making your component flexible. What if we wanted to use another type of input element to enter our password? We couldn’t.

Those two points are similar, but I hope you understand what I’m getting at. Basically, let’s just create the strength meter not the input field.

That means that we need to pass a password string to our PasswordStrengthMeter component for it to know what to run through zxcvbn. We’ll do this using props.

Inside App.js, add an input element and have it so that onChange, it sets the password state property to whatever the value that’s being typed into the input:

App.js
import React, { Component } from 'react'; import PasswordStrengthMeter from './PasswordStrengthMeter'; class App extends Component { constructor() { super(); this.state = { password: '', } } render() { const { password } = this.state; return ( <div className="App"> <div className="meter"> <input autoComplete="off" type="password" onChange={e => this.setState({ password: e.target.value })} /> <PasswordStrengthMeter password={password} /> </div> </div> ); } } export default App;

We do a couple of things above:

  • Give our component state, with a property called ‘password’.
  • Add an input element of type password, and attach an onChange handler to it which sets the state to whatever the value is.
  • Pass the password property from our state to the <PasswordStrengthMeter /> component through a prop called ‘password’.

Getting a Result from ZXCVBN 

Before you save and jump back over to your browser, we need to test that we’re getting the password in our PasswordStrengthMeter component.

I’m a big fan of destructuring props and state. Destructuring allows you to refer to prop and state values without having to write this.props.value or this.state.value every time.

const { value, value2, value3 } = this.props;

const { value } = this.state; 

Add the following code to the render method of PasswordStrengthMeter.js:

PasswordStrengthMeter.js
render() { const { password } = this.props; return ( <div className="password-strength-meter"> <br /> <label className="password-strength-meter-label" > {password} </label> </div> ); }

Save the component, jump over to your browser and you should now see whatever you’re typing into the input element below:

A very simple password strength meter in react with one input field.

This isn’t a great password strength meter. In fact, it’s the opposite of one right now This is where zxcvbn comes in.

In order to evaluate the password coming from the input element, we need to pass our password string prop to the zxcvbn library. This will return an object with a key named ‘score’. Score is an integer between 0 and 4:

result.score # Integer from 0-4 (useful for implementing a strength bar) 0 # too guessable: risky password. (guesses < 10^3) 1 # very guessable: protection from throttled online attacks. (guesses < 10^6) 2 # somewhat guessable: protection from unthrottled online attacks. (guesses < 10^8) 3 # safely unguessable: moderate protection from offline slow-hash scenario. (guesses < 10^10) 4 # very unguessable: strong protection from offline slow-hash scenario. (guesses >= 10^10)

Create a new constant called testedResult and assign it to the value of zxcvbn being passed the password string.

PasswordStrengthMeter.js
... render() { const { password } = this.props; const testedResult = zxcvbn(password); return ( <div className="password-strength-meter"> <label className="password-strength-meter-label" > {password} </label> </div> ); } ...

Adding a Progress Element

We’re almost there, but missing one crucial element: the strength meter itself!

The progress HTML element is the perfect use for this. It takes two attributes: value and max.

Insert a new Progress HTML element above the label and pass testedResult.score into the value attribute, and 4 into the max attribute. We’re passing 4 because that’s the highest value returned from the zxcvbn library, so the progress element will be out of 4.

PasswordStrengthMeter.js
... render() { const { password } = this.props; const testedResult = zxcvbn(password); return ( <div className="password-strength-meter"> <progress value={testedResult.score} max="4" /> <br /> <label className="password-strength-meter-label" > {password} </label> </div> ); } ...

Save the file, jump back to your browser and type a password into the input field. Watch the progress bar fill as you type!

A password strength meter in react, with a progress bar below it.
Our working Password Strength Meter

Adding a Better Label

We’re almost at the finish line. Technically, our Password Strength Meter in React is working, but it could be better. We don’t want to display the actual password that’s being typed. Instead, let’s show a handy label telling the user how strong their password is.

To do this, create a new class method inside the component called createPasswordLabel, that takes a single integer parameter, the score, and returns a string, our interpretation of that score (weak, fair, good, etc)

PasswordStrengthMeter.js
... createPasswordLabel = (result) => { switch (result.score) { case 0: return 'Weak'; case 1: return 'Weak'; case 2: return 'Fair'; case 3: return 'Good'; case 4: return 'Strong'; default: return 'Weak'; } } ...

This makes the Password Strength Meter a little more human-friendly (so we get top marks for UX).

Finally, modify the render method so that we’re calling this new method:

PasswordStrengthMeter.js
render() { const { password } = this.props; const testedResult = zxcvbn(password); return ( <div className="password-strength-meter"> <progress value={testedResult.score} max="4" /> <br /> <label className="password-strength-meter-label" > {password && ( <> <strong>Password strength:</strong> {this.createPasswordLabel(testedResult)} </> )} </label> </div> ); }

Save the component, hop back to your browser, type a password and watch what happens:

a password strength meter in react showing the password strength as a label
A more user-friendly password strength meter

Styling our Password Strength Meter

I’m a big fan of focusing on the user experience when it comes to creating React components. Our Password Strength Meter is good, but adding some color would really improve the user experience.

Let’s change the color of the progress meter by applying a CSS class to the progress element depending on the return value of the createPasswordLabel method.

PasswordStrengthMeter.js
... <progress className={`password-strength-meter-progress strength-${this.createPasswordLabel(testedResult)}`} value={testedResult.score} max="4" /> ...

Save the component, and create a new file in the same directory called PasswordStrengthMeter.css. Add the following CSS to it:

PasswordStrengthMeter.css
.password-strength-meter { text-align: left; } .password-strength-meter-progress { -webkit-appearance: none; appearance: none; width: 250px; height: 8px; } .password-strength-meter-progress::-webkit-progress-bar { background-color: #eee; border-radius: 3px; } .password-strength-meter-label { font-size: 14px; } .password-strength-meter-progress::-webkit-progress-value { border-radius: 2px; background-size: 35px 20px, 100% 100%, 100% 100%; } .strength-Weak::-webkit-progress-value { background-color: #F25F5C; } .strength-Fair::-webkit-progress-value { background-color: #FFE066; } .strength-Good::-webkit-progress-value { background-color: #247BA0; } .strength-Strong::-webkit-progress-value { background-color: #70C1B3; }

Save, jump back to your browser and enter in a password. You’ll now see a colorful, user-friendly password strength meter.

A password strength meter in react showing colors for the password strength and a label.

Wrapping Up

Well, that’s it. I hope you’ve enjoyed following this tutorial to build a password strength meter in react as much as I’ve enjoyed writing it.

The full source code can be found over on the Upmostly Github repository for this project.

As always, leave a comment if you have any questions, issues, or just straight up enjoyed coding this. See you next time!


📬 The Monthly Upmostly Newsletter

One email a month, packed with the latest React tutorials, delivered straight to your inbox.
Zero spam, just great content. Unsubscribe at any time.
James King headshot
👋 Hey, I'm James King
My tutorials help 60,000+ developers learn React and JavaScript every month. If you'd like to receive a friendly email once in a while of all new React tutorials, just pop your email above! I appreciate the support!

💬 Leave a comment

Your email address will not be published. Required fields are marked *

We will never share your email with anyone else.

Comments

Dwayne Charrington says:

Great tutorial guys and gals. I hope you do not mind, but I ported the code in this tutorial to the Aurelia Javascript framework, to show how easy it is to take other frameworks and libraries, and do the same thing in Aurelia.

https://github.com/Vheissu/aurelia-tutorial-merges/tree/master/password-strength-meter

James King says:

Thanks, Dwanye! We don’t mind one bit. Feel free to convert more of our tutorials to the Aurelia framework. I hadn’t heard of it until now, so I’ll go and check it out.

addie says:

Thank you so much. This really helped. How do I make sure symbols and numbers are included in the password?

James King says:

The password field is a text input field. Whatever the user types in it will be sent to the password validator. That means if they type !23#4&5! into the password field, then those symbols and numbers will be set as the password.

Mehrdad says:

thank you for this good tutorial.
there is a question about size of zxcvbn library.
Is it possible to only load zxcvbn on signup component?

James King says:

If you only initialize the library inside of that component, then it’ll only load when that component mounts.

Nimo says:

Great article, thanks