Form Validation with HTML, CSS & JavaScript
20 DAYS 20 PROJECT CHALLENGE
Day #03
Project Overview
The Form Validation project is a beginner-friendly web application built using HTML, CSS, and JavaScript. It demonstrates how a website can collect information from users and check whether the entered data meets specific requirements before accepting the form.
The project uses the validation principle to ensure that each input field contains the correct data type and is not empty. For instance, the form can collect the user’s name, email, password, and other information. The script checks if the input fields are empty and appends error messages next to them. In addition, JavaScript is used to enable the form to send data successfully and disable it when the input data does not meet the specified requirements.
This project is best for learning and understanding how the website can request data from the user, process the input data, and check if it meets the given conditions.
Key Features
- User Input Fields: The form includes text fields for the user to enter the needed information. Each field may have specific validations depending on their types.
- Required Field Validation: The application checks whether the required fields have information before proceeding to the next stage. It ensures that the user does not leave any empty fields in the form.
- Email Validation: The email field verifies whether the entered email is in the correct format. Thus, the users get notified about their wrong email addresses.
- Password Validation: The password field can check whether the entered password meets the required standards. It ensures that the user does not enter a weak password or one that does not meet the set requirements.
- Error Messages: This also shows error messages if any of the fields do not meet the requirements. Hence, the users know which fields to amend and resubmit the application.
- Real-Time Feedback: The application uses JavaScript to give feedback on the fields. Thus, the users get instant information on what they should do differently.
- Form Submit Handling: The script handles the form submission by validating the information before allowing the process to continue. It ensures that the information is valid and free from errors.
- Clean User Interface: The application uses CSS to design a clean interface for the form, fields, buttons, and messages. It ensures that the form is easy to read and has a good format.
- Responsive Design: The application can respond to smaller viewports by redesigning the layout. Thus, it ensures that the forms are easy to use and designed for mobile devices.
What You’ll Learn
- Understand how HTML creates a form structure.
- Learn how different HTML input types collect user information.
- Practice reading input values with JavaScript.
- Explore how conditions validate user input.
- Learn how to check email and password requirements.
- Understand how JavaScript handles form submission.
- Practice displaying error messages dynamically.
- Explore how DOM manipulation updates form elements.
- Learn how CSS creates a clean and responsive form.
- Understand how HTML, CSS, and JavaScript work together to create interactive forms.
HTML Code
The HTML code creates the basic structure of the Form Validation project. The form contains different input fields where users can enter their information. Each input can use attributes such as type, id, name, placeholder, and required to describe how the field should work.
The form also contains a submit button that allows users to send their information. Separate elements can display validation messages when JavaScript detects an invalid value. Additionally, the HTML file links the CSS stylesheet inside the <head> section. The JavaScript file is loaded near the bottom of the <body> so the script can access the form elements after the page structure loads.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Day 3 — Form Validation</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<main class="card" role="main">
<header>
<div class="logo">FV</div>
<div>
<h1>Day 3: Form Validation</h1>
<p class="lead">Validate signup/login inputs with regex and DOM events. Real-time feedback, password policy, and accessible error messages.</p>
</div>
</header>
<section class="form-wrap">
<form id="signupForm" novalidate>
<div class="field">
<label for="name">Full name<span class="req">*</span></label>
<input id="name" name="name" type="text" autocomplete="name" required />
<div class="error" id="nameError" aria-live="polite"></div>
</div>
<div class="field">
<label for="email">Email<span class="req">*</span></label>
<input id="email" name="email" type="email" autocomplete="email" required />
<div class="error" id="emailError" aria-live="polite"></div>
</div>
<div class="field">
<label for="password">Password<span class="req">*</span></label>
<div class="pw-row">
<input id="password" name="password" type="password" autocomplete="new-password" required />
<button type="button" id="togglePwd" class="tiny-btn" aria-label="Show password">Show</button>
</div>
<div class="small">Minimum 8 chars, include uppercase, lowercase, number, and special character.</div>
<div class="strength" aria-hidden="true"><i id="pwBar"></i></div>
<div class="error" id="passwordError" aria-live="polite"></div>
</div>
<div class="field">
<label for="confirm">Confirm password<span class="req">*</span></label>
<input id="confirm" name="confirm" type="password" autocomplete="new-password" required />
<div class="error" id="confirmError" aria-live="polite"></div>
</div>
<div class="field">
<label for="phone">Phone (optional)</label>
<input id="phone" name="phone" type="tel" inputmode="tel" placeholder="+91 98765 43210" />
<div class="error" id="phoneError" aria-live="polite"></div>
</div>
<div class="field checkbox">
<label><input id="terms" name="terms" type="checkbox" /> I agree to the terms <span class="req">*</span></label>
<div class="error" id="termsError" aria-live="polite"></div>
</div>
<div class="actions">
<button type="submit" id="submitBtn" class="btn">Sign up</button>
<button type="button" id="resetBtn" class="btn secondary">Reset</button>
</div>
<div id="formMessage" class="form-message" role="status" aria-live="polite"></div>
</form>
</section>
<section class="notes">
<details>
<summary>How it works (short)</summary>
<p>The JS attaches input and submit listeners. It uses regex to validate email and password rules, updates inline error messages, updates a visual strength bar, and prevents submission until all checks pass.</p>
</details>
</section>
</main>
<script src="script.js"></script>
</body>
</html>
CSS Code
The CSS code controls the appearance and layout of the Form Validation project. It styles the main form container, labels, input fields, buttons, and validation messages.
The form container uses spacing, padding, borders, and other properties to create a clean interface. Input fields receive consistent widths, padding, and borders so users can enter information comfortably. In addition, CSS can use different styles for error messages and valid input states. A media query can also adjust the form’s width and spacing on smaller screens, making the project more responsive.
:root {
--bg: #0f1724;
--card: #071027;
--accent: #6366f1;
--muted: #9aa4b2;
--danger: #ef4444;
font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, Arial;
}
html,
body {
height: 100%;
}
body {
margin: 0;
background: #002252;
color: #e6eef6;
display: flex;
align-items: center;
justify-content: center;
padding: 28px;
}
.card {
width: min(760px, 96%);
background: linear-gradient(180deg, rgba(255, 255, 255, 0.02), rgba(255, 255, 255, 0.01));
border-radius: 12px;
padding: 20px;
box-shadow: 0 8px 30px rgba(2, 6, 23, 0.6);
border: 1px solid rgba(255, 255, 255, 0.03);
}
header {
display: flex;
gap: 14px;
align-items: center;
}
.logo {
width: 44px;
height: 44px;
border-radius: 10px;
background: linear-gradient(135deg, var(--accent), #22c1c3);
display: flex;
align-items: center;
justify-content: center;
font-weight: 700;
}
h1 {
margin: 0;
font-size: 18px;
}
.lead {
margin: 4px 0 12px;
color: var(--muted);
font-size: 14px;
}
.form-wrap {
margin-top: 16px;
}
form {
display: grid;
gap: 12px;
}
.field {
display: flex;
flex-direction: column;
gap: 6px;
}
.field input[type="text"],
.field input[type="email"],
.field input[type="password"],
.field input[type="tel"] {
padding: 10px 12px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.04);
background: #ffff;
color: black;
outline: none;
}
.field input:focus {
box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.12);
border-color: rgba(99, 102, 241, 0.6);
}
.req {
color: var(--muted);
margin-left: 4px;
}
.error {
color: var(--danger);
font-size: 13px;
min-height: 18px;
}
.small {
font-size: 13px;
color: var(--muted);
}
.pw-row {
display: flex;
gap: 8px;
align-items: center;
}
.tiny-btn {
font-size: 13px;
padding: 8px;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.04);
background: transparent;
color: var(--muted);
cursor: pointer
}
.checkbox label {
display: flex;
align-items: center;
gap: 8px;
color: var(--muted);
}
.actions {
display: flex;
gap: 10px;
margin-top: 6px;
}
.btn {
padding: 10px 14px;
border-radius: 10px;
border: 0;
background: linear-gradient(90deg, var(--accent), #22c1c3);
color: white;
font-weight: 600;
cursor: pointer
}
.btn.secondary {
background: transparent;
border: 1px solid rgba(255, 255, 255, 0.06);
color: var(--muted)
}
.strength {
height: 8px;
border-radius: 6px;
background: rgba(255, 255, 255, 0.03);
overflow: hidden;
margin-top: 6px
}
.strength>i {
display: block;
height: 100%;
width: 0%;
}
.form-message {
margin-top: 8px;
color: var(--muted);
font-size: 14px;
min-height: 20px;
}
@media (max-width:600px) {
.pw-row {
flex-direction: row;
}
.card {
padding: 16px;
}
} Javascript Code
The JavaScript code provides the main validation functionality. First, it selects the form and required input elements from the HTML. An event listener then detects when the user submits the form.
The validation logic checks whether required fields contain values and whether specific inputs follow the expected format. Next, JavaScript displays an error message when a field contains invalid information and prevents the form from continuing until the problem is corrected.
Once all required values pass the validation checks, the code can allow the form submission or display a success message. This project helps beginners understand event listeners, conditions, input values, DOM manipulation, and form validation.
// Regex definitions (simple but effective)
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/i;
const PHONE_RE = /^(?:\+91[\s-]?|0)?[6-9]\d{9}$/;
const PWD_RULES = {
length: { test: pw => pw.length >= 8, msg: 'At least 8 characters' },
lower: { test: pw => /[a-z]/.test(pw), msg: 'Lowercase letter' },
upper: { test: pw => /[A-Z]/.test(pw), msg: 'Uppercase letter' },
number: { test: pw => /[0-9]/.test(pw), msg: 'Number' },
special: { test: pw => /[^A-Za-z0-9]/.test(pw), msg: 'Special character' }
};
// Elements
const form = document.getElementById('signupForm');
const nameInput = document.getElementById('name');
const emailInput = document.getElementById('email');
const passwordInput = document.getElementById('password');
const confirmInput = document.getElementById('confirm');
const phoneInput = document.getElementById('phone');
const termsInput = document.getElementById('terms');
const nameError = document.getElementById('nameError');
const emailError = document.getElementById('emailError');
const passwordError = document.getElementById('passwordError');
const confirmError = document.getElementById('confirmError');
const phoneError = document.getElementById('phoneError');
const termsError = document.getElementById('termsError');
const pwBar = document.getElementById('pwBar');
const formMessage = document.getElementById('formMessage');
const togglePwd = document.getElementById('togglePwd');
const resetBtn = document.getElementById('resetBtn');
// Utilities
function setError(el, msg){
el.textContent = msg || '';
}
function setValidState(input, ok){
if(ok) input.style.borderColor = 'rgba(16,185,129,0.6)'; // green
else input.style.borderColor = 'rgba(239,68,68,0.6)'; // red
}
// Validation functions
function validateName(){
const v = nameInput.value.trim();
if(!v){
setError(nameError,'Please enter your full name.');
setValidState(nameInput, false);
return false;
}
setError(nameError,'');
setValidState(nameInput, true);
return true;
}
function validateEmail(){
const v = emailInput.value.trim();
if(!v){
setError(emailError,'Email is required.');
setValidState(emailInput, false);
return false;
}
if(!EMAIL_RE.test(v)){
setError(emailError,'Enter a valid email address.');
setValidState(emailInput, false);
return false;
}
setError(emailError,'');
setValidState(emailInput, true);
return true;
}
function passwordStrength(pw){
// score 0..100 based on rules and length
let score = 0;
if(PWD_RULES.length.test(pw)) score += 30;
if(PWD_RULES.lower.test(pw)) score += 15;
if(PWD_RULES.upper.test(pw)) score += 15;
if(PWD_RULES.number.test(pw)) score += 20;
if(PWD_RULES.special.test(pw)) score += 20;
return Math.min(100, score);
}
function validatePassword(){
const pw = passwordInput.value;
const fails = Object.values(PWD_RULES).filter(r => !r.test(pw)).map(r => r.msg);
if(!pw){
setError(passwordError,'Password is required.');
setValidState(passwordInput, false);
updateStrength(0);
return false;
}
if(fails.length){
setError(passwordError, 'Missing: ' + fails.join(', '));
setValidState(passwordInput, false);
updateStrength(passwordStrength(pw));
return false;
}
setError(passwordError,'');
setValidState(passwordInput, true);
updateStrength(passwordStrength(pw));
return true;
}
function validateConfirm(){
const pw = passwordInput.value;
const c = confirmInput.value;
if(!c){
setError(confirmError,'Please confirm your password.');
setValidState(confirmInput, false);
return false;
}
if(pw !== c){
setError(confirmError,'Passwords do not match.');
setValidState(confirmInput, false);
return false;
}
setError(confirmError,'');
setValidState(confirmInput, true);
return true;
}
function validatePhone(){
const v = phoneInput.value.trim();
if(!v){
setError(phoneError,'');
phoneInput.style.borderColor = '';
return true; // optional
}
if(!PHONE_RE.test(v)){
setError(phoneError,'Enter a valid phone number.');
setValidState(phoneInput, false);
return false;
}
setError(phoneError,'');
setValidState(phoneInput, true);
return true;
}
function validateTerms(){
if(!termsInput.checked){
setError(termsError,'You must accept the terms.');
return false;
}
setError(termsError,'');
return true;
}
// Strength bar UI
function updateStrength(score){
pwBar.style.width = score + '%';
if(score < 35) pwBar.style.background = '#ef4444';
else if(score < 70) pwBar.style.background = '#f59e0b';
else pwBar.style.background = '#10b981';
}
// Event listeners for live validation
nameInput.addEventListener('input', validateName);
emailInput.addEventListener('input', validateEmail);
passwordInput.addEventListener('input', () => {
validatePassword();
validateConfirm(); // re-check confirmation live
});
confirmInput.addEventListener('input', validateConfirm);
phoneInput.addEventListener('input', validatePhone);
termsInput.addEventListener('change', validateTerms);
// Toggle show/hide password
togglePwd.addEventListener('click', () => {
const type = passwordInput.type === 'password' ? 'text' : 'password';
passwordInput.type = type;
confirmInput.type = type;
togglePwd.textContent = type === 'text' ? 'Hide' : 'Show';
togglePwd.setAttribute('aria-pressed', type === 'text');
});
// Reset
resetBtn.addEventListener('click', () => {
form.reset();
// clear errors & styles
[nameError,emailError,passwordError,confirmError,phoneError,termsError].forEach(e => e.textContent = '');
[nameInput,emailInput,passwordInput,confirmInput,phoneInput].forEach(i => i.style.borderColor = '');
updateStrength(0);
formMessage.textContent = '';
});
// Final submit
form.addEventListener('submit', (ev) => {
ev.preventDefault();
formMessage.textContent = '';
const ok = [
validateName(),
validateEmail(),
validatePassword(),
validateConfirm(),
validatePhone(),
validateTerms()
].every(Boolean);
if(!ok){
formMessage.textContent = 'Please fix the errors above before submitting.';
formMessage.style.color = '#f59e0b';
return;
}
// Simulate successful submission (replace with real registration logic)
formMessage.textContent = 'Success! Form validated — ready to submit to the server.';
formMessage.style.color = '#10b981';
// Optionally collect data
const payload = {
name: nameInput.value.trim(),
email: emailInput.value.trim(),
phone: phoneInput.value.trim() || null
// IMPORTANT: in real apps never send plain password unless over HTTPS and following best practices
};
console.log('Validated payload:', payload);
// Optionally clear sensitive fields
passwordInput.value = '';
confirmInput.value = '';
updateStrength(0);
});
Related Projects
Day 1 : Weather App
Fetch and display real-time weather data for any city using an API.
Concepts: API fetch, async/await, JSON handling.
Day 5 : Digital Piano
Play sound notes when user clicks keys or presses keyboard buttons.
Concepts: Audio API, keyboard events.
Day 6 : Tip Calculator
Calculates tip amount and total per person based on bill and tip %.
Concepts: Form inputs, math logic.