Bài 10: Dự án — hoàn thiện trang cá nhân (HTML + CSS + JS)

Bài 9 bạn đã thao tác DOM để trang tương tác. Giờ là lúc ghép tất cả lại: HTML (nội dung), CSS (trang trí + responsive), và JavaScript (tương tác) thành một trang cá nhân hoàn chỉnh — có bố cục co giãn trên điện thoại và một nút đổi giao diện sáng/tối. Đây là dự án tổng kết cả series cơ bản; làm xong bạn có một sản phẩm thật để tự hào và chia sẻ.
⏱️ Cách học bài này (~30 phút): dựng HTML (8’), thêm CSS responsive (10’), thêm JS đổi giao diện (7’), chạy thử + tinh chỉnh (5’).
Mục tiêu bài học
Sau bài này bạn sẽ:
- Ghép HTML + CSS + JS thành một trang hoàn chỉnh.
- Dựng bố cục responsive (đẹp trên điện thoại).
- Thêm nút đổi giao diện sáng/tối bằng JavaScript.
- Có một trang cá nhân của riêng mình để mở rộng tiếp.
Bước 1: Cấu trúc HTML
Tạo index.html:
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Trang cá nhân của Lan</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Nguyễn Thị Lan</h1>
<p>Nhân viên marketing · yêu viết lách</p>
<button id="nut-giao-dien">🌙 Đổi giao diện</button>
</header>
<section>
<h2>Về tôi</h2>
<p>Xin chào! Tôi thích marketing, cà phê và học điều mới mỗi ngày.</p>
</section>
<section>
<h2>Kỹ năng</h2>
<div class="ky-nang">
<span class="the">Marketing</span>
<span class="the">Viết nội dung</span>
<span class="the">Canva</span>
</div>
</section>
<footer>
<p>Liên hệ: [email protected]</p>
</footer>
<script src="script.js"></script>
</body>
</html>
Bước 2: CSS trang trí + responsive
Tạo style.css:
* { box-sizing: border-box; }
body {
max-width: 700px;
width: 100%;
margin: 0 auto;
padding: 0 16px;
font-family: Arial, sans-serif;
line-height: 1.6;
background: #ffffff;
color: #222222;
}
header { text-align: center; padding: 24px 0; }
.ky-nang { display: flex; gap: 12px; flex-wrap: wrap; }
.the {
background: #eee;
padding: 6px 12px;
border-radius: 8px;
}
img { max-width: 100%; height: auto; }
/* Giao diện tối: bật khi body có class .toi */
body.toi { background: #1e1e1e; color: #f0f0f0; }
body.toi .the { background: #333; }
/* Điện thoại: màn rộng tối đa 600px */
@media (max-width: 600px) {
body { font-size: 15px; }
h1 { font-size: 24px; }
.ky-nang { flex-direction: column; }
}
Bước 3: JavaScript — nút đổi giao diện
Tạo script.js:
const nut = document.querySelector("#nut-giao-dien");
nut.addEventListener("click", function () {
document.body.classList.toggle("toi"); // bật/tắt class giao diện tối
});
Cách chạy: để cả ba file (index.html, style.css, script.js) cùng một thư mục, mở index.html. Bấm nút Đổi giao diện — trang chuyển sáng ↔ tối. Thu nhỏ cửa sổ để thấy thẻ kỹ năng xếp dọc trên màn hẹp.
Cách hoạt động (ghép các bài đã học)
- HTML dựng bố cục: header, các
<section>, footer — cấu trúc rõ ràng (Bài 1–5). - CSS dùng
box-sizing,max-width, Flexbox và@mediađể đẹp trên mọi màn (Bài 6–7). - JS dùng
querySelector+addEventListener+classList.toggleđể đổi giao diện (Bài 8–9).
Điểm hay: đổi giao diện chỉ tốn 3 dòng JS vì phần “tối” đã định nghĩa sẵn trong CSS (body.toi). JS chỉ bật/tắt class — CSS lo phần còn lại.
Bài thực hành / mở rộng
Bài 1 — Cá nhân hoá: đổi tên, giới thiệu, kỹ năng thành của bạn.
Bài 2 — Thêm mục: thêm một <section> “Sở thích” với vài thẻ .the.
Bài 3 — Nút đổi chữ nút: khi bật giao diện tối, đổi chữ nút thành “☀️ Sáng”; khi tắt thì về “🌙 Đổi giao diện” (gợi ý: if (document.body.classList.contains("toi")) để kiểm tra, rồi đổi chữ bằng nut.textContent = "...").
Lỗi thường gặp & cách sửa
- Nút không đổi màu trang → sai
id(#nut-giao-dien) hoặc chưa định nghĩabody.toitrong CSS. - CSS/JS không áp dụng → sai đường dẫn
href="style.css"/src="script.js", hoặc file không cùng thư mục. - Trang tràn ngang trên điện thoại → thiếu
* { box-sizing: border-box; }hoặc thẻ meta viewport. - Thẻ kỹ năng không xếp dọc trên màn nhỏ → thiếu
.ky-nang { display: flex }(cần có thìflex-direction: columnmới tác dụng).
💾 Mang về — khung trang cá nhân
Bạn vừa có một bộ khung 3 file hoàn chỉnh (HTML + CSS + JS) tái dùng cho mọi trang cá nhân: cấu trúc header/section/footer, CSS responsive có sẵn giao diện tối, và nút tương tác. Giữ lại làm nền cho các dự án sau.
Thuật ngữ chốt
| Thuật ngữ | Giải thích ngắn |
|---|---|
| section / header / footer | Thẻ HTML chia bố cục trang |
box-sizing: border-box |
Tính padding vào trong bề rộng, tránh tràn |
classList.toggle |
Bật/tắt một class (dùng cho sáng/tối) |
body.toi (CSS) |
Quy tắc chỉ áp dụng khi body có class toi |
@media (max-width) |
Đổi bố cục theo kích thước màn hình |
Tự kiểm tra
- Nút đổi giao diện dùng phương thức JS nào? (Đáp án:
classList.toggle("toi")) - Vì sao chỉ cần 3 dòng JS cho dark mode? (Đáp án: phần “tối” đã định nghĩa sẵn trong CSS
body.toi) - Thiếu gì thì thẻ kỹ năng không xếp dọc trên điện thoại? (Đáp án:
flex-direction: columntrong media query — vì.ky-nangvốn đã códisplay: flexở rule gốc)
Ghi nhớ nhanh
- Trang hoàn chỉnh = HTML (nội dung) + CSS (trang trí/responsive) + JS (tương tác).
- Dark mode gọn: định nghĩa
body.toitrong CSS, JS chỉclassList.toggle. - Luôn có
box-sizing: border-box+ meta viewport để không tràn ngang.
👉 Bài tập về nhà: hoàn thiện trang cá nhân của bạn (nội dung thật) và làm Bài 3 mở rộng (đổi chữ nút theo giao diện). Bài tiếp theo trong series: Bài 11 — Đưa web lên mạng bằng hosting miễn phí (sắp đăng) — để cả thế giới xem được trang của bạn.
Câu hỏi thường gặp
Một trang web cá nhân cơ bản gồm những phần nào?
Thường gồm: phần đầu (header) với tên và giới thiệu ngắn, phần ‘Về tôi’ (about), phần kỹ năng hoặc sở thích, và phần liên hệ (contact). Về kỹ thuật, ba lớp phối hợp: HTML dựng nội dung và cấu trúc, CSS trang trí và làm responsive, JavaScript thêm tương tác (ví dụ nút đổi giao diện). Bài này ghép cả ba thành một trang hoàn chỉnh.
Làm nút đổi giao diện sáng/tối (dark mode) bằng JavaScript thế nào?
Cách đơn giản nhất: định nghĩa sẵn một class CSS (ví dụ .toi) chứa màu nền tối và màu chữ sáng, gắn vào thẻ body. Khi bấm nút, dùng JavaScript document.body.classList.toggle(‘toi’) để bật/tắt class đó — trang lập tức đổi giữa sáng và tối. Đây là ứng dụng trực tiếp của classList.toggle bạn đã học ở Bài 9.
Sau khi làm xong trang cá nhân thì đưa lên mạng thế nào?
Bạn có thể đưa trang tĩnh (chỉ HTML/CSS/JS) lên các dịch vụ hosting miễn phí như GitHub Pages, Netlify hoặc Vercel — chỉ cần tải thư mục dự án lên là có một địa chỉ web thật để chia sẻ. Đây chính là nội dung của bài tiếp theo trong series. Trước mắt, hãy hoàn thiện trang chạy tốt trên máy đã.
Phù thủy bàn phím, mê tự động hoá và 'lười thông minh'. Gom phần mềm, code và AI thành mấy phép nhỏ giúp bạn xong việc trước giờ nghỉ trưa.
Bài liên quan

Git và GitHub cho người mới: đưa dự án đầu tiên lên GitHub
Biết Git là gì rồi nhưng chưa biết đưa code lên GitHub? Bài này dẫn bạn từ cài đặt, tạo repo, đến các lệnh init → add → commit → push để đưa dự án đầu tiên lên GitHub, kèm giải thích từng khái niệm.

Bài 11: Module và thư viện chuẩn trong Python
Bài 11 series Python cho người mới (bài học 30 phút): dùng module và thư viện chuẩn — import math, random, datetime — và tự tách code thành module riêng để tái dùng; kèm bài tập và code mang về.

Bài 9: JavaScript — thao tác DOM (đổi nội dung, ẩn/hiện, tạo phần tử)
Bài 9 series Web cơ bản (bài học 30 phút): thao tác DOM bằng JavaScript — chọn phần tử, đổi nội dung và kiểu, ẩn/hiện, tạo phần tử mới — làm danh sách việc cần làm tương tác; kèm thực hành và file mang về.