Building a Student Login & Profile System with HTML, CSS, and JavaScript
Live Demo |
In this tutorial, I'll walk you through creating a complete student login and profile system using HTML, CSS, JavaScript, and Tailwind CSS. This system features user registration, login, profile viewing, and editing capabilities - all stored in the browser's localStorage.
Overview of Our Project
We'll build a responsive web application with four main components:
-
Login Page: For existing users to sign in
-
Registration Page: For new users to create accounts
-
Profile Page: To display student information
-
Edit Profile Page: To modify student details
All user data will be stored in the browser's localStorage, making this a perfect solution for simple applications that don't require a backend server.
Step 1: Setting Up the HTML Structure
First, let's create our HTML file with all the necessary containers:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Student Login & Profile</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap" rel="stylesheet">
<style>
/* Custom styles will go here */
</style>
</head>
<body class="flex items-center justify-center p-4">
<div id="app" class="w-full max-w-md">
<!-- Login Form -->
<div id="login-container" class="card rounded-xl p-8">
<!-- Login form content -->
</div>
<!-- Registration Form -->
<div id="register-container" class="card rounded-xl p-8 hidden">
<!-- Registration form content -->
</div>
<!-- Profile Page -->
<div id="profile-container" class="card rounded-xl p-8 hidden">
<!-- Profile content -->
</div>
<!-- Edit Profile Form -->
<div id="edit-profile-container" class="card rounded-xl p-8 hidden">
<!-- Edit profile form -->
</div>
</div>
<script src="script.js"></script>
</body>
</html>
Step 2: Creating the Login Form
Let's build our login form with email and password fields:
<div id="login-container" class="card rounded-xl p-8">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Student Login</h1>
<p class="text-gray-600">Access your profile and dashboard</p>
</div>
<form id="login-form" class="space-y-6">
<div>
<label for="login-email" class="block text-sm font-medium text-gray-700 mb-1">Email</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-envelope text-gray-400"></i>
</div>
<input type="email" id="login-email" required
class="pl-10 w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition"
placeholder="student@example.com">
</div>
</div>
<div>
<label for="login-password" class="block text-sm font-medium text-gray-700 mb-1">Password</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-lock text-gray-400"></i>
</div>
<input type="password" id="login-password" required
class="pl-10 w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition"
placeholder="••••••••">
</div>
</div>
<div class="flex items-center justify-between">
<div class="flex items-center">
<input id="remember-me" type="checkbox" class="h-4 w-4 text-blue-600 focus:ring-blue-500 border-gray-300 rounded">
<label for="remember-me" class="ml-2 block text-sm text-gray-700">Remember me</label>
</div>
<a href="#" id="forgot-password" class="text-sm text-blue-600 hover:text-blue-500">Forgot password?</a>
</div>
<button type="submit" class="w-full bg-gradient-to-r from-blue-500 to-blue-600 text-white py-3 px-4 rounded-lg font-medium hover:from-blue-600 hover:to-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-all duration-300 shadow-md">
Sign In
</button>
<div class="text-center text-sm text-gray-600">
Don't have an account? <a href="#" id="show-register" class="text-blue-600 hover:text-blue-500 font-medium">Sign up</a>
</div>
</form>
</div>
Step 3: Building the Registration Form
Next, we'll create the registration form for new students:
<div id="register-container" class="card rounded-xl p-8 hidden">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Student Registration</h1>
<p class="text-gray-600">Create your student profile</p>
</div>
<form id="register-form" class="space-y-6">
<div>
<label for="register-name" class="block text-sm font-medium text-gray-700 mb-1">Full Name</label>
<div class="relative">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<i class="fas fa-user text-gray-400"></i>
</div>
<input type="text" id="register-name" required
class="pl-10 w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition"
placeholder="John Doe">
</div>
</div>
<!-- Similar structure for email, student ID, password, and confirm password fields -->
<button type="submit" class="w-full bg-gradient-to-r from-green-500 to-green-600 text-white py-3 px-4 rounded-lg font-medium hover:from-green-600 hover:to-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2 transition-all duration-300 shadow-md">
Register
</button>
<div class="text-center text-sm text-gray-600">
Already have an account? <a href="#" id="show-login" class="text-blue-600 hover:text-blue-500 font-medium">Sign in</a>
</div>
</form>
</div>
Step 4: Designing the Profile Page
Now, let's create the profile display page:
<div id="profile-container" class="card rounded-xl p-8 hidden">
<div class="text-center mb-8">
<div class="w-24 h-24 rounded-full bg-gradient-to-r from-blue-500 to-purple-500 mx-auto mb-4 flex items-center justify-center text-white text-4xl font-bold" id="profile-avatar">
JD
</div>
<h1 class="text-3xl font-bold text-gray-800 mb-1" id="profile-name">John Doe</h1>
<p class="text-gray-600" id="profile-email">john.doe@example.com</p>
<p class="text-sm text-gray-500 mt-2" id="profile-id">Student ID: STU12345</p>
</div>
<div class="space-y-6">
<div class="bg-gray-50 p-4 rounded-lg">
<h3 class="text-lg font-medium text-gray-800 mb-2">Personal Information</h3>
<div class="grid grid-cols-2 gap-4">
<div>
<p class="text-sm text-gray-500">Course</p>
<p class="font-medium" id="profile-course">Computer Science</p>
</div>
<!-- Similar structure for year, semester, GPA -->
</div>
</div>
<div class="flex justify-between pt-4">
<button id="edit-profile" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition">
Edit Profile
</button>
<button id="logout" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition">
Logout
</button>
</div>
</div>
</div>
Step 5: Implementing the Edit Profile Form
Finally, let's create the form to edit profile information:
<div id="edit-profile-container" class="card rounded-xl p-8 hidden">
<div class="text-center mb-8">
<h1 class="text-3xl font-bold text-gray-800 mb-2">Edit Profile</h1>
<p class="text-gray-600">Update your student information</p>
</div>
<form id="edit-profile-form" class="space-y-6">
<div>
<label for="edit-name" class="block text-sm font-medium text-gray-700 mb-1">Full Name</label>
<input type="text" id="edit-name" required
class="w-full px-4 py-3 rounded-lg border border-gray-300 focus:ring-2 focus:ring-blue-500 focus:border-blue-500 outline-none transition">
</div>
<!-- Similar structure for email, student ID, course dropdown, etc. -->
<div class="flex justify-between pt-4">
<button type="submit" class="px-6 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition">
Save Changes
</button>
<button type="button" id="cancel-edit" class="px-6 py-2 bg-gray-200 text-gray-700 rounded-lg hover:bg-gray-300 transition">
Cancel
</button>
</div>
</form>
</div>
Step 6: Adding JavaScript Functionality
Now let's implement the JavaScript to make everything work:
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const loginContainer = document.getElementById('login-container');
const registerContainer = document.getElementById('register-container');
const profileContainer = document.getElementById('profile-container');
const editProfileContainer = document.getElementById('edit-profile-container');
// Form elements
const loginForm = document.getElementById('login-form');
const registerForm = document.getElementById('register-form');
const editProfileForm = document.getElementById('edit-profile-form');
// Navigation links
const showRegisterLink = document.getElementById('show-register');
const showLoginLink = document.getElementById('show-login');
const logoutBtn = document.getElementById('logout');
const editProfileBtn = document.getElementById('edit-profile');
const cancelEditBtn = document.getElementById('cancel-edit');
// Check if user is already logged in
checkLoginStatus();
// Event Listeners
showRegisterLink.addEventListener('click', showRegisterForm);
showLoginLink.addEventListener('click', showLoginForm);
loginForm.addEventListener('submit', handleLogin);
registerForm.addEventListener('submit', handleRegistration);
logoutBtn.addEventListener('click', handleLogout);
editProfileBtn.addEventListener('click', showEditProfileForm);
editProfileForm.addEventListener('submit', handleProfileUpdate);
cancelEditBtn.addEventListener('click', () => {
editProfileContainer.classList.add('hidden');
profileContainer.classList.remove('hidden');
});
// Functions
function checkLoginStatus() {
const currentUser = localStorage.getItem('currentUser');
if (currentUser) {
const user = JSON.parse(localStorage.getItem(currentUser));
showProfile(user);
}
}
function showRegisterForm(e) {
e.preventDefault();
loginContainer.classList.add('hidden');
registerContainer.classList.remove('hidden');
}
function showLoginForm(e) {
e.preventDefault();
registerContainer.classList.add('hidden');
loginContainer.classList.remove('hidden');
}
function handleLogin(e) {
e.preventDefault();
const email = document.getElementById('login-email').value;
const password = document.getElementById('login-password').value;
// Simple validation
if (!email || !password) {
alert('Please fill in all fields');
return;
}
// Check if user exists
const user = JSON.parse(localStorage.getItem(email));
if (!user) {
alert('User not found. Please register.');
return;
}
// Check password
if (user.password !== password) {
alert('Incorrect password');
return;
}
// Remember me functionality
const rememberMe = document.getElementById('remember-me').checked;
if (rememberMe) {
localStorage.setItem('currentUser', email);
}
showProfile(user);
}
function handleRegistration(e) {
e.preventDefault();
const name = document.getElementById('register-name').value;
const email = document.getElementById('register-email').value;
const studentId = document.getElementById('register-id').value;
const password = document.getElementById('register-password').value;
const confirmPassword = document.getElementById('register-confirm-password').value;
// Validation checks
if (!name || !email || !studentId || !password || !confirmPassword) {
alert('Please fill in all fields');
return;
}
if (password !== confirmPassword) {
alert('Passwords do not match');
return;
}
if (localStorage.getItem(email)) {
alert('User already exists. Please login.');
return;
}
// Create new user
const newUser = {
name,
email,
studentId,
password,
course: 'Computer Science',
year: '1st Year',
semester: '1st Semester',
gpa: '0.00',
phone: '',
address: ''
};
// Save user to localStorage
localStorage.setItem(email, JSON.stringify(newUser));
localStorage.setItem('currentUser', email);
showProfile(newUser);
registerForm.reset();
}
function showProfile(user) {
// Update profile page with user data
document.getElementById('profile-name').textContent = user.name;
document.getElementById('profile-email').textContent = user.email;
document.getElementById('profile-id').textContent = `Student ID: ${user.studentId}`;
// Update other fields similarly...
// Set avatar initials
const initials = user.name.split(' ').map(n => n[0]).join('').toUpperCase();
document.getElementById('profile-avatar').textContent = initials;
// Show profile and hide other containers
loginContainer.classList.add('hidden');
registerContainer.classList.add('hidden');
profileContainer.classList.remove('hidden');
editProfileContainer.classList.add('hidden');
}
function showEditProfileForm() {
const currentUser = localStorage.getItem('currentUser');
const user = JSON.parse(localStorage.getItem(currentUser));
// Fill edit form with current user data
document.getElementById('edit-name').value = user.name;
document.getElementById('edit-email').value = user.email;
// Fill other fields similarly...
// Show edit form
profileContainer.classList.add('hidden');
editProfileContainer.classList.remove('hidden');
}
function handleProfileUpdate(e) {
e.preventDefault();
const currentUser = localStorage.getItem('currentUser');
const user = JSON.parse(localStorage.getItem(currentUser));
// Update user data from form
user.name = document.getElementById('edit-name').value;
user.email = document.getElementById('edit-email').value;
// Update other fields similarly...
// Save updated user
localStorage.removeItem(currentUser);
localStorage.setItem(user.email, JSON.stringify(user));
localStorage.setItem('currentUser', user.email);
// Show updated profile
showProfile(user);
}
function handleLogout() {
localStorage.removeItem('currentUser');
loginContainer.classList.remove('hidden');
profileContainer.classList.add('hidden');
editProfileContainer.classList.add('hidden');
loginForm.reset();
}
});
Step 7: Adding Custom Styles
Let's enhance our design with some custom CSS:
body {
font-family: 'Poppins', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
}
.card {
backdrop-filter: blur(10px);
background: rgba(255, 255, 255, 0.8);
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.1);
transition: all 0.3s ease;
}