Create A Modal Component for Sign-in/Sign-Up using JavaScript

Create A Modal Component for Sign-in/Sign-Up using JavaScript

Hello, in this Article, you will learn how to create a landing page with an interactive button component for sign-in/sign-up as modals.

Part of the relevance of modal in web applications is to create less bulky and compacted User interfaces, UI best design principles include flow-neatness i.e creating user interfaces with neat transitions from one section to another, so it is generally a good practice to keep lesser pages if possible, and this can best be done by dynamically creating components that you only use when necessary, and they don’t hold vital information that can impact user experience.

So let’s get started by creating the HTML document, index.html and populate with the following code

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <link rel="stylesheet" href="style.css" />
    <script src="scripts.js"></script>
    <title>Space-Z Modal</title>
  </head>
  <body>
    <nav>
      <div class="logo">
        <p>Modal</p>
      </div>
      <div class="auth">
        <div class="btn" id="loginBtn">Login</div>
        <span>/</span>
        <div class="btn" id="signupBtn">SignUp</div>
      </div>
    </nav>
    <section class="hero">
      <div class="overlay">
        <div class="content">
          <h1 class="">Welcome to the Space Z</h1>
          <p>Build your online community easily and Seamless!</p>
          <div class="container">
            <div class="signal"></div>
            <div class="signal-2"></div>
            <div class="signal-3">
              <div class="box">About us</div>
              <div class="box">Product & Pricing</div>
              <div class="box">Get Started</div>
            </div>
          </div>
        </div>
      </div>
      <div class="modal" id="loginModal">
        <div class="modal-content">
          <span class="close">&times;</span>
          <h2>Sign-in Space-Z</h2>
          <form>
            <input type="text" placeholder="Email address" name="username" />
            <input type="password" placeholder="Password" name="password" />
            <button>Login</button>
            <span>or</span>
            <div class="button" type="button">
              <img
                class="google"
                src="https://cdn1.iconfinder.com/data/icons/google-s-logo/150/Google_Icons-09-1024.png"
                alt=""
              />Sign-in with Google
            </div>
            <div class="alt">
              Forgot Password? Click to change<span id="loginBtn"
                >Password</span
              >
            </div>
          </form>
        </div>
      </div>

      <div class="modal" id="signupModal">
        <div class="modal-content">
          <span class="close">&times;</span>
          <h2>Sign-up Space-Z</h2>
          <form>
            <input type="email" placeholder="Enter your Email Address" />
            <button type="submit">Sign-up Free</button>
            <span>or</span>
            <div class="button" type="button">
              <img
                class="google"
                src="https://cdn1.iconfinder.com/data/icons/google-s-logo/150/Google_Icons-09-1024.png"
                alt=""
              />Signup with Google
            </div>
            <div class="alt">
              Already Registered?<span id="loginBtn">Login</span>
            </div>
          </form>
        </div>
      </div>
    </section>
  </body>
</html>

So, the HTML file above contains our raw HTML file, if you preview it, it's going to be just an ugly statically rendered document without styling. To make it look beautiful, I will go ahead to add the styles.

/*add-google-font*/
@import url("https://fonts.googleapis.com/css2?family=Cabin:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&display=swap");

* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
}
body {
  font-family: "Cabin", sans-serif;
}
nav {
  width: 90%;
  height: 80px;
  margin: auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
}
nav .logo p {
  font-size: 30px;
  font-weight: 600;
  text-decoration: underline;
}
nav .auth {
  display: flex;
}
.auth .btn {
  margin-left: 4px;
  margin-right: 4px;
  cursor: pointer;
}
.hero {
  height: 90vh;
  width: 100vw;
  position: relative;
  background-size: cover;
  background-position: 50% 50%;
  background-image: url("https://images.unsplash.com/photo-1581291518857-4e27b48ff24e?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8MTl8fGJ1aWxkJTIwd2VifGVufDB8fDB8fA%3D%3D&auto=format&fit=crop&w=800&q=60");
}
.hero .content {
  width: 60%;
  margin: auto;
}
.content a {
  width: auto;
  text-decoration: none;
  font-size: 18px;
  border: 2px solid black;
  border-radius: 6px;
  padding: 4px 16px;
  color: gainsboro;
  margin-top: 30px;
}
.content h1 {
  font-size: 80px;
}
.content p {
  padding-bottom: 20px;
}
.content .container {
  display: flex;
  align-items: center;
  padding-top: 2;
  margin-top: 6px;
  z-index: 30;
}
.content .container .signal {
  border-bottom: 10px solid rgba(0, 0, 0, 0.496);
  position: absolute;
  width: 500px;
}
.content .container .signal-3 {
  z-index: 20;
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 30px;
}
.content .container .signal-3 .box {
  width: auto;
  padding: 5px 20px;
  border: 1px solid gray;
  border-radius: 6px;
  cursor: pointer;
}
.content .container .signal-3 .box:hover {
  background-color: rgba(128, 128, 128, 0.507);
  color: black;
}
.content .container .signal-2 {
  border-right: 20px solid black;
}
.overlay {
  position: absolute;
  height: 100%;
  width: 100%;
  top: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.65);
  color: white;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}
.modal {
  display: none;
  position: fixed;
  z-index: 1000;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  overflow: auto;
  background-color: rgba(0, 0, 0, 0.4);
}
.modal-content {
  background-color: white;
  margin: 15% auto;
  height: 60%;
  padding: 20px;
  border: 0px solid #888;
  border-radius: 2px;
  width: 30%;
  display: flex;
  flex-direction: column;
  justify-items: center;
  align-items: center;
}
.modal-content form {
  display: flex;
  margin-top: 20px;
  flex-direction: column;
  row-gap: 10px;
  width: 100%;
  justify-content: center;
  align-items: center;
}
.modal-content form input {
  width: 90%;
  padding: 10px 4px;
  outline: none;
  border: 1.5px solid #aaaaaa;
  transition: all;
  border-radius: 6px;
  color: gray;
}
.modal-content form input:focus {
  border: 1px solid black;
  color: black;
  transition: 0.6s ease-in;
}
.modal-content form button {
  background-color: #ff9800;
  cursor: pointer;
  width: 90%;
  padding: 10px 4px;
  outline: none;
  border: 0px solid #aaaaaa;
  transition: all;
  border-radius: 6px;
}
.modal-content form .button {
  width: 90%;
  padding: 10px 4px;
  outline: none;
  border: 1.5px solid #aaaaaa;
  transition: all;
  border-radius: 6px;
  color: gray;
  font-size: 16px;
  cursor: pointer;
  display: flex;
  justify-content: center;
  align-items: center;
}
.modal-content h2 {
  margin-top: 10px;
}
.modal-content .alt {
  margin-top: 10px;
  font-size: 14px;
}
.modal-content .alt span {
  text-decoration: underline;
  margin-left: 4px;
  cursor: pointer;
}
.close {
  width: 100%;
  color: #aaaaaa;
  float: right;
  font-size: 28px;
  font-weight: bold;
  display: flex;
  justify-content: end;
  right: 0;
  align-items: end;
}
form .google {
  width: 25px;
}
.close:hover,
.close:focus {
  color: #000;
  text-decoration: none;
  cursor: pointer;
}
/*mobile-responsive*/
@media screen and (max-width: 768px) {
  body {
    height: 100vh;
  }
  nav {
    height: 60px;
  }
  .hero {
    width: 100%;
    overflow: hidden;
  }
  .hero .content {
    width: 100%;
    padding: 20px;
  }
  .content h1 {
    font-size: 40px;
  }
  .content .container .signal-3 .box {
    font-size: 14px;
    padding: 10px 10px;
  }
  .modal {
    position: absolute;
  }
  .modal-content {
    width: 96%;
    height: 70vh;
    margin-top: 20px;
  }
  .content .container .signal-3 {
    gap: 10px;
  }
  .modal-content form input {
    width: 100%;
  }
  .modal-content form button {
    width: 100%;
  }
  .modal-content form .button {
    width: 100%;
  }
}

Here is the magic of the whole code, the JavaScript. JavaScript enables us to dynamically render static pages, enhancing the UI and improving User experience.

window.onload = function() {
  const loginModal = document.getElementById("loginModal");
  const signupModal = document.getElementById("signupModal");
  const loginBtn = document.getElementById("loginBtn");
  const signupBtn = document.getElementById("signupBtn");
  const loginClose = document.querySelector("#loginModal .close");
  const signupClose = document.querySelector("#signupModal .close");
  // Show login modal on click
  loginBtn.onclick = function() {
    loginModal.style.display = "block";
  }
  // Show signup modal on click
  signupBtn.onclick = function() {
    signupModal.style.display = "block";
  }
  // Close login modal on click of close button
  loginClose.onclick = function() {
    loginModal.style.display = "none";
  }
  // Close signup modal on click of close button
  signupClose.onclick = function() {
    signupModal.style.display = "none";
  }
  // Close login and signup modals on click outside the modal
  window.onclick = function(event) {
    if (event.target == loginModal) {
      loginModal.style.display = "none";
    }
    if (event.target == signupModal) {
      signupModal.style.display = "none";
    }
  }
}

What is simply done here is mapping the JavaScript function via the ID tag given to the clickable elements in the index.html. The window.onload function ensures that the JavaScript code can only run after our HTML is fully rendered, this is to prevent JavaScript runtime errors. Here is my final output https://spacez-z.netlify.app/

If you enjoyed this article, please like and share.