CSS cơ bản – Bài 17: Tạo kiểu form, hover, focus và trạng thái lỗi
- 19-10-2026
- Toanngo92
- 0 Comments
Bạn sẽ làm form liên hệ dễ đọc và thao tác, giữ nhãn rõ ràng cùng dấu focus, đồng thời phân biệt hover, disabled và kiểm tra dữ liệu. CSS hỗ trợ trải nghiệm nhưng không thay backend xác thực.
Dùng tiếp website Góc học web từ môn HTML. Mỗi thư mục ví dụ là một phiên bản độc lập: before.html và before.css để so sánh, index.html và styles.css là kết quả sau bài học. Hãy sửa một quy tắc, tải lại và giải thích điều thay đổi.
Mục lục
Bắt đầu từ form HTML đã có nhãn
Mỗi input có label liên kết đúng, name phù hợp và hướng dẫn khi cần. CSS không sửa được việc label trỏ nhầm ID. Trước khi tạo màu, dùng Tab để xác nhận thứ tự và tên điều khiển đã có nghĩa.
Ví dụ chỉ dùng dữ liệu giả với GET tới một trang kết quả tĩnh. Không có backend lưu liên hệ, gửi email hay xác minh quyền sở hữu địa chỉ email. Thay màu nút thành xanh không làm các chức năng đó xuất hiện.
Chữ, kích thước và khoảng cách
Nhiều điều khiển có kiểu mặc định riêng theo hệ điều hành và trình duyệt. font:inherit giúp một số điều khiển thống nhất kiểu chữ với nội dung. Đặt width và box-sizing có kiểm soát để input không vượt vùng khi có padding và border.
Không cần loại bỏ toàn bộ giao diện native của checkbox, radio hoặc select chỉ để chúng giống nhau tuyệt đối. Tự tạo lại có thể phát sinh vấn đề về bàn phím, tương phản và trạng thái, nên hãy ưu tiên một bản hoạt động đúng trước.
Hover và focus không thay thế nhau
Hover hữu ích cho thiết bị có con trỏ; focus-visible giúp thể hiện vị trí khi cần, nhất là bàn phím. Nút hoặc liên kết cần một dấu focus rõ trên nền thật. Không xóa outline chung toàn website mà chưa cung cấp dấu thay thế.
Disabled thể hiện điều khiển không thao tác được theo HTML. CSS :disabled chỉ tạo kiểu cho trạng thái đó, không thay thuộc tính disabled. Một nút màu xám nhưng vẫn có thể bấm không tự trở thành nút vô hiệu hóa đúng ngữ nghĩa.
Lỗi cần được giải thích bằng nội dung
:invalid có thể khớp required trống ngay khi trang mở, nên tô đỏ mọi :invalid có thể làm form trông đã lỗi trước khi người dùng nhập. Ví dụ chỉ thể hiện một thông báo lỗi minh họa bằng chữ và aria-invalid khi có lỗi được biết; ứng dụng thật phải cập nhật trạng thái theo luồng xử lý.
Không truyền đạt lỗi chỉ bằng viền đỏ. Nêu rõ điều cần sửa, liên kết mô tả với điều khiển khi phù hợp và giữ dữ liệu đang nhập. CSS không thể tự xác định mọi quy tắc nghiệp vụ hoặc bảo mật của form.
Mã của phần đang học
Giữ lại cấu trúc HTML có ý nghĩa. Đoạn dưới là phần HTML liên quan đến tình huống; bộ tải về có cả tài liệu hoàn chỉnh và stylesheet tích lũy từ các bài trước.
<form action="result.html" method="get" class="contact-form"><p class="form-note">Chỉ dùng dữ liệu giả. Đây là ví dụ tĩnh, không có backend lưu dữ liệu hay gửi email.</p>
<label for="name">Họ tên giả</label><input id="name" name="ho_ten" autocomplete="off" required>
<label for="email">Email giả</label><input id="email" name="email" type="email" autocomplete="off" required>
<label for="message">Nội dung thử</label><textarea id="message" name="noi_dung" rows="4" required minlength="10" aria-describedby="message-help"></textarea><p id="message-help" class="help">Ít nhất 10 ký tự. Không nhập thông tin cá nhân thật.</p>
<button type="submit">Gửi dữ liệu giả</button><button type="button" disabled>Đang xử lý — minh họa</button></form><section class="contact-form" aria-labelledby="error-title"><h3 id="error-title">Ảnh chụp trạng thái lỗi bằng HTML</h3><p>Trạng thái dưới đây cố định để quan sát, không tự cập nhật khi nhập. Form phía trên dùng kiểm tra native của trình duyệt.</p><label for="email-error">Email giả có lỗi</label><input id="email-error" type="email" value="sai" aria-invalid="true" aria-describedby="email-error-message"><p id="email-error-message" class="error-message">Địa chỉ cần có dạng [email protected]. Hãy sửa email trước khi gửi.</p></section>Thêm hoặc sửa trong styles.css
.contact-form { max-width: 36rem; }
.contact-form label { display: block; font-weight: 700; margin-top: 1rem; }
.contact-form input, .contact-form textarea { width: 100%; padding: .65rem; border: 1px solid #839db4; border-radius: .4rem; font: inherit; }
.contact-form button { padding: .6rem 1rem; margin: 1rem .5rem 0 0; border: 1px solid #175f82; border-radius: .4rem; background: #175f82; color: #fff; }
a:focus-visible, button:focus-visible, input:focus-visible, textarea:focus-visible { outline: 3px solid #b25b00; outline-offset: 3px; }
@media (hover: hover) { .button:hover, .contact-form button:not(:disabled):hover { background: #104761; } }
.contact-form button:disabled { opacity: .65; cursor: not-allowed; }
.help, .form-note { font-size: .9rem; color: #425a73; }
.error-message { color: #9f1239; font-weight: 700; }So sánh trước và sau
Form có nhãn, khoảng cách và dấu focus dễ nhận biết. Nút vô hiệu hóa chỉ minh họa trạng thái; nút gửi dùng dữ liệu giả và chuyển trang tĩnh, không gửi email.
Xem trước khi sửa · Xem sau khi sửa · Tải 20 phiên bản và website hoàn chỉnh
Mở bản trước khi sửa của bài 17
Lỗi thường gặp và cách sửa
- Xóa outline vì thấy viền focus xấu: thiết kế dấu focus thay thế có tương phản.
- Tô đỏ mọi trường trống ngay khi tải: cân nhắc thời điểm thể hiện lỗi.
- Dùng màu nút thay cho disabled: dùng trạng thái HTML thật.
Tự kiểm tra
- Dùng Tab để đi qua mọi điều khiển, không dùng chuột.
- Gửi dữ liệu giả hợp lệ và xác nhận trang kết quả nói rõ không có backend.
Những điều cần nhớ
Đối chiếu kết quả với mục tiêu của bài, không chỉ nhìn xem giao diện có giống ảnh mẫu. Dùng DevTools kiểm tra quy tắc thực sự được áp dụng và thử một nội dung dài hơn hoặc khung nhìn hẹp hơn trước khi kết luận đã xong.
