Giới thiệu
Register form (form đăng ký) thường bao gồm: Email, Mật khẩu, Xác nhận mật khẩu, đồng ý điều khoản. Thiết kế cần rõ ràng, validation trực quan, bảo mật (hiện/ẩn mật khẩu), và responsive.
Ví dụ hoàn chỉnh - Form đăng ký hiện đại
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register Form</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
* { box-sizing: border-box; }
body { font-family: 'Segoe UI', system-ui, sans-serif; background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%); min-height: 100vh; display: flex; align-items: center; justify-content: center; padding: 40px 20px; }
.register-card {
width: 100%;
max-width: 460px;
background: #fff;
border-radius: 20px;
box-shadow: 0 20px 50px rgba(0,0,0,0.1);
padding: 48px;
position: relative;
overflow: hidden;
}
.register-card::before {
content: '';
position: absolute;
top: 0; left: 0; right: 0;
height: 5px;
background: linear-gradient(90deg, #1eadef, #512c94, #f44336);
}
h1 { text-align: center; margin: 0 0 8px; font-size: 28px; color: #1a1a1a; }
.subtitle { text-align: center; margin: 0 0 32px; color: #666; font-size: 15px; }
.form-group { margin-bottom: 22px; position: relative; }
label { display: block; margin-bottom: 8px; font-weight: 500; font-size: 14px; color: #333; }
.input-wrapper { position: relative; }
input[type="email"], input[type="password"], input[type="text"] {
width: 100%;
padding: 14px 16px 14px 48px;
font-size: 16px;
border: 1.5px solid #e0e0e0;
border-radius: 10px;
background: #fafafa;
transition: all 0.2s;
}
input:focus {
outline: none;
border-color: #1eadef;
background: #fff;
box-shadow: 0 0 0 4px rgba(30,173,239,0.1);
}
.input-icon {
position: absolute;
left: 16px;
top: 50%;
transform: translateY(-50%);
color: #aaa;
font-size: 18px;
pointer-events: none;
transition: color 0.2s;
}
.input-wrapper:focus-within .input-icon { color: #1eadef; }
.toggle-pwd {
position: absolute;
right: 14px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
color: #888;
cursor: pointer;
padding: 4px;
font-size: 16px;
}
.toggle-pwd:hover { color: #333; }
.password-strength {
height: 4px;
border-radius: 2px;
background: #eee;
margin-top: 8px;
overflow: hidden;
}
.password-strength-bar {
height: 100%;
width: 0%;
border-radius: 2px;
transition: all 0.3s;
}
.strength-weak .password-strength-bar { width: 33%; background: #f44336; }
.strength-medium .password-strength-bar { width: 66%; background: #ff9800; }
.strength-strong .password-strength-bar { width: 100%; background: #4caf50; }
.terms-group {
display: flex;
align-items: flex-start;
gap: 10px;
margin: 8px 0 24px;
}
.terms-group input { width: 18px; height: 18px; margin-top: 2px; accent-color: #1eadef; flex-shrink: 0; }
.terms-group label { font-size: 13px; color: #555; line-height: 1.5; margin: 0; cursor: pointer; }
.terms-group a { color: #1eadef; text-decoration: none; font-weight: 500; }
.terms-group a:hover { text-decoration: underline; }
.btn-register {
width: 100%;
padding: 16px;
font-size: 16px;
font-weight: 600;
color: #fff;
background: linear-gradient(135deg, #1eadef, #512c94);
border: none;
border-radius: 10px;
cursor: pointer;
transition: transform 0.1s, box-shadow 0.2s;
}
.btn-register:hover { box-shadow: 0 8px 25px rgba(30,173,239,0.35); }
.btn-register:active { transform: scale(0.98); }
.login-prompt { text-align: center; margin-top: 24px; font-size: 14px; color: #666; }
.login-prompt a { color: #1eadef; font-weight: 600; text-decoration: none; }
.login-prompt a:hover { text-decoration: underline; }
@media (max-width: 480px) { .register-card { padding: 32px 24px; } }
</style>
</head>
<body>
<div class="register-card">
<h1>Tạo tài khoản mới</h1>
<p class="subtitle">Điền thông tin bên dưới để bắt đầu</p>
<form id="registerForm" novalidate>
<div class="form-group">
<label for="email">Email</label>
<div class="input-wrapper">
<input type="email" id="email" name="email" placeholder="email@example.com" required autocomplete="email">
<i class="fas fa-envelope input-icon" aria-hidden="true"></i>
</div>
</div>
<div class="form-group">
<label for="password">Mật khẩu</label>
<div class="input-wrapper">
<input type="password" id="password" name="password" placeholder="Tối thiểu 8 ký tự" required autocomplete="new-password" minlength="8">
<i class="fas fa-lock input-icon" aria-hidden="true"></i>
<button type="button" class="toggle-pwd" aria-label="Hiện/ẩn mật khẩu"><i class="fas fa-eye"></i></button>
</div>
<div class="password-strength" aria-hidden="true"><div class="password-strength-bar"></div></div>
</div>
<div class="form-group">
<label for="confirmPassword">Xác nhận mật khẩu</label>
<div class="input-wrapper">
<input type="password" id="confirmPassword" name="confirmPassword" placeholder="Nhập lại mật khẩu" required autocomplete="new-password">
<i class="fas fa-lock input-icon" aria-hidden="true"></i>
<button type="button" class="toggle-pwd" aria-label="Hiện/ẩn mật khẩu"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="terms-group">
<input type="checkbox" id="terms" name="terms" required>
<label for="terms">Tôi đồng ý với <a href="#">Điều khoản dịch vụ</a> và <a href="#">Chính sách bảo mật</a>.</label>
</div>
<button type="submit" class="btn-register">Tạo tài khoản</button>
</form>
<p class="login-prompt">Đã có tài khoản? <a href="#">Đăng nhập ngay</a></p>
</div>
<script>
// Toggle password
document.querySelectorAll('.toggle-pwd').forEach(btn => {
btn.addEventListener('click', () => {
const input = btn.closest('.input-wrapper').querySelector('input');
const icon = btn.querySelector('i');
const type = input.type === 'password' ? 'text' : 'password';
input.type = type;
icon.className = type === 'password' ? 'fas fa-eye' : 'fas fa-eye-slash';
});
});
// Password strength meter
const pwd = document.getElementById('password');
const strengthBar = document.querySelector('.password-strength');
pwd.addEventListener('input', () => {
const val = pwd.value;
strengthBar.className = 'password-strength';
if (val.length === 0) return;
let score = 0;
if (val.length >= 8) score++;
if (/[A-Z]/.test(val) && /[a-z]/.test(val)) score++;
if (/\d/.test(val)) score++;
if (/[^A-Za-z0-9]/.test(val)) score++;
if (score <= 1) strengthBar.classList.add('strength-weak');
else if (score <= 3) strengthBar.classList.add('strength-medium');
else strengthBar.classList.add('strength-strong');
});
// Confirm password match
document.getElementById('registerForm').addEventListener('submit', (e) => {
if (pwd.value !== document.getElementById('confirmPassword').value) {
e.preventDefault();
alert('Mật khẩu xác nhận không khớp!');
}
});
</script>
</body>
</html>
Tính năng nổi bật
- Password strength meter: Thanh tiến độ đổi màu theo độ mạnh (JS nhẹ).
- Toggle hiện/ẩn mật khẩu: Cho cả 2 ô password.
- Icon trong input: Email, Lock - đổi màu khi focus.
- Validation HTML5 + JS: required, minlength, match confirm.
- Checkbox điều khoản bắt buộc: Không submit được nếu chưa tick.
- Responsive card: Gradient border top, shadow sâu, bo góc lớn.
Mẹo UX đăng ký
- Cho phép đăng ký bằng Google/GitHub/Facebook (social login) - giảm ma sát.
- Hiển thị yêu cầu mật khẩu trước khi nhập (helper text), không chỉ khi sai.
- Tự động focus vào ô đầu tiên khi load trang.
- Enter key submit form (mặc định của button type=submit).