<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Form Validation</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
    <link rel="stylesheet" href="./style.css">
</head>

<body>
    <main>
        <div class="container">
            <div class="header">
                <h2>Create an Account</h2>
            </div>
            <form class="form" id="form">
                <div class="form-control">
                    <label for="username">Username</label>
                    <input type="text" id="username" placeholder="Enter your Username">
                    <i class="fa fa-smile-o"></i>
                    <i class="fa fa-frown-o"></i>
                    <p class="errorMessage">Error Message</p>
                </div>

                <div class="form-control">
                    <label for="email">Email</label>
                    <input type="email" id="email" placeholder="Enter your Email">
                    <i class="fa fa-smile-o"></i>
                    <i class="fa fa-frown-o"></i>
                    <p class="errorMessage">Error Message</p>
                </div>

                <div class="form-control">
                    <label for="password">Password</label>
                    <input type="password" id="password" placeholder="Enter your Password">
                    <i class="fa fa-smile-o"></i>
                    <i class="fa fa-frown-o"></i>
                    <p class="errorMessage">Error Message</p>
                </div>

                <div class="form-control">
                    <label for="password2">Confirm Password</label>
                    <input type="password" id="password2" placeholder="Confirm your Password">
                    <i class="fa fa-smile-o"></i>
                    <i class="fa fa-frown-o"></i>
                    <p class="errorMessage">Error Message</p>
                </div>

                <button>Submit</button>
            </form>

            <div class="complete-modal">
                <h2>Successful!</h2>
            </div>

        </div>
    </main>
    <div class="animate-circles">
        <div class="red circle"></div>
        <div class="blue circle"></div>
        <div class="red circle"></div>
        <div class="circle"></div>
        <div class="orange circle"></div>
        <div class="red circle"></div>
        <div class="circle"></div>
        <div class="red circle"></div>
        <div class="blue circle"></div>
        <div class="orange circle"></div>
    </div>
    <script src="./app.js"></script>
</body>

</html>
* {
    box-sizing: border-box;
}

body {
    font-family: Arial, Helvetica, sans-serif;
    margin: 0;
    padding: 0;
    background-color: blueviolet;
}

h2,
p {
    margin: 0;
}

main {
    display: flex;
    justify-content: center;
    align-items: center;
    height: 100vh;
}

.container {
    background-color: #fff;
    padding: 40px 20px;
    border-radius: 5px;
    width: 400px;
    max-width: 100%;
    box-shadow: 0 0 10px 1px rgba(61, 61, 61, 0.19), 0 0 15px 1px rgba(63, 63, 63, 0.23);
}

.container.complete {
    visibility: hidden;
}

.container .header {
    padding-bottom: 20px;
}

h2 {
    font-size: 20px;
}

.form-control {
    margin-bottom: 10px;
    position: relative;
}

.form-control label {
    font-weight: bold;
    font-size: 13px;
}

.form-control input {
    margin-top: 2px;
    display: block;
    width: 100%;
    padding: 10px;
    border-radius: 4px;
    border: 2px solid blueviolet;
    font-family: inherit;
}

.form-control i {
    position: absolute;
    top: 29px;
    right: 10px;
    font-size: 24px;
    visibility: hidden;
}

.form-control input:focus {
    outline: none;
}

.form-control.success input {
    border: 2px solid green;
}

.form-control.success .fa-smile-o {
    color: green;
    visibility: visible;
}


/* Animation code to move form fields */
@keyframes inputMove {
    0% {
        transform: translateX(5px);
    }
    25% {
        transform: translateX(-5px);
    }
    50% {
        transform: translateX(5px);
    }
    75% {
        transform: translateX(-5px);
    }
    100% {
        transform: translateX(0px);
    }
}

/* Adding the animation properties to the error CSS selector */
.form-control.error input {
    border: 2px solid red;
    animation-name: inputMove;
    animation-duration: .5s;
    /* animation-iteration-count: 3; */
}

.form-control.error .fa-frown-o {
    color: red;
    visibility: visible;
}

.container.complete .fa {
    visibility: hidden;
}


/* .container.error {
    animation-name: inputMove;
    animation-duration: .5s;
} */

.form-control .errorMessage {
    visibility: hidden;
    margin: 2px 0 12px 0;
    font-weight: bold;
    font-size: 11px;
}

.form-control.error .errorMessage {
    visibility: visible;
    color: red;
}

button {
    font-family: inherit;
    width: 100%;
    padding: 10px;
    background-color: blueviolet;
    color: #fff;
    font-size: 15px;
    border-radius: 4px;
    border: 2px solid blueviolet;
    cursor: pointer;
    transition: all .5s ease-in-out;
}

button:focus {
    outline: none;
}

button:hover {
    color: blueviolet;
    border: 2px solid blueviolet;
    background: transparent;
}

.complete-modal {
    visibility: hidden;
    position: fixed;
    top: 45%;
    left: 41%;
    background-color: #fff;
    padding: 40px 20px;
    border-radius: 5px;
    width: 300px;
    max-width: 100%;
    box-shadow: 0 0 10px 1px rgba(61, 61, 61, 0.19), 0 0 15px 1px rgba(63, 63, 63, 0.23);
    color: green;
    text-align: center;
}

.container.complete .complete-modal {
    visibility: visible;
}

/* Animation code to move bubbles up */
@keyframes animCircle {
    0% {
        transform: translateY(0);
        opacity: 0;
    }
    50% {
        opacity: 1;
    }
    75% {
        opacity: 1;
    }
    100% {
        transform: translateY(-100vh);
        opacity: 0;
    }
}

.animate-circles {
    width: 100%;
    display: flex;
    justify-content: space-around;
    position: absolute;
    bottom: -10vh;
    z-index: -1;
    visibility: hidden;
}

.animate-circles.complete {
    visibility: visible;
}


.animate-circles div {
    animation: animCircle 7s infinite linear;
}

.animate-circles div:nth-child(1) {
    animation-delay: 5s;
}

.animate-circles div:nth-child(3) {
    animation-delay: 2s;
}

.animate-circles div:nth-child(7) {
    animation-delay: 6s;
}

.animate-circles div:nth-child(5) {
    animation-delay: 4s;
}

.animate-circles div:nth-child(9) {
    animation-delay: 4s;
}

.animate-circles div:nth-child(8) {
    animation-delay: 2s;
}

.animate-circles .circle {
    background-color: lawngreen;
    height: 40px;
    width: 40px;
    border-radius: 50%;
}

.animate-circles .red {
    background-color: red;
    height: 30px;
    width: 30px;
}

.animate-circles .blue {
    background-color: blue;
    height: 20px;
    width: 20px;
}

.animate-circles .orange {
    background-color: orange;
    height: 40px;
    width: 40px;
}
//Assigning DOM elements to variables
const form = document.getElementById('form');
const username = document.getElementById('username');
const email = document.getElementById('email');
const password = document.getElementById('password');
const password2 = document.getElementById('password2');
const container = document.querySelector('.container');
const animateCircles = document.querySelector('.animate-circles');

//Listen for for submission
form.addEventListener('submit', (e) => {  
//prevent default loading when form is submitted
    e.preventDefault();

  // Get values of form fields and assign to new variables
    const usernameValue = username.value;
    const emailValue = email.value;
    const passwordValue = password.value;
    const password2Value = password2.value;
  
  //conditional statements to check if form value is valid ..... If form value is not valid an error function is triggered but if it is valid a success function is triggered

    if (usernameValue === '') {
        errorMessage(username, "Username is empty");
    } else {
        successMessage(username);
    }

    if (emailValue === '') {
        errorMessage(email, "Email is empty");
    } else if (!validateEmail(emailValue)) {
        errorMessage(email, "Email is invalid");
    } else {
        successMessage(email);
    }

    if (passwordValue === '') {
        errorMessage(password, "Password is empty");
    } else {
        successMessage(password);
    }

    if (password2Value === '') {
        errorMessage(password2, "Password is empty");
    } else if (password2Value !== passwordValue) {
        errorMessage(password2, "Both Passwords does not match");
    } else {
        successMessage(password2);
    }

// conditional statement to check if all values are valid so the bubbles can appear
    if (username.parentElement.classList.contains('success') && email.parentElement.classList.contains('success') && password.parentElement.classList.contains('success') && password2.parentElement.classList.contains('success')) {

        container.classList.add('complete');
        animateCircles.classList.add('complete');

    }
});


// function to be triggered if form valu is not valid. This function simply adds the error CSS class and removes that of success if it exists

function errorMessage(value, message) {
    const formControl = value.parentElement;

    if (formControl.classList.contains('success')) {
        formControl.classList.remove('success');
        formControl.classList.add('error');
    } else {
        formControl.classList.add('error');
    }
    formControl.querySelector('.errorMessage').textContent = message;


}

// function to be triggered if form valu is valid. This function simply adds the success CSS class and removes that of error if it exists

function successMessage(value) {
    const formControl = value.parentElement;

    if (formControl.classList.contains('error')) {
        formControl.classList.remove('error');
        formControl.classList.add('success');
    } else {
        formControl.classList.add('success');
    }
}

//This is a simple function to validate the email 

function validateEmail(email) {
    const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    return re.test(String(email).toLowerCase());
}

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.