Bài tổng kết về form: định dạng form đẹp và đồng nhất bằng CSS, bảo đảm người khuyết tật dùng được, đọc dữ liệu bằng JavaScript và xử lý ở máy chủ bằng PHP; cuối bài là dự án form đăng ký học phần hoàn chỉnh.
- Định dạng form gọn, đẹp, responsive
- Áp dụng nguyên tắc trợ năng cho form
- Đọc dữ liệu form bằng FormData, gửi bằng fetch
- Nhận dữ liệu ở máy chủ bằng PHP và các dịch vụ không cần máy chủ
- Trợ năng (accessibility)
- Khả năng người khuyết tật sử dụng được.
- FormData
- Đối tượng JavaScript chứa dữ liệu của form.
- $_POST
- Mảng PHP chứa dữ liệu gửi bằng POST.
- CSRF
- Tấn công giả mạo yêu cầu; cần token để chống.
Khái niệm và lý thuyết
Một form tốt: ngắn (chỉ hỏi điều cần), rõ ràng (nhãn ở trên ô, nhóm hợp lý), dễ bấm (ô cao tối thiểu 44px trên điện thoại), báo lỗi cụ thể và an toàn (HTTPS, kiểm tra ở máy chủ).
Định dạng form bằng CSS
<style>
.f-dep { max-width: 420px; display: grid; gap: 12px; font-family: inherit; }
.f-dep label { font-weight: 600; display: grid; gap: 4px; }
.f-dep input, .f-dep select, .f-dep textarea {
font: inherit; padding: 10px 12px; border: 1px solid #bdbdbd; border-radius: 8px; }
.f-dep input:focus, .f-dep select:focus, .f-dep textarea:focus {
outline: none; border-color: #2e7d32; box-shadow: 0 0 0 3px rgb(46 125 50 / .25); }
.f-dep .hang { display: flex; gap: 12px; } .f-dep .hang label { flex: 1; }
.f-dep { accent-color: #2e7d32; }
.f-dep button { padding: 12px; border: 0; border-radius: 8px; background: #2e7d32; color: #fff; font-weight: 700; cursor: pointer; }
.f-dep button:hover { background: #1b5e20; }
</style>
<form class="f-dep" onsubmit="alert('Đã gửi'); return false;">
<div class="hang">
<label>Họ <input name="ho" autocomplete="family-name" required></label>
<label>Tên <input name="ten" autocomplete="given-name" required></label>
</div>
<label>Email <input type="email" name="email" autocomplete="email" required></label>
<label>Học phần
<select name="hoc_phan"><option>Thiết kế web</option><option>Lập trình Python</option></select>
</label>
<label style="font-weight:400; display:flex; gap:8px; align-items:center;"><input type="checkbox" required> Tôi đã đọc quy chế đào tạo</label>
<button type="submit">Đăng ký học phần</button>
</form>accent-color đổi màu checkbox, radio, range theo màu thương hiệu chỉ với một dòng CSS.
Trợ năng cho form
- Mọi ô đều có
label; nhóm radio/checkbox đặt trongfieldsetcólegend. - Không chỉ dùng màu để báo lỗi: thêm chữ, biểu tượng.
- Gắn thông báo hướng dẫn/lỗi bằng
aria-describedby. - Thứ tự Tab hợp lý, có viền focus nhìn rõ; không xóa outline mà không thay thế.
- Bắt buộc ghi rõ: dấu * kèm chú thích “(*) bắt buộc”.
<label for="cccd">Số CCCD *</label>
<input id="cccd" name="cccd" inputmode="numeric" pattern="[0-9]{12}" required aria-describedby="hd-cccd">
<small id="hd-cccd">Gồm 12 chữ số, in ở mặt trước thẻ.</small>Đọc dữ liệu bằng JavaScript và gửi bằng fetch
<form id="f-js">
<input name="ten" value="Lò Văn An"> <input name="lop" value="K66 Tin">
<button>Xem dữ liệu</button>
</form>
<pre id="kq-js" style="background:#f5f5f5;padding:8px;"></pre>
<script>
document.getElementById("f-js").addEventListener("submit", e => {
e.preventDefault();
const duLieu = Object.fromEntries(new FormData(e.target));
document.getElementById("kq-js").textContent = JSON.stringify(duLieu, null, 2);
// Gửi lên máy chủ: fetch("/api/dang-ky", { method: "POST", body: new FormData(e.target) })
});
</script>Xử lý ở máy chủ bằng PHP
<?php
// dang-ky.php
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$hoTen = trim($_POST['ho_ten'] ?? '');
$email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL);
if ($hoTen === '' || !$email) {
exit('Dữ liệu không hợp lệ');
}
// Lưu CSDL bằng PDO với câu lệnh chuẩn bị (prepared statement)
echo 'Xin chào ' . htmlspecialchars($hoTen) . '!';
}Luôn kiểm tra lại dữ liệu, dùng htmlspecialchars khi hiển thị để chống XSS và prepared statement khi ghi CSDL để chống SQL injection. Không có máy chủ? Có thể gửi form tới Formspree, Google Apps Script hoặc dùng Google Forms.
Đặt nhãn phía trên ô nhập (thay vì bên trái) giúp form đọc nhanh hơn và tự nhiên trên điện thoại.
Form có thao tác quan trọng (đổi mật khẩu, chuyển điểm) cần token chống CSRF và giới hạn số lần gửi để chống spam; các framework như Laravel, Django có sẵn cơ chế này.
- Hoàn thiện form đăng ký học phần ở trên, thêm ngày sinh, số điện thoại, ghi chú.
- Bổ sung thông báo lỗi dưới từng ô với aria-describedby.
- Hiển thị dữ liệu form dạng JSON bằng FormData.
- Viết dang-ky.php nhận và hiển thị dữ liệu, chạy thử trên XAMPP.
- Form tốt: ngắn, rõ, dễ bấm, báo lỗi cụ thể.
- CSS grid, focus, accent-color giúp form đẹp và nhất quán.
- Trợ năng: label, fieldset, aria-describedby, focus rõ.
- FormData/fetch ở trình duyệt; máy chủ luôn kiểm tra và làm sạch dữ liệu.