Build Your Own Password Generator Web App with JavaScript

Jaimin PatelJaimin Patel
7 min read

Introduction: In this tutorial, we will guide you through the process of creating a simple yet powerful password generator web application using HTML, CSS, and JavaScript. This interactive web app allows users to customize their passwords based on length and character requirements.

Prerequisites:

  • Basic knowledge of HTML, CSS, and JavaScript.

  • A text editor for coding.

Step 1: HTML Structure

<!DOCTYPE html>
<html lang="en" data-theme="light">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <script>
      let localTheme = localStorage.getItem('PasswordTheme');

     if(localTheme === "dark"){
      document.documentElement.setAttribute('data-theme', "dark");
     }
    </script>


    <link rel="stylesheet" href="./style.css">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
    <title>Password Generator</title>
</head>
<body>
    <section id="container">
        <div id="heading">
          <h1>Password Generator</h1>
          <p id="passwordStrength">passwordStrength</p>
          <p id="passwordStrengthRequired">passwordStrengthRequired</p>
        </div>
        <div id="generationgSection">
            <input type="text" id="showPassword" readonly>
            <div id="copyBtn"><i class="fa-regular fa-copy"></i></div>
        </div>
        <div id="btnSection">
            <div class="range-slider">
                <input class="range-slider__range" type="range" value="1" min="1" max="30" id="passwordGenerateSlides">
                <span class="range-slider__value">0</span>
              </div>
        </div>
        <div id="requementSection">
            <div class="row">
                <label for="lowercase" class="checkbox">
                    <input class="checkbox__input" type="checkbox" id="lowercase">
                    <svg class="checkbox__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
                      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
                      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
                    </svg>
                    <span class="checkbox__label">Lowercase</span>
                  </label>
            </div>
            <div class="row">
                <label for="uppercase" class="checkbox">
                    <input class="checkbox__input" type="checkbox" id="uppercase">
                    <svg class="checkbox__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
                      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
                      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
                    </svg>
                    <span class="checkbox__label">Uppercase</span>
                  </label>
            </div>
            <div class="row">
                <label for="numbers" class="checkbox">
                    <input class="checkbox__input" type="checkbox" id="numbers">
                    <svg class="checkbox__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
                      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
                      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
                    </svg>
                    <span class="checkbox__label">Numbers</span>
                  </label>
            </div>

            <div class="row">
                <label for="symbols" class="checkbox">
                    <input class="checkbox__input" type="checkbox" id="symbols">
                    <svg class="checkbox__icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 22 22">
                      <rect width="21" height="21" x=".5" y=".5" fill="#FFF" stroke="#006F94" rx="3" />
                      <path class="tick" stroke="#6EA340" fill="none" stroke-linecap="round" stroke-width="4" d="M4 10l5 5 9-9" />
                    </svg>
                    <span class="checkbox__label">Symbols</span>
                  </label>
            </div>

        </div>
    </section>
    <div class="copyright"><p>Made With <a href="#">❤️</a> By <a href="https://jaimindev.blogspot.com">Jaimin Patel</a></p></div>
    <button type="button" class="theme" id="modeBtn">
      <span><i class="fa-solid fa-moon"></i></span>
    </button>
</body>
</html>

<script src="./app.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/js/all.min.js" integrity="sha512-GWzVrcGlo0TxTRvz9ttioyYJ+Wwk9Ck0G81D+eO63BaqHaJ3YZX9wuqjwgfcV/MrB2PhaVX9DkYVhbFpStnqpQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

Explanation:

  • The HTML structure defines the layout of your web page. It includes the necessary elements like headings, input fields, checkboxes, and buttons.

Step 2: Styling with CSS

[data-theme="light"] {
  --main-bg-color: #163020;
  --main-text-color: #EEF0E5;
  --accent-color: #304d30;
  --notification-bg: #b6c4b6;
  --error-color: #9A031E;
  --input-text-color: #163020;
  --mode-color: #163020;
}

[data-theme="dark"] {
  --main-bg-color: #07120c;
  --main-text-color: #57b60bc7;
  --accent-color: #3e3a3a;
  --notification-bg: #3e3a3a;
  --error-color: #9A031E;
  --input-text-color: #57b60bc7;
  --mode-color: #57b60bc7;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
  max-height: 100%;
  height: 100vh;
  background-color: var(--main-bg-color);
  color: var(--main-text-color);
  font-family: 'Outfit', sans-serif;
  font-family: 'Roboto', sans-serif;
  transition: all 0.15s ease-in-out;
  position: relative;
}

.notification {
  position: absolute;
  top: 0;
  right: 0;
  padding: 1rem 2rem;
  margin: 1rem;
  background-color: var(--notification-bg);
  border-radius: 5px;
  color: var(--input-text-color);
  font-weight: 800;
  text-transform: capitalize;
  animation: alert-box .5s ease-in-out;
}

.theme{
  position: absolute;
  top: 0;
  left: 0;
  padding: 0.6rem 0.8rem;
  margin: 1rem;
  background-color: var(--notification-bg);
  border-radius: 50%;
  color: var(--mode-color);
  font-weight: 800;
  border: none;
}

@keyframes alert-box {
  0% {
      top: -20%;
  }
  100% {
      top: 0%;
  }
}

label {
  font-weight: 600;
}

#heading {
  text-align: center;
  padding-bottom: 1rem;
  margin-bottom: 1rem;
  font-weight: 600;
  text-transform: capitalize;
}

#heading h1 {
  font-size: 5rem;
}

#generationgSection {
  display: flex;
  background-color: var(--notification-bg);
  border-radius: .5rem;
}

#generationgSection input {
  width: 100%;
  height: 4rem;
  background-color: inherit;
  border-radius: inherit;
  color: var(--input-text-color);
  border: none;
  outline: none;
  padding: 1rem;
  font-size: 1.8rem;
}

#generationgSection div {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1rem;
  font-size: 2rem;
  color: var(--mode-color);
  transition: .3s all ease-in-out;
}

.fa-copy:hover {
  color: var(--main-bg-color);
}

#requementSection {
  display: flex;
  justify-content: space-evenly;
  align-items: center;
  gap: 1rem;
  background-color: var(--accent-color);
  border: 1px solid var(--main-bg-color);
  padding: 1rem;
  border-radius: 2rem;
  width: 70%;
  margin: auto;
}

#btnSection {
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 1rem;
  gap: 1rem;
  margin: 1rem 0;
}

.checkbox {
  cursor: pointer;
  display: flex;
  align-items: center;
}

.checkbox__input {
  position: absolute;
  width: 1.375em;
  height: 1.375em;
  opacity: 0;
  cursor: pointer;
}

.checkbox__input:checked + .checkbox__icon .tick {
  stroke-dashoffset: 0;
}

.checkbox__icon {
  width: 1.375em;
  height: 1.375em;
  flex-shrink: 0;
  overflow: visible;
}

.checkbox__icon .tick {
  stroke-dasharray: 20px;
  stroke-dashoffset: 20px;
  transition: stroke-dashoffset 0.2s ease-out;
}

.checkbox__label { margin-left: 0.5em; }
.range-slider { width: 70%; }

.range-slider__range {
  -webkit-appearance: none;
  width: calc(100% - (73px));
  height: 10px;
  border-radius: 5px;
  background: var(--notification-bg);
  outline: none;
  padding: 0;
  margin: 0;
}

.range-slider__range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent-color);
  cursor: pointer;
  transition: background 0.15s ease-in-out;
}

.range-slider__range::-webkit-slider-thumb:hover {
  background: var(--main-bg-color);
}

.range-slider__range:active::-webkit-slider-thumb { background: #1abc9c; }

.range-slider__range::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: 50%;
  background: #2c3e50;
  cursor: pointer;
  transition: background 0.15s ease-in-out;
}

.range-slider__range::-moz-range-thumb:hover { background: var(--main-bg-color);}

.range-slider__range:active::-moz-range-thumb {
  background: var(--main-bg-color);
}

.range-slider__range:focus::-webkit-slider-thumb {
  box-shadow: 0 0 0 3px var(--main-text-color), 0 0 0 6px var(--main-bg-color);
}

::-moz-range-track {
  background: var(--main-text-color);
  border: 0;
}

input::-moz-focus-inner,
input::-moz-focus-outer {
  border: 0;
}

#passwordStrength,
#passwordStrengthRequired {
  visibility: hidden;
}

#passwordStrengthRequired {
  font-size: 0.7rem;
  color: var(--main-text-color);
  padding: 0.3rem 0.8rem;
  background-color: rgba(171, 47, 47, 0.62);
  width: fit-content;
  border-radius: 1rem;
  margin: auto;
}

.copyright {
  z-index: 1;
  position: absolute;
  color: var(--main-text-color);
  bottom: 1rem;
  font-family: 'Franklin Gothic Medium', 'Arial Narrow', Arial, sans-serif;
  font-weight: 600;
}

.copyright a {
  color: var(--main-text-color);
  text-decoration: none;
  font-weight: 600;
}

Explanation:

  • CSS is used to style the appearance of the web page. It defines the color scheme, layout, and visual elements of your password generator.

Step 3: JavaScript Functionality

const $generator = document.querySelector('#passwordGenerateSlides');
const $lowercase = document.querySelector('#lowercase');
const $uppercase = document.querySelector('#uppercase');
const $numbers = document.querySelector('#numbers');
const $symbols = document.querySelector('#symbols');
const $passwordShow = document.querySelector('#showPassword');
const $sliderLenght = document.querySelector('.range-slider__value');
const $checkboxlabel = document.querySelectorAll('.checkbox__label');
const $copyBtn = document.querySelector('#copyBtn');
const $passwordStrength = document.querySelector('#passwordStrength');
const $passwordStrengthRequired = document.querySelector('#passwordStrengthRequired');
const $modeBtn = document.querySelector('#modeBtn');

const lowerChars = "abcdefghijklmnopqrstuvwxyz";
const upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const allNumbers = "0123456789";
const allSymbols = "~!@#$%^&*"; 

let generatedPassword = ""; // Declare generatedPassword outside the event listener callback

$generator.addEventListener('input', () => {
    let allChar = "";
    allChar += $uppercase.checked ? upperChars : "";
    allChar += $lowercase.checked ? lowerChars : "";
    allChar += $numbers.checked ? allNumbers : "";
    allChar += $symbols.checked ? allSymbols : "";

    if (allChar === "") {
        popModel('Please select at least one option');
        return false;
    }

    const sliderLength = $generator.value;
    $sliderLenght.textContent = sliderLength;

    if (sliderLength <= 2) {
        popModel('Please Add more Characters');
        $passwordShow.value = '';
        return false;
    }

    generatedPassword = ""; 

    let i = 1;
    while (i <= sliderLength) {
        const generatedValue = allChar.charAt(Math.floor(Math.random() * allChar.length));
        generatedPassword += generatedValue;
        i++;
    }

    $passwordShow.value = generatedPassword;

    // Check password requirements
    if (generatedPassword.length > 4) {
        $passwordStrength.textContent = 'too short';
        $passwordStrength.style.visibility = 'visible';
        $passwordStrengthRequired.style.visibility = 'visible';
        $passwordStrength.style.color = 'red';
        checkRequirement();

    } if (generatedPassword.length > 6) {
        $passwordStrength.textContent = 'long enough';
        $passwordStrength.style.color = 'yellow';
    } if (generatedPassword.length > 8) {
        $passwordStrength.textContent = 'Strong';
        $passwordStrength.style.color = 'green';
    } if (generatedPassword.length > 16) {
        $passwordStrength.textContent = 'Very Strong';
        $passwordStrength.style.color = 'green';
    }
});

$copyBtn.addEventListener('click', () => {
    const $copyPassWord = $passwordShow.value;

    if($copyPassWord == ''){
        popModel('Unable to copy password Input is blank');
        return false
    }

    $passwordShow.select();
    navigator.clipboard.writeText($copyPassWord)
        .then(() => {
            popModel('Password Copied');
        })
        .catch(error => {
            console.error(error);
            popModel('Unable to copy password');
        });
});

function checkRequirement() {
    if (generatedPassword.search(/[a-z]/) === -1) {
        $passwordStrengthRequired.textContent = `Password is missing lowercase letter`;
    }
    else if (generatedPassword.search(/[A-Z]/) === -1) {
        $passwordStrengthRequired.textContent = `Password is missing uppercase letter`;
    }
    else if (generatedPassword.search(/[0-9]/) === -1) {
        $passwordStrengthRequired.textContent = `Password is missing number letter`;
    }
    else if (generatedPassword.search(/[!@#$%^&*]/) === -1) {
        $passwordStrengthRequired.textContent = `Password is missing special characters letter`;
    }else{
        $passwordStrengthRequired.style.visibility = 'hidden';
    }
}


function popModel(massage){
   let modal = document.createElement('div');
   modal.classList.add('notification');
   modal.textContent = massage;

   let place =  document.querySelector('#container')
   place.appendChild(modal);

   setTimeout(() => { modal.remove() }, 3000); 
}


// light and Dark
$modeBtn.addEventListener('click', ()=>{
    let modelIcon = document.querySelector('.fa-moon');

    let currentTheme = document.documentElement.getAttribute('data-theme')
    const newTheme = currentTheme === "light" ? "dark" : "light";
    document.documentElement.setAttribute('data-theme', newTheme);

    localStorage.setItem('PasswordTheme', newTheme)
})

Explanation:

  • JavaScript adds interactivity to your password generator. It handles user input, generates passwords based on selected criteria, and provides real-time feedback on password strength.

Key Features:

  1. Password Length Slider:

    • Users can adjust the password length using a slider for a customized experience.
  2. Character Requirements:

    • Checkboxes allow users to specify whether their password should include lowercase letters, uppercase letters, numbers, or symbols.
  3. Real-time Password Generation:

    • As users make selections, the password is dynamically generated and displayed in the input field.
  4. Password Strength Indicator:

    • The application provides feedback on password strength, helping users create secure passwords.
  5. Copy to Clipboard:

    • Users can easily copy the generated password to the clipboard with a single click.
  6. Dark/Light Mode Toggle:

    • The web app supports a dark and light theme, providing users with a personalized visual experience.

🌟 If you find this project helpful or interesting, please consider giving it a star on GitHub! ⭐️

Your support means a lot! 🚀💻

Conclusion:

By following this tutorial, you've built a fully functional password generator web app. Users can now generate strong and secure passwords tailored to their preferences. Feel free to customize the code further or add additional features to enhance the user experience.

Happy coding!

0
Subscribe to my newsletter

Read articles from Jaimin Patel directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jaimin Patel
Jaimin Patel

Hi, I'm Jaimin, a front-end developer with counting years of experience in HTML5, CSS3, JavaScript, and React. I am passionate about creating user-friendly web experiences that look great and drive engagement. In my free time, I enjoy exploring new hiking trails and checking out local coffee shops. Let's work together to bring your web project to life!