DEV Community

loading...

Mask and unmask a password input

Ridhwana Khan
Senior Software Engineer at DEV. Passionate about building communities, learning/sharing & software engineering. Always looking to make a difference in this world 🌍
・4 min read

I recently worked on a feature to be able to mask and unmask a password using some vanilla javascript, and I thought I'd share how I did this.

Password Mask

If you want to jump ahead and just see the code without the walkthrough, you can view the code on Codepen.

Step 1:

THE HTML:

Let's put some HTML together for a password field. In most instances that will form as part of a form but in this case I'm just going to go ahead and only show the div for the password.

<div>
  <label>Password</label>
  <div class="password-input-container">
    <span class="eye-container js-password-visibility-toggle">
      <span class="js-eye">
        <svg width="22" height="18" viewBox="0 0 22 18" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M11 0c5.392 0 9.878 3.88 10.819 9-.94 5.12-5.427 9-10.82 9C5.609 18 1.123 14.12.182 9 1.12 3.88 5.608 0 11 0zm0 16a9.005 9.005 0 0 0 8.777-7A9.005 9.005 0 0 0 2.223 9 9.005 9.005 0 0 0 11 16zm0-2.5a4.5 4.5 0 1 1 0-9 4.5 4.5 0 0 1 0 9zm0-2a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z" fill="#64707D"/>
        </svg>
      </span>
      <span class="js-eye-off hidden">
        <svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
          <path d="M16.882 18.297A10.95 10.95 0 0 1 11 20C5.608 20 1.122 16.12.18 11a10.982 10.982 0 0 1 3.34-6.066L.393 1.808 1.807.393l19.799 19.8-1.415 1.414-3.31-3.31zM4.935 6.35A8.965 8.965 0 0 0 2.223 11a9.006 9.006 0 0 0 13.2 5.838l-2.027-2.028A4.5 4.5 0 0 1 7.19 8.604L4.935 6.35zm6.979 6.978-3.242-3.242a2.5 2.5 0 0 0 3.24 3.241l.002.001zm7.893 2.264-1.431-1.43a8.936 8.936 0 0 0 1.4-3.162A9.006 9.006 0 0 0 8.553 4.338L6.974 2.76C8.22 2.27 9.58 2 11 2c5.392 0 9.878 3.88 10.819 9a10.95 10.95 0 0 1-2.012 4.592zm-9.084-9.084a4.5 4.5 0 0 1 4.769 4.77l-4.77-4.77z" fill="#64707D"/>
        </svg>
      </span>  
    </span>
    <input class="js-password" type="password"/>
  </div> 
</div>
Enter fullscreen mode Exit fullscreen mode

The main element to take note of is the password-input-container. It contains two elements:

  • The eye-container with two spans that each contain an SVG (an eye and an eye-off SVG). The eye-off SVG will be hidden by default because the password is masked in its default state.
  • An input field with type password.

I tend to still follow BEM Notation for any classnames that I write. Hence, you will see that some classnames have a JavaScript namespace, and are therefore prepended with js- . This is a verbose indicator that this piece of the DOM has some behaviour acting upon it, and that JavaScript binds onto it to provide that behaviour. Hence, it reduces the risk of someone editing or removing the classname mistakenly without realizing that some javascript code depends on it.

Take note of the js- prepended classnames as this will allow us to bind the correct masking and unmasking behaviour in the JavaScript code.

Step 2:

THE JAVASCRIPT

let visible = false;
const eyeIcon = document.getElementsByClassName('js-eye')[0];
const eyeOffIcon = document.getElementsByClassName('js-eye-off')[0];
const passwordField = document.getElementsByClassName('js-password')[0];
const visibilityToggle = document.getElementsByClassName(
  'js-password-visibility-toggle',
)[0];
visibilityToggle.addEventListener('click', togglePasswordMask);

function togglePasswordMask() {
  visible = !visible;
  togglePasswordType(visible)
  toggleEyeIcons(visible);
}

function togglePasswordType(visible)  {
  const passwordType = visible ? 'text' : 'password';
  passwordField.type = passwordType;
}

function toggleEyeIcons(visible) {
  eyeOffIcon.classList.toggle("hidden", !visible );
  eyeIcon.classList.toggle("hidden", visible );
}
Enter fullscreen mode Exit fullscreen mode

Let's walkthrough the code:

const visibilityToggle = document.getElementsByClassName(
  'js-password-visibility-toggle',
)[0];
visibilityToggle.addEventListener('click', togglePasswordMask);
Enter fullscreen mode Exit fullscreen mode

We first search the DOM for the classname js-password-visibility-toggle. js-password-visibility-toggle is the container that contains the eye icons (one hidden and one not).

We then use add addEventListener to listen for a click on the element. When the user clicks on the element the function togglePasswordMask will be called.

The reason we do not add event listeners on the individual SVG span is because then we'll need to add two eventListeners to the DOM (one for the eye and another for the eye-off) and each of the callbacks will be doing something similar. Instead, we allow the trigger on the container and use a "sort of state" variable to figure out whether we're masking or unmasking.

let visible = false;
function togglePasswordMask() {
  visible = !visible;
  togglePasswordType(visible)
  toggleEyeIcons(visible);
}
Enter fullscreen mode Exit fullscreen mode

The first time that we load the form the password is not visible, hence we set visible to false initially.

Each time we click on the eye icon, we toggle visible to negate its current value using visible = !visible.

When we click we want

a) the password to be revealed, i.e. togglePasswordType, and

b) the icon we clicked on to change - i.e. toggleEyeIcons.

const passwordField = document.getElementsByClassName('js-password')[0];

function togglePasswordType(visible)  {
  const passwordType = visible ? 'text' : 'password';
  passwordField.type = passwordType;
}
Enter fullscreen mode Exit fullscreen mode

togglePasswordType simply sets the input type to text or password depending if we want to mask or unmask the password.

const eyeIcon = document.getElementsByClassName('js-eye')[0];
const eyeOffIcon = document.getElementsByClassName('js-eye-off')[0];

function toggleEyeIcons(visible) {
  eyeOffIcon.classList.toggle("hidden", !visible );
  eyeIcon.classList.toggle("hidden", visible );
}
Enter fullscreen mode Exit fullscreen mode

toggleEyeIcons add and remove the hidden class name depending on whether the password is visible or not.

That wraps it up for the code, I hope that was useful and easy to follow. Feel free to drop comments or questions below. πŸ‘‡πŸ½

Discussion (2)

Collapse
jcubic profile image
Jakub T. Jankiewicz

It's not that simple if you want accessible input. There is great article worth reading by gov.uk
Simple things are complicated: making a show password option

Collapse
ridhwana profile image
Ridhwana Khan Author

Thanks @jcubic this is a such a good read and will be very useful for the next step when I make it accessible before we merge the code!