Password Strength Meter
In order to keep malicious hackers away from your site, you might want to heighten the security of your users’ accounts by forcing a certain password policy upon your users. For this, the Password Strength Meter pattern is a great visual way to communicate how strong a password is.
In the following, you will be guided along the way of creating such a password meter for your own website using HTML, CSS and javascript. The version we will create in this guide will not protect against dictionary attacks.
First off, we’ll define what makes a strong password. Consider each of the following criteria filled as the strongest password and only few of them filled as a weaker password:- Password has more than 8 characters
- Password contains both small and uppercase letters
- Password contains at least one numerical character
- Password contains special characters
- Password has more than 12 characters
In our password meter, we are going to have 6 categories of a strong password: Very weak, weak, better, fair, strong, strongest. If all of the above criteria has been met, we have a “strongest” password, if none have been met we have a “Very weak” password, and if for instance 2 of the above criteria have been met, we have a “medium” strong password. In other words, we’ll award 1 point for each of the above criteria that has been met. 5 points gives a strong password and 0 points gives a very weak password.
The validity of this model can be argued why you might want to define your own model of what makes a good password – you might for instance want to force a certain length or make a servercall to a dictionary to check for real words. Nevertheless, the model serves as great means of education.
.h3 The password meter
We will start out by defining our password input field in HTML as well as the horizontal bar that will make the password strength meter. I have chosen to create the horizontal password meter with a table instead of a <div>, as it renders more consistently for our purpose across browsers regardless of us having content inside the box we’re defining. We’re interested in showing the background color of the meter box and not so much the text inside the meter box.
Our HTML will look like this:
<label for="password">Password:</label><br />
<input type="password" id="password">
<table id="password_bar" cellspacing="0" cellpadding="0" class="strength_0">
<tr>
<td colspan="2" id="password_strength_label">Too short</td>
</tr>
<tr>
<td id="positive_bar"></td>
<td id="negative_bar"></td>
</tr>
</table>
The first two lines are pretty self-explanatory: a password input field and a label for that field. The table HTML however has a two of old-school attributes (cellspacing and cellpadding). I have included these as some browsers have wished not to follow CSS rules that strictly.
You might also have notices that the only element with a CSS class defined is the <table> element. The class given here will through a set of CSS rules define the color and length of the password meter. By defining it on the <table> element and not the <td> (table cell), we can ease the javascript pain by only having to change the CSS class of one element instead of all the relevant table cells, which actually are the points of interest.
I have also created a table cell to act as a label for the current password strength. I have given it the id password_strength_label and entered an initial value – “Too short”.
input {
width: 300px;
}
table#password_bar {
width: 300px;
border-collapse: collapse;
}
#password_bar #negative_bar {height: 10px;}
#password_bar.strength_0 #positive_bar {width: 0px;}
#password_bar.strength_1 #positive_bar {width: 20%; background: #a71528;}
#password_bar.strength_2 #positive_bar {width: 40%; background: #fec72d;}
#password_bar.strength_3 #positive_bar {width: 60%; background: #6b9fd6;}
#password_bar.strength_4 #positive_bar {width: 80%; background: #17d114;}
#password_bar.strength_5 #positive_bar {width: 100%; background: #038001;}
#password_bar #negative_bar {background: #ddd;}
#password_bar.strength_0 #negative_bar {width: 100%;}
#password_bar.strength_1 #negative_bar {width: 80%;}
#password_bar.strength_2 #negative_bar {width: 60%;}
#password_bar.strength_3 #negative_bar {width: 40%;}
#password_bar.strength_4 #negative_bar {width: 20%;}
#password_bar.strength_5 #negative_bar {width: 0px;}
#password_bar #password_strength_label {text-align: right;}
#password_bar.strength_0 #password_strength_label {color: #ddd;}
#password_bar.strength_1 #password_strength_label {color: #a71528;}
#password_bar.strength_2 #password_strength_label {color: #fec72d;}
#password_bar.strength_3 #password_strength_label {color: #6b9fd6;}
#password_bar.strength_4 #password_strength_label {color: #17d114;}
#password_bar.strength_5 #password_strength_label {color: #038001;}
Now – let’s look at the javascript:
function updatePasswordMeter(password) {
var strength_descriptions = new Array();
strength_descriptions[0] = 'Very weak';
strength_descriptions[1] = 'Weak';
strength_descriptions[2] = 'Better';
strength_descriptions[3] = 'Fair';
strength_descriptions[4] = 'Strong';
strength_descriptions[5] = 'Very strong';
var strength = calculatePasswordStrength(password);
document.getElementById('password_strength_label').innerHTML = strength_descriptions[strength];
document.getElementById('password_bar').className = 'strength_' + strength;
}
function calculatePasswordStrength(password) {
var score = 0;
// Length at least 8 chars long
if (password.length >= 8)
score++;
// both lower and uppercase chars
if (password.match(/[a-z]/) && password.match(/[A-Z]/))
score++;
// at least one num char
if (password.match(/[0-9]+/))
score++;
// at least one special char
if (password.match(/.[!,@,#,$,%,^,&,*,?,_,~,-,(,)-]/))
score++;
// Length at least 12 chars long
if (password.length >= 12)
score++;
return score;
}
Finally, we want to add an event to the password field in order to change the meter value as the user types his or her password. onkeyup will do the trick. The password input field now looks like this:
<input type="password" id="password" onkeyup="updatePasswordMeter(this.value);">And – tadaaaa… here it is:
| Too short | |
The code in its entirety looks like this:
<script type="text/javascript">
function updatePasswordMeter(password) {
var strength_descriptions = new Array();
strength_descriptions[0] = 'Very weak';
strength_descriptions[1] = 'Weak';
strength_descriptions[2] = 'Better';
strength_descriptions[3] = 'Fair';
strength_descriptions[4] = 'Strong';
strength_descriptions[5] = 'Very strong';
var strength = calculatePasswordStrength(password);
document.getElementById('password_strength_label').innerHTML = strength_descriptions[strength];
document.getElementById('password_bar').className = 'strength_' + strength;
}
function calculatePasswordStrength(password) {
var score = 0;
// Length at least 8 chars long
if (password.length >= 8)
score++;
// both lower and uppercase chars
if (password.match(/[a-z]/) && password.match(/[A-Z]/))
score++;
// at least one num char
if (password.match(/[0-9]+/))
score++;
// at least one special char
if (password.match(/.[!,@,#,$,%,^,&,*,?,_,~,-,(,)-]/))
score++;
// Length at least 12 chars long
if (password.length >= 12)
score++;
return score;
}
</script>
<style><!--
input {
width: 300px;
}
table#password_bar {
width: 300px;
border-collapse: collapse;
}
#password_bar #negative_bar {height: 10px;}
#password_bar.strength_0 #positive_bar {width: 0px;}
#password_bar.strength_1 #positive_bar {width: 20%; background: #a71528;}
#password_bar.strength_2 #positive_bar {width: 40%; background: #fec72d;}
#password_bar.strength_3 #positive_bar {width: 60%; background: #6b9fd6;}
#password_bar.strength_4 #positive_bar {width: 80%; background: #17d114;}
#password_bar.strength_5 #positive_bar {width: 100%; background: #038001;}
#password_bar #negative_bar {background: #ddd;}
#password_bar.strength_0 #negative_bar {width: 100%;}
#password_bar.strength_1 #negative_bar {width: 80%;}
#password_bar.strength_2 #negative_bar {width: 60%;}
#password_bar.strength_3 #negative_bar {width: 40%;}
#password_bar.strength_4 #negative_bar {width: 20%;}
#password_bar.strength_5 #negative_bar {width: 0px;}
#password_bar #password_strength_label {text-align: right;}
#password_bar.strength_0 #password_strength_label {color: #ddd;}
#password_bar.strength_1 #password_strength_label {color: #a71528;}
#password_bar.strength_2 #password_strength_label {color: #fec72d;}
#password_bar.strength_3 #password_strength_label {color: #6b9fd6;}
#password_bar.strength_4 #password_strength_label {color: #17d114;}
#password_bar.strength_5 #password_strength_label {color: #038001;}
--></style>
<label for="password">Password:</label><br />
<input type="password" id="password" onkeyup="updatePasswordMeter(this.value);">
<table id="password_bar" cellspacing="0" cellpadding="0" border="0" class="strength_0">
<tr>
<td colspan="2" id="password_strength_label">Too short</td>
</tr>
<tr>
<td id="positive_bar"></td>
<td id="negative_bar"></td>
</tr>
</table>
This document was last updated at January 29, 2008
