Dự án tổng kết loạt CSS: dựng trang giới thiệu khóa học (landing page) hoàn chỉnh, responsive, có chế độ tối, chỉ với HTML và CSS thuần. Bài cũng hướng dẫn tổ chức mã CSS theo quy ước BEM, chia tệp và kiểm tra chất lượng.
- Lên cấu trúc trang và hệ thống token
- Dựng các khối: header, hero, tính năng, bảng giá, footer
- Tổ chức CSS: reset, token, bố cục, thành phần, tiện ích; quy ước BEM
- Kiểm tra responsive, trợ năng, hiệu năng
Một số khái niệm
BEM (Block – Element – Modifier) đặt tên class rõ ràng, tránh xung đột: .card (khối), .card__title (phần tử của khối), .card--noi-bat (biến thể). Kết hợp @layer để sắp xếp tầng: @layer reset, token, bo-cuc, thanh-phan, tien-ich;.
css/
├── main.css /* @import các tệp dưới theo thứ tự layer */
├── reset.css /* box-sizing, margin 0, img responsive */
├── tokens.css /* :root { --mau-..., --co-chu-..., --khoang-... } */
├── layout.css /* .container, .grid, header, footer */
├── components.css /* .btn, .card, .nav, .pricing */
└── utilities.css /* .text-center, .mt-2, .sr-only */Trang mẫu thu nhỏ
<style>
:root { --c: #2e7d32; --c2: #00838f; --chu: #263238; --phu: #607d8b; --nen: #fff; --nen2: #f5f7f8; --r: 14px; }
* { box-sizing: border-box; } body { margin: 0 !important; font: 15px/1.6 system-ui; color: var(--chu); }
.container { width: min(100% - 32px, 1000px); margin-inline: auto; }
.header { position: sticky; top: 0; background: rgb(255 255 255 / .85); backdrop-filter: blur(6px); border-bottom: 1px solid #eceff1; z-index: 10; }
.header__in { display: flex; align-items: center; gap: 16px; height: 56px; }
.header__logo { font-weight: 800; color: var(--c); } .header__nav { margin-left: auto; display: flex; gap: 14px; font-size: 14px; }
.hero { background: linear-gradient(135deg, var(--c), var(--c2)); color: #fff; padding: 48px 0; text-align: center; }
.hero h1 { font-size: clamp(1.6rem, 5vw, 2.6rem); margin: 0 0 8px; }
.btn { display: inline-block; padding: 10px 20px; border-radius: 10px; background: #fff; color: var(--c); font-weight: 700; text-decoration: none; }
.features { padding: 36px 0; background: var(--nen2); }
.grid { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); }
.card { background: var(--nen); border-radius: var(--r); padding: 18px; box-shadow: 0 4px 14px rgb(0 0 0 / .06); }
.card__icon { width: 40px; height: 40px; border-radius: 10px; background: #e8f5e9; display: grid; place-items: center; margin-bottom: 8px; }
.card--noi-bat { outline: 2px solid var(--c); }
.footer { padding: 18px 0; text-align: center; color: var(--phu); font-size: 13px; }
@media (max-width: 520px) { .header__nav { display: none; } }
</style>
<header class="header"><div class="container header__in"><span class="header__logo">TỰ HỌC TIN</span><nav class="header__nav"><a href="#">Khóa học</a><a href="#">Lộ trình</a><a href="#">Liên hệ</a></nav></div></header>
<section class="hero"><div class="container"><h1>Học CSS từ con số 0</h1><p>22 bài, ví dụ trực quan, dự án thực tế.</p><a class="btn" href="#">Bắt đầu học</a></div></section>
<section class="features"><div class="container grid">
<article class="card"><div class="card__icon">🎨</div><b>Màu sắc và font</b><p>Thiết kế đẹp, dễ đọc.</p></article>
<article class="card card--noi-bat"><div class="card__icon">📐</div><b>Flexbox và Grid</b><p>Bố cục hiện đại.</p></article>
<article class="card"><div class="card__icon">📱</div><b>Responsive</b><p>Đẹp trên mọi màn hình.</p></article>
</div></section>
<footer class="footer">© 2026 Tự Học Tin</footer>Toàn bộ trang chỉ khoảng 30 dòng CSS nhờ token và lưới auto-fit. Thu nhỏ cửa sổ để thấy menu ẩn và thẻ tự xuống hàng.
Danh sách kiểm tra trước khi hoàn thành
- Không có thanh cuộn ngang ở chiều rộng 320px.
- Tương phản chữ đạt tối thiểu 4.5:1; mọi phần tử bấm được có trạng thái focus.
- Ảnh có width/height, nén WebP, loading="lazy".
- Kiểm tra bằng Lighthouse (DevTools) điểm Performance, Accessibility ≥ 90.
- CSS hợp lệ tại jigsaw.w3.org/css-validator; không còn !important thừa.
- Đưa lên GitHub Pages để có đường dẫn công khai.
Sau dự án này, hãy làm lại đúng trang đó bằng Bootstrap 5 rồi bằng Tailwind CSS (hai loạt bài tiếp theo) để thấy ưu, nhược điểm của từng cách.
Đừng sao chép nguyên mẫu giao diện có bản quyền; hãy lấy cảm hứng bố cục, còn màu, chữ, hình ảnh tự thiết kế.
- Dựng landing page giới thiệu một khóa học của bạn với 5 khối như trên.
- Thêm bảng giá 3 gói, gói giữa nổi bật (modifier --noi-bat).
- Thêm chế độ tối bằng biến và prefers-color-scheme.
- Chia CSS thành các tệp theo layer, đặt tên BEM, chạy Lighthouse và sửa lỗi.
- Token + reset + layout + component + utility.
- BEM: block__element--modifier.
- Grid auto-fit, clamp, sticky header, biến màu.
- Kiểm tra responsive, trợ năng, hiệu năng trước khi bàn giao.