Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn vừa nhận một file Word dài 40 trang. Nếu cả tài liệu chỉ toàn chữ cùng một cỡ, không heading, không mục lục, không in đậm — bạn sẽ phải đọc từng dòng để biết phần nào là tiêu đề, phần nào là nội dung, phần nào là chú thích. Mệt mỏi và dễ lạc.
HTML không semantic chính là tài liệu 40 trang đó. Khi bạn dựng cả trang web bằng những thẻ <div> vô danh chồng lên nhau, trình duyệt vẫn hiển thị ra giao diện đẹp như thường — nhưng bên dưới lớp giao diện ấy là một mớ hỗn độn không ai đọc được cấu trúc: Google không hiểu đâu là nội dung chính, screen reader không biết đâu là vùng điều hướng, và đồng nghiệp tiếp quản code của bạn sáu tháng sau sẽ phải đoán mò.
Semantic HTML là nghệ thuật chọn đúng thẻ cho đúng vai trò ngữ nghĩa của nội dung. Đây là bài học bản lề: ở các bài trước bạn đã học HTML và CSS để "vẽ" ra giao diện. Từ bài này trở đi, bạn học cách viết HTML để cấu trúc có ý nghĩa — nền tảng cho mọi thứ về sau: SEO (Bài 57), accessibility (Bài 42, 43), và dev handoff (Bài 55). Một designer web giỏi không chỉ làm trang đẹp, mà còn làm trang "đọc được" với cả con người lẫn máy móc. Đó chính là điều chúng ta học hôm nay.
Khái niệm cốt lõi
Semantic nghĩa là gì?
"Semantic" nghĩa là "có ý nghĩa". Một thẻ semantic là thẻ mà bản thân cái tên của nó đã nói lên vai trò của nội dung bên trong. So sánh:
<!-- Không semantic: thẻ div không nói gì về vai trò -->
<div class="header">
<div class="nav">...</div>
</div>
<div class="main-content">
<div class="article">...</div>
</div>
<div class="footer">...</div><!-- Semantic: tên thẻ chính là vai trò -->
<header>
<nav>...</nav>
</header>
<main>
<article>...</article>
</main>
<footer>...</footer>
Hai đoạn này render ra giao diện y hệt nhau nếu bạn áp cùng CSS. Nhưng đoạn thứ hai mang theo thông tin: trình duyệt, công cụ tìm kiếm và phần mềm hỗ trợ đều hiểu ngay đây là phần đầu trang, đây là vùng điều hướng, đây là nội dung chính, đây là chân trang. Cái class header trong đoạn đầu chỉ có ý nghĩa với riêng bạn — máy móc không đọc class để hiểu cấu trúc.
Bộ thẻ semantic landmark cần thuộc nằm lòng
HTML5 cho chúng ta một bộ thẻ "landmark" — những cột mốc định vị cấu trúc trang:
<header>— phần đầu của trang hoặc của một khối nội dung (chứa logo, tiêu đề, đôi khi cả nav).<nav>— vùng chứa các liên kết điều hướng chính. Không phải mọi nhóm link đều là nav; chỉ dùng cho điều hướng quan trọng (menu chính, breadcrumb).<main>— nội dung chính, duy nhất của trang. Mỗi trang chỉ được có một<main>.<article>— một khối nội dung độc lập, tự nó có nghĩa kể cả khi tách ra: một bài blog, một sản phẩm, một bình luận.<section>— một nhóm nội dung có chủ đề chung, thường có một heading mở đầu.<aside>— nội dung phụ, liên quan gián tiếp: sidebar, box "bài liên quan", quảng cáo.<footer>— chân trang hoặc chân của một khối (copyright, liên kết phụ, thông tin liên hệ).<figure>và<figcaption>— hình ảnh/biểu đồ kèm chú thích.<time>— đánh dấu thời gian theo định dạng máy đọc được (<time datetime="2026-06-27">27/6/2026</time>).
Phân biệt section vs article vs div
Đây là chỗ nhiều bạn rối nhất. Quy tắc đơn giản:
- Dùng
<article>khi nội dung đứng độc lập được — bạn có thể đem nó đặt sang RSS feed, sang trang khác mà vẫn có nghĩa. Một bài viết, một thẻ sản phẩm trên trang Tiki, một review trên Shopee đều là<article>. - Dùng
<section>khi đó là một phần có chủ đề trong một tổng thể lớn hơn, và thường có heading. Ví dụ trang chủ chia thành section "Sản phẩm nổi bật", section "Đánh giá khách hàng", section "Câu hỏi thường gặp". - Dùng
<div>khi bạn chỉ cần một cái hộp để styling, không có ý nghĩa ngữ nghĩa nào.<div>là thẻ trung tính — và nó hoàn toàn ổn khi dùng đúng mục đích đó.
<div> vẫn cần thiết để bọc nhóm phần tử phục vụ layout (ví dụ một flex container). Vấn đề chỉ nảy sinh khi bạn dùng <div> thay cho một thẻ semantic đáng lẽ phải có.Heading là xương sống cấu trúc
Ngoài landmark, hệ thống heading <h1> đến <h6> chính là dàn ý của trang. Quy tắc:
- Mỗi trang nên có một
<h1>mô tả chủ đề chính. - Không nhảy cấp tuỳ tiện (đừng từ
<h2>nhảy thẳng xuống<h4>rồi quay lại<h2>). - Heading chọn theo ý nghĩa thứ bậc, không chọn theo kích cỡ chữ. Nếu bạn muốn một dòng nhỏ hơn, dùng CSS để chỉnh cỡ — đừng đổi
<h2>thành<h3>chỉ vì muốn nó nhỏ lại.
Tình huống thực tế
Tình huống 1: Trang tin Việt Nam và cú nhảy hạng SEO
Một toà soạn báo điện tử (gọi là VnTinTuc cho dễ hình dung) có hàng nghìn bài viết, nhưng template cũ dựng toàn bộ bằng <div class="title">, <div class="content">, <div class="date">. Google bot vào đọc nhưng không xác định rõ đâu là tiêu đề bài, đâu là nội dung chính, đâu là ngày đăng. Kết quả tìm kiếm hiển thị thiếu ngày tháng, và snippet lấy nhầm đoạn văn quảng cáo ở sidebar làm mô tả.
Đội kỹ thuật làm lại template: tiêu đề bài thành <h1>, nội dung bọc trong <article> với <main> bao ngoài, ngày đăng đổi sang <time datetime="2026-03-15">15/3/2026</time>, sidebar "Tin liên quan" chuyển thành <aside>. Không đổi một dòng nội dung nào, chỉ đổi thẻ. Sau khoảng 6 tuần Google re-crawl, snippet hiển thị đúng tiêu đề và ngày đăng, tỉ lệ click (CTR) trên kết quả tìm kiếm tăng rõ rệt vì người dùng thấy kết quả "đáng tin" hơn.
Bài học: Semantic HTML không phải thủ thuật SEO màu mè, mà là cách bạn nói cho Google biết phần nào quan trọng. Cùng một nội dung, cách đặt thẻ quyết định Google hiểu được bao nhiêu.
Tình huống 2: Sàn thương mại điện tử và người dùng khiếm thị
Một sàn TMĐT (giả định tên ShopVN) bị một khách hàng khiếm thị phản ánh: anh dùng screen reader NVDA nhưng không thể lướt nhanh giữa các phần của trang. Lý do: trang sản phẩm dựng hoàn toàn bằng <div>, không có landmark nào. Screen reader có tính năng "nhảy đến vùng điều hướng" hoặc "nhảy đến nội dung chính" — nhưng vì không có <nav> và <main>, các phím tắt này vô dụng. Anh phải nghe đọc tuần tự từ trên xuống, mất 2-3 phút mới tới được nút "Thêm vào giỏ".
Đội phát triển bọc menu danh mục trong <nav>, khu vực sản phẩm trong <main>, mỗi thẻ sản phẩm thành một <article>, và phần "Sản phẩm tương tự" thành <aside>. Họ cũng bổ sung một liên kết "Bỏ qua đến nội dung chính" (skip link) ở đầu trang. Sau thay đổi, người dùng khiếm thị nhấn một phím tắt là nhảy thẳng vào danh sách sản phẩm — thời gian thao tác giảm còn vài giây.
Bài học: Landmark là "bản đồ" để người dùng screen reader di chuyển. Thiếu nó, họ buộc phải đi bộ qua từng phần tử. Đây cũng là yêu cầu ngày càng bị soi kỹ về mặt pháp lý ở nhiều thị trường.
Tình huống 3: Bàn giao code giữa hai team thuê ngoài
Một startup ở TP.HCM thuê agency A làm landing page chiến dịch Tết, sau đó chuyển sang agency B để bảo trì. Code của A toàn <div class="box1">, <div class="box2">, <div class="wrapper-inner-2">. Lập trình viên của B mất gần một ngày chỉ để hiểu đâu là header, đâu là phần khuyến mãi, đâu là form đăng ký — vì tên class không nói lên ý nghĩa, mỗi div phải mở ra xem bên trong mới đoán được.
Khi B làm lại, họ dùng <header>, <section class="promo">, <form>, <footer> rõ ràng. Lần bàn giao sau đó cho một dev mới, người này chỉ liếc qua cây HTML là nắm được bố cục trong vài phút.
Bài học: Semantic HTML là tài liệu sống. Cấu trúc tự mô tả giúp người tiếp theo — kể cả chính bạn sau này — đọc hiểu nhanh, giảm chi phí bảo trì.
Hướng dẫn từng bước
Đây là quy trình để chuyển một bố cục bất kỳ sang semantic HTML chuẩn:
Bước 1 — Vẽ sơ đồ vùng (region) trước khi viết code. Nhìn thiết kế và khoanh vùng: đâu là đầu trang, điều hướng, nội dung chính, sidebar, chân trang. Cách tư duy này giống như đọc một bài báo và xác định bố cục trước khi quan tâm màu sắc.
Bước 2 — Chọn landmark cho từng vùng. Đầu trang → <header>. Menu chính → <nav>. Khối nội dung trung tâm → <main> (nhớ: chỉ một). Sidebar → <aside>. Chân trang → <footer>.
Bước 3 — Trong <main>, phân rã thành section/article. Nội dung độc lập (bài viết, sản phẩm) → <article>. Nhóm chủ đề có heading → <section>. Phần chỉ để styling thuần → <div>.
Bước 4 — Dựng cây heading hợp lý. Một <h1> cho chủ đề trang. Mỗi <section>/<article> mở đầu bằng heading cấp phù hợp. Kiểm tra không có chỗ nhảy cấp.
Bước 5 — Dùng thẻ semantic nhỏ đúng chỗ. Hình kèm chú thích → <figure>/<figcaption>. Thời gian → <time>. Danh sách → <ul>/<ol> (đừng dùng <div> cho từng dòng danh sách). Nút bấm hành động → <button>, liên kết điều hướng → <a>.
Bước 6 — Kiểm tra bằng công cụ. Mở DevTools, bật tab Accessibility để xem cây landmark. Dùng tiện ích như HTML5 Outliner hoặc trình kiểm tra accessibility để soi cấu trúc heading. Nếu một screen reader ảo "đọc" được mạch lạc trang của bạn, bạn đã làm đúng.
Lỗi thường gặp & mẹo
Lỗi 1 — "Divitis": dùng div cho mọi thứ. Đây là bệnh phổ biến nhất, đặc biệt khi copy code từ một số trình dựng kéo-thả. Mẹo: trước khi gõ <div>, tự hỏi "có thẻ semantic nào hợp hơn không?". Nếu có, dùng nó.
Lỗi 2 — Nhiều <main> trên một trang. <main> phải duy nhất. Nếu bạn thấy mình cần hai main, nghĩa là bạn đang nhầm — một trong số đó có lẽ nên là <section> hoặc <aside>.
Lỗi 3 — Dùng <div onclick> thay cho <button>. Một <div> gắn sự kiện click trông giống nút nhưng không nhận focus bàn phím, không đọc được bằng screen reader như nút. Luôn dùng <button> cho hành động và <a href> cho điều hướng. Đây là lỗi vừa hỏng accessibility vừa hỏng SEO.
Lỗi 4 — Chọn heading theo cỡ chữ. Đừng đổi <h2> thành <h4> vì muốn nó nhỏ. Giữ đúng thứ bậc ngữ nghĩa, chỉnh cỡ bằng CSS.
Lỗi 5 — Lạm dụng <section>. Không phải cái hộp nào cũng là section. Một section nên có heading và một chủ đề rõ. Nếu nó chỉ là vỏ để layout, dùng <div>.
Mẹo vàng: Semantic HTML phải đúng trước, đẹp sau. Hãy viết cấu trúc có nghĩa trước, rồi mới áp CSS lên. Cấu trúc tốt giúp CSS của bạn cũng gọn gàng hơn, vì bạn có thể nhắm thẳng vào nav a hay article h2 thay vì rừng class.
Bài tập thực hành
- Refactor một trang div sang semantic. Lấy một đoạn HTML toàn
<div class="...">(tự viết hoặc lấy từ một trang cũ của bạn) gồm header, menu, một bài viết, sidebar và footer. Chuyển toàn bộ sang landmark semantic phù hợp. So sánh cây DOM trước và sau.
- Dựng cây heading cho trang chủ. Phác một trang chủ giả định cho một quán cà phê ở Đà Nẵng: tên quán, các mục "Về chúng tôi", "Thực đơn", "Liên hệ". Viết HTML chỉ với heading và landmark, đảm bảo
<h1>duy nhất và thứ bậc không nhảy cấp.
- Kiểm tra accessibility. Mở một trang bạn từng làm bằng Chrome DevTools, vào tab Accessibility, xem cây landmark. Ghi lại những vùng nào không xuất hiện landmark và sửa lại.
- Phân loại section/article/div. Cho 5 khối nội dung (một bình luận người dùng, một thẻ sản phẩm, một nhóm "Câu hỏi thường gặp", một flex container 3 cột, một bài blog). Quyết định mỗi khối nên dùng thẻ gì và giải thích lý do.
Tóm tắt
Semantic HTML là việc chọn đúng thẻ cho đúng vai trò ngữ nghĩa, thay vì nhồi mọi thứ vào <div>. Ba lý do để bạn luôn làm điều này: SEO — Google hiểu được cấu trúc và xếp hạng tốt hơn; Accessibility — screen reader dùng landmark và heading như bản đồ để di chuyển; Maintainability — code tự mô tả, người sau đọc hiểu nhanh, bảo trì rẻ.
Hãy thuộc bộ landmark cốt lõi: <header>, <nav>, <main> (duy nhất), <article>, <section>, <aside>, <footer>. Dùng heading <h1>–<h6> theo thứ bậc ý nghĩa, không theo cỡ chữ. Dùng <button> cho hành động, <a> cho điều hướng. Và đừng sợ <div> — chỉ cần dùng nó đúng việc: làm hộp styling, không phải thay thế cho thẻ có nghĩa.
Khi bạn quen tay, viết semantic không tốn thêm thời gian nào — nó chỉ là thói quen chọn đúng từ. Và đó là khác biệt giữa một người "biết HTML" và một designer web thực thụ.