Buổi 4: HTML (2): ngữ nghĩa, văn bản, bảng, danh sách, liên kết
Hãy tưởng tượng bạn được giao dựng trang web cho một cửa hàng sách nhỏ: có thanh menu trên cùng, vài bài giới thiệu sách mới, bảng giá, danh sách thể loại và những liên kết dẫn sang các trang khác. Bạn đã biết một tài liệu HTML có khung html, head, body, biết thẻ và thuộc tính là gì. Nhưng "biết khung" chưa đủ để dựng một trang thật: bạn cần biết đặt nội dung vào đâu, đánh dấu nó bằng thẻ nào để người đọc, trình duyệt, công cụ tìm kiếm và cả trình đọc màn hình đều hiểu đúng. Buổi này đi qua năm nhóm phần tử HTML mà trang web nào cũng dùng: phần tử ngữ nghĩa, văn bản, bảng biểu, danh sách và liên kết. Sau mỗi nhóm, bạn gõ mã chạy thử ngay trong bài rồi làm các bài tập tương ứng trên Codelab.
Mục tiêu buổi học
- Sau buổi này bạn có thể giải thích thế nào là phần tử ngữ nghĩa (semantic element), phân biệt với phần tử phi ngữ nghĩa
div,span, và dùng đúngmain,section,article,header,footer,nav,aside,figure,figcaption,hr. - Sau buổi này bạn có thể tổ chức nội dung văn bản bằng tiêu đề
h1–h6, đoạn vănp, trích dẫn (blockquote,q,cite),abbr,address,time, các thẻ định dạng (strong,em,mark,del,ins,sub,sup...), ngắt dòngbrvà mã lệnhcode,pre. - Sau buổi này bạn có thể dựng bảng với
table,tr,th,td, gộp ô bằngcolspan,rowspan, thêmcaptionvà chiathead,tbody,tfoot. - Sau buổi này bạn có thể tạo danh sách không thứ tự
ul, có thứ tựol(vớistart, kiểu đánh số) và danh sách định nghĩadl,dt,dd. - Sau buổi này bạn có thể tạo liên kết bằng
avớihref,target,title, liên kết cục bộ, liên kết bằng hình ảnh và liên kết đánh dấu (dấu trang#id).
Bản đồ buổi học
| Phần | Nội dung | Thời lượng gợi ý |
|---|---|---|
| 1. Phần tử ngữ nghĩa | Khái niệm, main, section, article, header, footer, nav, aside, figure, hr |
35 phút |
| 2. Văn bản | Tiêu đề, đoạn văn, định dạng, ngắt dòng, mã lệnh | 35 phút |
| 3. Bảng biểu | Thẻ tạo bảng, gộp hàng cột, tiêu đề bảng, đầu – thân – chân | 35 phút |
| 4. Danh sách | Không thứ tự, có thứ tự, danh sách định nghĩa | 25 phút |
| 5. Liên kết | href, đường dẫn tuyệt đối/tương đối, target, ảnh liên kết, dấu trang |
30 phút |
| Thực hành & ôn tập | Bài 2.2 của giáo trình, câu hỏi ôn tập, bài tập trên Codelab | 20 phút |
Khoảng một nửa thời gian của buổi là thực hành: bạn vừa đọc vừa bấm "Chạy thử", sửa mã rồi chạy lại để thấy thay đổi, sau đó làm nhóm bài tập Codelab tương ứng.
1. Phần tử ngữ nghĩa
Giáo trình: Chương 2 — mục "Phần tử ngữ nghĩa" (Khái niệm về phần tử ngữ nghĩa; section; article; header; footer; nav; aside; figure; hr).
1.1. Khái niệm về phần tử ngữ nghĩa
HTML cung cấp các phần tử ngữ nghĩa (semantic element) để xác định các phần khác nhau của trang web. Một phần tử ngữ nghĩa mô tả rõ ý nghĩa của nó đối với cả máy tính lẫn con người. Chẳng hạn main, article, form, table, figure, figcaption cho biết ngay nội dung bên trong là gì: nội dung chính, một bài viết, một biểu mẫu, một bảng, một hình minh họa kèm chú thích. Ngược lại, div và span là các phần tử phi ngữ nghĩa: chúng không nói gì về nội dung (trừ khi bạn đặt thêm id hoặc class có tên gợi nghĩa). Sử dụng phần tử ngữ nghĩa giúp công cụ tìm kiếm xác định đúng nội dung trang, đồng thời giúp trình đọc màn hình của người khiếm thị tìm nhanh tới vùng cần đọc.
<div class="header"><header><div class="navbar"><nav><div class="content"><main><div class="sidebar"><aside><div class="footer"><footer>id/class.Phần tử ngữ nghĩa nói rõ vai trò của từng vùng; công cụ tìm kiếm và trình đọc màn hình dựa vào đó để hiểu trang, còn div và span thì không nói gì về nội dung.
Sơ đồ trên là một bố cục điển hình: header ở trên cùng, nav chứa menu, main chứa nội dung chính (gồm section/article), aside là thanh bên và footer ở cuối. Hãy đọc nó từ trên xuống dưới và tự hỏi: "vùng này trong trang web thật của mình tên là gì?".
Phần tử main khai báo nội dung chính của tài liệu. Bên trong main có thể chứa các phần (section), bài viết (article), tiêu đề, đoạn văn tùy mục đích của người thiết kế. Giáo trình nhấn mạnh: chỉ nên có một phần tử main trong tài liệu, và nó nên đặt ngang hàng với header, nav, footer. Cấu trúc khung của một Website theo giáo trình gồm header, vùng điều hướng, section, main và footer đều là con trực tiếp của body.
Hãy thử dựng khung này. Bạn không cần CSS, chỉ cần thêm viền tạm thời bằng thuộc tính style để nhìn thấy từng vùng:
<header style="border:2px solid #2563eb;padding:6px">header — đầu trang</header>
<nav style="border:2px solid #16a34a;padding:6px">nav — menu</nav>
<main style="border:2px solid #dc2626;padding:6px">
main — nội dung chính (chỉ một cái)
<section style="border:1px dashed #9333ea;margin:6px;padding:6px">section — một phần</section>
<article style="border:1px dashed #ea580c;margin:6px;padding:6px">article — một bài viết</article>
</main>
<footer style="border:2px solid #475569;padding:6px">footer — chân trang</footer>Mỗi phần tử là một khối riêng xếp chồng theo đúng thứ tự mã nguồn. Điều đáng chú ý là trên màn hình chúng gần như giống div (mặc định đều là phần tử khối), nhưng ý nghĩa thì khác hẳn: máy biết nav là menu, footer là chân trang.
Để chọn đúng thẻ cho từng vùng trang, hãy dùng mô phỏng sau: chọn một vùng trên trang mẫu, mô phỏng sẽ cho biết thẻ ngữ nghĩa phù hợp.
Chọn phần tử ngữ nghĩa cho từng vùng trang
khám phá rồi thử tháchDùng khi: Chứa logo, tiêu đề, phần giới thiệu ở đầu trang hoặc đầu một bài viết.
💡 Dùng được nhiều lần: một cho cả trang, và một cho mỗi article/section.
<header><h1>NEU Codelab</h1></header>
Giáo trình: Nhà trường có công cụ "Bản đồ thẻ ngữ nghĩa" tại fit.neu.edu.vn/smartdoc/congcu/web-ban-do-the-ngu-nghia.html để tra nhanh các thẻ ngữ nghĩa — mô phỏng bên trên đóng vai trò tương tự.
Lưu ý: Phần tử ngữ nghĩa không tự làm trang đẹp hơn. Nó giúp trang dễ hiểu hơn với máy, còn đẹp hay không là việc của CSS (buổi 6–9).
1.2. Phần tử section
Phần tử section đánh dấu một phần của tài liệu. Đây là một trong những phần tử ngữ nghĩa dùng để khai báo cấu trúc trang, giúp việc đọc hiểu và xử lý trang trở nên dễ dàng. section thường nhóm các nội dung liên quan với nhau về mặt ngữ nghĩa: các đoạn văn, hình ảnh hay video có cùng chủ đề.
Ví dụ trong giáo trình dùng section để nhóm thông tin tác giả: họ tên, ảnh đại diện, câu nói yêu thích, hòm thư, điện thoại, địa chỉ. Ví dụ dưới đây rút gọn từ đó (ảnh đại diện thay bằng hình vẽ nhúng sẵn để chạy được mà không cần tệp ngoài):
<section>
<h2>Phạm Dương Minh</h2>
<img id="avatar" height="80" alt="Avatar"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='80' height='80'%3E%3Ccircle cx='40' cy='40' r='38' fill='%2393c5fd'/%3E%3C/svg%3E">
<q style="display: block" id="myquote">Nếu không có đam mê, sẽ không có năng lượng</q>
<div class="contact">
<h4 class="contact-title">Hòm thư:</h4>
<a href="mailto:[email protected]" id="info-email">[email protected]</a>
<h4 class="contact-title">Điện thoại:</h4>
<a href="tel:+84912345679" id="phone">+84912345679</a>
<h4 class="contact-title">Địa chỉ:</h4>
<a href="https://www.google.com/maps" target="_blank" id="info-address">207 Giải phóng</a>
</div>
</section>Bạn thấy trong ví dụ có một div bao các thông tin liên hệ: div ở đây chỉ để gom nhóm phục vụ CSS, còn section là đơn vị ý nghĩa. Một quy tắc nhỏ: nếu nhóm nội dung có thể đặt một tiêu đề (h2...) thì nhiều khả năng đó là section; nếu chỉ để gom cho dễ tạo kiểu thì dùng div.
1.3. Phần tử article
Phần tử article xác định một bài viết: có thể là bài trên nhật ký (blog), tạp chí, một tin tức, hay một bình luận. Một trang có thể có nhiều bài viết và thường có chung một cấu trúc. Điểm nhận biết: nếu bạn tách article ra khỏi trang và dán sang nơi khác, nó vẫn đứng được một mình và có nghĩa.
Ví dụ của giáo trình, một bài viết giới thiệu ngôn ngữ HTML, có tiêu đề, ngày đăng gắn thẻ time (có thuộc tính datetime để máy đọc được), ảnh minh họa dẫn tới bài đầy đủ, từ viết tắt abbr và liên kết "Đọc thêm":
<article>
<h2>Ngôn ngữ đánh dấu văn bản HTML</h2>
<h3>Ngày đăng:
<time datetime="2022-10-25">25/10/2022</time>
</h3>
<div class="content">
<a href="article.html"><img alt="HTML" height="60"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='60'%3E%3Crect width='100' height='60' fill='%23fdba74'/%3E%3C/svg%3E"></a>
<div>
<p><em>Ngôn ngữ HTML là gì?</em></p>
<p><abbr title="Hypertext Markup Language">HTML</abbr> là ngôn ngữ đánh dấu dùng để xây dựng và cấu trúc lại các thành phần có trong Website...</p>
</div>
</div>
<a class="readmore" href="article.html">Đọc thêm</a>
</article>Trong một bài viết có thể có phần nội dung chi tiết, phần tổng kết, kết luận. Những nội dung này cũng được khai báo bằng các phần tử details và summary. Hai phần tử này tạo ra một khối đóng/mở mà không cần JavaScript:
<article>
<h2>Kết luận bài viết</h2>
<details open>
<summary>Xem phần tổng kết</summary>
<p>HTML mô tả cấu trúc, CSS lo trình bày, JavaScript lo hành vi.</p>
</details>
</article>Mở rộng:
detailscó thuộc tínhopenđể mặc định mở. Khi sinh viên bấm vào dòngsummary, nội dung bên dưới được ẩn/hiện mà không cần một dòng JavaScript nào.
1.4. Phần tử header
Phần tử header chứa phần đầu của một khối nội dung. Đó có thể là phần đầu của cả trang web, hoặc đơn giản là phần đầu của một bài viết. Ví dụ giáo trình đặt header bên trong article để chứa tiêu đề và câu mở đầu của bài:
<article>
<header>
<h1>What Does WWF Do?</h1>
<p>WWF's mission:</p>
</header>
<p>WWF's mission is to stop the degradation of our planet's natural environment,
and build a future in which humans live in harmony with nature.</p>
</article>Hãy phân biệt: header (thẻ ngữ nghĩa) khác head (phần đầu tài liệu) học ở buổi 3. head chứa siêu dữ liệu không hiển thị (tiêu đề tab, meta, favicon), còn header nằm trong body và hiển thị cho người đọc.
1.5. Phần tử footer
Phần tử footer thường chứa thông tin về tác giả, bản quyền, liên kết tới điều khoản sử dụng, thông tin liên hệ... Phần chân này có thể là chân của cả tài liệu, hoặc chân của một bài viết, một nhóm bài viết. Ví dụ giáo trình dùng footer cho một bài viết:
<article>
<h2>Học HTML thật dễ</h2>
<p>Nội dung bài viết...</p>
<footer>
<p>Đăng bởi: Trần Tuấn Anh</p>
<p>Liên hệ <a href="mailto:[email protected]">[email protected]</a></p>
</footer>
</article>1.6. Phần tử nav
Phần tử nav xác định một khu vực điều hướng. Bên trong nav thường là các liên kết phục vụ việc điều hướng, chẳng hạn menu chính của website. Trình đọc màn hình dùng nav để cho phép người dùng nhảy thẳng tới menu hoặc bỏ qua nó.
<nav>
<a href="/html/">HTML</a> |
<a href="/css/">CSS</a> |
<a href="/js/">JavaScript </a> |
<a href="/jquery/">jQuery</a>
</nav>Mẹo: Không phải mọi nhóm liên kết đều cần
nav; chỉ dùng cho các khối điều hướng chính (menu chính, mục lục, phân trang). Một vài liên kết lẻ trongfooterthì không cần.
1.7. Phần tử aside
Phần tử aside xác định nội dung nằm ngoài nội dung chính của tài liệu, ví dụ một thanh bên (sidebar). Các aside thường là nội dung liên quan hoặc bổ trợ cho nội dung chính: ghi chú, quảng cáo, bài viết liên quan, tiểu sử tác giả.
<p>Đoạn văn</p>
<aside>
<h4>Tiêu đề phụ</h4>
<p>Đoạn văn trong tiêu đề phụ</p>
</aside>1.8. Phần tử figure
Phần tử figure kết hợp với figcaption dùng để nhóm một hình (ảnh, sơ đồ, đoạn mã) với chú thích của nó. Nhờ vậy ảnh và lời chú thích là một khối thống nhất, máy biết caption thuộc về ảnh nào.
<figure>
<img src="university.jpg" alt="University" width="120" height="60">
<figcaption>Hình 1.3 Trường Đại học</figcaption>
</figure>Ảnh university.jpg không có thật nên trình duyệt hiển thị biểu tượng ảnh lỗi cùng chữ thay thế alt — nhưng bạn vẫn thấy rõ chú thích figcaption nằm ngay dưới ảnh. Thuộc tính alt luôn nên có: nó là mô tả cho người dùng khiếm thị và hiển thị khi ảnh không tải được.
1.9. Phần tử hr
Phần tử hr xác định ngắt theo chủ đề trong trang HTML, thường hiển thị dưới dạng một đường kẻ ngang. Nó dùng để tách nội dung hoặc đánh dấu sự thay đổi chủ đề. Giáo trình lấy ví dụ hai bài viết được tách bởi hr; bạn có thể đổi màu, độ dày đường kẻ bằng CSS.
<article>
<h2>Ngôn ngữ đánh dấu văn bản HTML</h2>
<h3>Ngày đăng: 25/10/2022</h3>
<p>HTML viết tắt của Hypertext Markup Language là ngôn ngữ đánh dấu văn bản.</p>
</article>
<hr>
<article>
<h2>Bảng các thuộc tính CSS</h2>
<h3>Ngày đăng: 21/10/2022</h3>
<p>Đây là bảng liệt kê các thuộc tính được sử dụng trong CSS.</p>
</article>Giáo trình lưu ý thêm: các phần tử ngữ nghĩa có thể lồng nhau. Ví dụ section chứa các article, và các article đó lại có thể chứa section bên trong. Tuy nhiên đừng lồng quá nhiều tầng, vì như vậy việc phân tích cú pháp để hiểu nội dung tài liệu sẽ khó khăn hơn.
1.10. So sánh nhanh các phần tử ngữ nghĩa
| Phần tử | Dùng để | Ví dụ điển hình |
|---|---|---|
main |
Nội dung chính của trang (chỉ một) | Phần giữa trang, sau menu, trước chân trang |
section |
Một phần có chủ đề, thường có tiêu đề | "Giới thiệu", "Kỹ năng" |
article |
Bài viết độc lập, tự đứng được | Tin tức, bài blog, bình luận |
header |
Phần đầu của trang/bài viết | Logo + tiêu đề, tiêu đề bài |
footer |
Phần chân của trang/bài viết | Bản quyền, tác giả, liên hệ |
nav |
Khu vực điều hướng chính | Menu, mục lục |
aside |
Nội dung phụ, ngoài mạch chính | Thanh bên, ghi chú |
figure + figcaption |
Hình kèm chú thích | Ảnh, sơ đồ, biểu đồ |
hr |
Ngắt chủ đề | Đường kẻ ngang giữa hai chủ đề |
Vừa học xong các phần tử ngữ nghĩa, hãy làm nhóm bài 4.1 trên Codelab: bạn sẽ dựng khung trang với header, nav, main, footer, bọc ảnh bằng figure và viết một bài blog hoàn chỉnh. Chú ý chọn thẻ theo ý nghĩa, không theo hình dáng.
2. Văn bản
Giáo trình: Chương 2 — mục "Văn bản" (Tiêu đề; Đoạn văn; Định dạng văn bản; Ngắt dòng; Mã lệnh).
2.1. Tiêu đề
Tiêu đề và đoạn văn là những thành phần phổ biến nhất của một trang web. Tiêu đề (heading) luôn chứa nội dung quan trọng. Một tài liệu có thể có nhiều mức tiêu đề, xác định bằng các thẻ từ h1 đến h6. Thẻ h1 (tiêu đề mức 1) chứa nội dung quan trọng nhất; h2 dùng cho nội dung ít quan trọng hơn; tiếp đến h3 tới h6 giảm dần mức độ quan trọng. Mỗi tiêu đề có cỡ chữ mặc định như bảng sau:
| Phần tử | Mô tả |
|---|---|
h1 |
Tiêu đề mức 1, chữ đậm, cỡ chữ bằng 200% chữ thường |
h2 |
Tiêu đề mức 2, chữ đậm, cỡ chữ bằng 150% chữ thường |
h3 |
Tiêu đề mức 3, chữ đậm, cỡ chữ bằng 117% chữ thường |
h4 |
Tiêu đề mức 4, chữ đậm, cỡ chữ bằng 100% chữ thường |
h5 |
Tiêu đề mức 5, chữ đậm, cỡ chữ bằng 83% chữ thường |
h6 |
Tiêu đề mức 6, chữ đậm, cỡ chữ bằng 67% chữ thường |
Chạy đoạn mã sau để thấy sáu mức tiêu đề cạnh một dòng chữ thường (giáo trình ghi chú "cỡ chữ bình thường" để so sánh):
Cỡ chữ bình thường
<h1>Tiêu đề mức 1</h1>
<h2>Tiêu đề mức 2</h2>
<h3>Tiêu đề mức 3</h3>
<h4>Tiêu đề mức 4</h4>
<h5>Tiêu đề mức 5</h5>
<h6>Tiêu đề mức 6</h6>Bạn có thể chỉ định kích thước cho bất kỳ tiêu đề nào bằng thuộc tính style với font-size của CSS, ví dụ <h1 style="font-size:60px;">Tiêu đề mức 1</h1>. Trình duyệt tự động thêm một khoảng trắng cách lề (margin) trước và sau tiêu đề.
Vì sao tiêu đề quan trọng hơn "chữ to"? Công cụ tìm kiếm dùng tiêu đề để lập chỉ mục cấu trúc và nội dung trang; người dùng lướt qua trang và thường đọc tiêu đề trước, sau đó mới đọc tiêu đề phụ và nội dung. Vì vậy cần dùng tiêu đề để thể hiện cấu trúc tài liệu một cách hợp lý. Ví dụ giáo trình: h1 cho tiêu đề chính "BÀI VIẾT", h2 cho tên từng bài, h3 cho ngày đăng:
<h1>BÀI VIẾT</h1>
<article>
<h2>Ngôn ngữ đánh dấu văn bản HTML</h2>
<h3>Ngày đăng: <time datetime="2022-10-25">25/10/2022</time></h3>
<div>
<p><em>Ngôn ngữ HTML là gì?</em></p>
HTML viết tắt của <strong>Hypertext Markup Language</strong> là ngôn ngữ đánh dấu dùng để xây
dựng và cấu trúc lại các thành phần có trong Website...
</div>
<a class="readmore" href="article.html">Đọc thêm</a>
</article>Cảnh báo: Giáo trình dặn rõ: chỉ dùng
h1–h6cho tiêu đề, không dùng để tạo chữ to hoặc chữ đậm. Việc định dạng hiển thị như cỡ chữ, độ đậm là công việc của CSS. Đừng chọnh3chỉ vì "muốn chữ nhỏ hơn", và đừng nhảy cóc từh1xuốngh4.
2.2. Đoạn văn
Các tài liệu dài thường có nhiều đoạn văn, tạo bởi phần tử p (paragraph). Giống tiêu đề, p là phần tử khối: mặc định chiếm toàn bộ chiều rộng của tài liệu và bắt đầu trên dòng mới. Trình duyệt tự thêm khoảng trắng trước và sau đoạn; muốn chỉnh khoảng cách này, hãy dùng margin và padding trong CSS.
Điều rất dễ nhầm với người mới: khoảng trắng thừa và dấu xuống dòng trong mã nguồn HTML không có ý nghĩa. Trình duyệt gộp mọi khoảng trắng và dòng thừa thành một dấu cách khi hiển thị. Bạn hãy chạy thử và quan sát: mã nguồn viết ba dòng nhưng kết quả vẫn là một câu liền mạch.
<p>Ngôn ngữ
HTML là gì?
Mã nguồn xuống dòng nhưng trình duyệt vẫn gộp lại.</p>
<p>Đoạn thứ hai nằm riêng vì là một phần tử <code>p</code> khác.</p>Nếu chủ ý muốn xuống dòng, phải dùng phần tử ngắt dòng br (mục 2.4).
Ngoài p, giáo trình giới thiệu một nhóm phần tử văn bản có ngữ nghĩa riêng:
blockquote— nội dung trích dẫn dài từ nguồn khác (phần tử khối); trình duyệt mặc định thụt lề. Thuộc tínhciteghi địa chỉ nguồn.q— trích dẫn ngắn; là phần tử nội tuyến, trình duyệt thường tự chèn dấu ngoặc kép; muốn đứng riêng một dòng cần đặtdisplay: block.abbr— từ/cụm từ viết tắt; thuộc tínhtitlechứa nghĩa đầy đủ, hiện ra khi rê chuột. Đánh dấu viết tắt giúp công cụ tìm kiếm tìm được cả bằng từ viết tắt lẫn từ đầy đủ.address— thông tin liên hệ (tác giả/chủ sở hữu) của nội dung; thường hiển thị chữ nghiêng.cite— tham chiếu tới một tác phẩm (sách, bức tranh, bài thơ...); thường hiển thị chữ nghiêng.time— thời gian; nên kèm thuộc tínhdatetimeđể máy đọc được.
Hãy xem tất cả cùng nhau trong một ví dụ nhỏ (trích từ các ví dụ của giáo trình):
<p>Đây là một trích dẫn từ trang Web của WWF:</p>
<blockquote cite="http://www.worldwildlife.org/who/index.html">WWF hoạt động ở 100 quốc gia và được hỗ trợ bởi 1,2 triệu thành viên ở Hoa Kỳ và gần 5 triệu trên toàn cầu với mục tiêu bảo vệ thiên nhiên</blockquote>
<p>Câu nói yêu thích:</p>
<q style="display: block">Nếu không có đam mê, sẽ không có năng lượng</q>
<p><abbr title="Hypertext Markup Language">HTML</abbr> là ngôn ngữ đánh dấu dùng để xây dựng và cấu trúc lại các thành phần có trong Website...</p>
<address>
Biên tập bởi Dương Minh<br>
Trang chủ: https://minh-blogs.web.app
</address>
<p><cite>Tác phẩm Tiếng thét (The Scream)</cite> được sáng tác bởi Edvard Munch năm 1893</p>
<p>Ngày đăng: <time datetime="2022-12-01">1/12/2022</time></p>Hãy rê chuột lên chữ "HTML" trong khung xem trước: trình duyệt hiện ra "Hypertext Markup Language". Quan sát cả sự khác nhau giữa blockquote (khối, thụt lề) và q (nội tuyến, có ngoặc kép).
Giáo trình còn nhắc: có rất nhiều thẻ khác liên quan đến văn bản. Với văn bản dùng hệ chữ không phải Latinh (như chữ Hán, Nhật) người thiết kế có thể phải dùng thêm ruby và rt để chú âm. Người thiết kế web cần thường xuyên cập nhật các phần tử mới xuất hiện trong các phiên bản HTML.
Mở rộng:
rubybọc ký tự gốc,rtchứa phần chú âm hiển thị nhỏ phía trên. Ví dụruby 漢 rt kanhiện cách đọc phía trên chữ Hán. Bạn chưa cần dùng thường xuyên, chỉ cần biết là có.
2.3. Định dạng văn bản
Trong văn bản, những nội dung quan trọng cần nhấn mạnh để người đọc tập trung hơn. HTML có một nhóm phần tử định dạng:
| Thẻ | Ý nghĩa |
|---|---|
b |
Chữ in đậm |
strong |
Chữ chứa nội dung quan trọng |
i |
Chữ in nghiêng |
em |
Nội dung nhấn mạnh trong văn bản |
mark |
Đánh dấu văn bản |
small |
Văn bản chữ nhỏ |
del |
Văn bản bị xóa |
s |
Văn bản không còn đúng nữa |
u |
Văn bản viết sai (chính tả) |
ins |
Văn bản chèn thêm |
sub |
Chỉ số dưới |
sup |
Chỉ số trên |
Trong quá khứ, định dạng bằng b, i rất phổ biến. Ngày nay, để định dạng hiển thị, người thiết kế ưu tiên dùng thuộc tính CSS (học ở buổi 6–7). Phần quan trọng cần hiểu là bản chất ngữ nghĩa:
bchỉ xác định chữ in đậm, không mang nghĩa quan trọng;strongxác định nội dung quan trọng về mặt ngữ nghĩa.ichỉ xác định chữ in nghiêng;emxác định nội dung được nhấn mạnh.
Bên ngoài trình duyệt, b và strong trông giống nhau, nhưng máy tính và công cụ tìm kiếm (và trình đọc màn hình, đọc strong với giọng nhấn) biết đâu là nội dung quan trọng của tài liệu. Hãy chạy ví dụ so sánh:
<b>Văn bản sử dụng thẻ b</b><br>
<strong>Văn bản sử dụng thẻ strong</strong><br>
<i>Văn bản sử dụng thẻ i</i><br>
<em>Văn bản sử dụng thẻ em</em>Thẻ del định nghĩa văn bản đã xóa, thẻ ins xác định văn bản được chèn thêm; cả hai cho biết dữ liệu vừa được thêm vào hoặc xóa khỏi văn bản. Ví dụ thể hiện màu blue bị thay bằng red, hoặc từ color mới được thêm vào câu. Còn sub là chỉ số dưới, sup là chỉ số trên:
<p>My favorite color is <del>blue</del> red.</p>
<p>My favorite <ins>color</ins> is red.</p>
<p>This text contains <sup>superscript</sup> text.</p>
<p>This text contains <sub>subscript</sub> text.</p>
<p>Công thức nước: H<sub>2</sub>O, diện tích: 5 m<sup>2</sup>.</p>
<p>Từ <mark>quan trọng</mark> được tô nổi, còn <small>ghi chú nhỏ</small> thì chữ nhỏ hơn.</p>Bạn nhận thấy del gạch ngang, ins gạch chân, sup nâng chữ lên, sub hạ chữ xuống, mark tô nền vàng, small nhỏ hơn bình thường.
Mẹo: Quy tắc chọn thẻ: hỏi "tại sao mình muốn chữ này đậm?". Nếu vì nó quan trọng →
strong; nếu chỉ muốn đổi kiểu (ví dụ tên sản phẩm) → dùngbhoặc tốt hơn làspankèm CSS.
2.4. Ngắt dòng
Phần tử br xác định việc ngắt dòng trong văn bản. Bạn dùng br khi muốn xuống một dòng mới mà không bắt đầu một đoạn mới. Giáo trình lưu ý: br là phần tử rỗng — nó không có nội dung và không có thẻ đóng.
<p>Một đoạn văn bản sử dụng <br> ngắt dòng</p>
<p>Trình bày bài thơ:<br>
Sáng nay trời nắng đẹp<br>
Em đi học một mình<br>
Cặp sách vui theo gió</p>Điểm khác nhau cần nhớ: p tạo đoạn mới (có khoảng cách trước/sau), còn br chỉ xuống dòng trong cùng một đoạn. Lạm dụng nhiều br liên tiếp để tạo khoảng trống là cách làm xấu; hãy dùng margin/padding của CSS.
2.5. Mã lệnh
Khi cần biểu diễn mã lệnh máy tính (code) trên trang web, dùng thẻ code: trình duyệt dùng phông chữ phù hợp (đơn cách) để hiển thị. Tuy vậy, nhiều dòng mã bọc bằng code sẽ bị dồn thành một dòng vì khoảng trắng và dấu xuống dòng bị bỏ qua (như đã nói ở mục 2.2). Có hai cách: thêm br cuối mỗi dòng, hoặc đơn giản hơn là bao nội dung bằng thẻ pre — phần tử khai báo nội dung đã định dạng sẵn (preformatted text), giữ nguyên khoảng trắng và xuống dòng. Chạy hai khối dưới đây để so sánh cùng một đoạn mã Java trong giáo trình:
<p>Chỉ dùng code:</p>
<code>
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
</code>
<p>Dùng pre + code:</p>
<pre>
<code>
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, World!");
}
}
</code>
</pre>Kết quả: khối trên bị dồn thành một dòng, khối dưới giữ nguyên cách trình bày, kể cả thụt lề. Đây cũng là lý do bạn thường thấy cặp pre + code trong các trang tài liệu lập trình.
Lưu ý: Muốn hiển thị chính các ký tự
<và>trong mã HTML mẫu, phải viết dưới dạng thực thể<và>, nếu không trình duyệt sẽ hiểu đó là thẻ thật và biến mất khỏi trang.
Dưới đây là bảng tổng hợp các phần tử văn bản trong mục này:
| Nhóm | Phần tử | Loại hiển thị | Ghi nhớ |
|---|---|---|---|
| Tiêu đề | h1–h6 |
Khối | h1 quan trọng nhất; không dùng để làm chữ to |
| Đoạn | p, blockquote |
Khối | Khoảng trắng mã nguồn bị gộp |
| Trích/nhãn | q, abbr, cite, time |
Nội tuyến | abbr có title, time có datetime |
| Liên hệ | address |
Khối | Thông tin tác giả/chủ sở hữu |
| Định dạng | b/strong, i/em, mark, small, del/s, ins/u, sub/sup |
Nội tuyến | Ưu tiên ngữ nghĩa, CSS lo hiển thị |
| Ngắt dòng | br |
Rỗng | Không có thẻ đóng |
| Mã | code, pre |
code nội tuyến, pre khối |
pre giữ nguyên định dạng |
Vừa học xong phần văn bản, hãy làm nhóm bài 4.2: bạn sẽ dùng các thẻ định dạng đặc biệt, xuống dòng đúng chỗ khi trình bày một bài thơ và chèn trích dẫn vào bài viết. Hãy kiểm tra mình đã chọn đúng thẻ theo ý nghĩa (ví dụ strong thay vì b khi nội dung quan trọng).
3. Bảng biểu
Giáo trình: Chương 2 — mục "Bảng biểu" (Các thẻ tạo bảng; Gộp hàng, cột; Tiêu đề cho bảng; Đầu, thân và chân bảng).
Các bảng (table) cho phép sắp xếp dữ liệu vào các ô nằm trên các hàng và cột. Để khai báo một bảng trong tài liệu HTML, ta dùng bốn phần tử chính:
table: phần tử gốc, định nghĩa cả bảng.tr(table row): định nghĩa một dòng (row) trong bảng.td(table data): định nghĩa một ô dữ liệu (cell).th(table header): định nghĩa một ô tiêu đề (header cell).
Một bảng đã được định dạng giao diện đẹp (có hàng tiêu đề đậm màu, các dòng xen kẽ) thường trông như sản phẩm của CSS; bản thân HTML chỉ lo cấu trúc hàng/cột.
3.1. Các thẻ tạo bảng
Bảng được tạo bằng thẻ table. Trong đó thẻ tr tạo các dòng và thẻ td tạo các ô dữ liệu. Ví dụ giáo trình mô tả hai thuộc tính CSS:
<table>
<tr>
<th>Thuộc tính</th>
<th>Mô tả</th>
</tr>
<tr>
<td>accent-color</td>
<td>Thuộc tính xác định màu sắc của các điều khiển</td>
</tr>
<tr>
<td>align-content</td>
<td>Thuộc tính xác định căn chỉnh cho các item trong một hộp chứa</td>
</tr>
</table>Hãy đọc kết quả: các tr là các dòng, các td là cột dữ liệu. Thẻ th tạo ô tiêu đề cho một hàng hoặc một cột dữ liệu; mặc định chữ đậm và căn giữa. Thông thường ta đặt hàng đầu tiên làm tiêu đề, nhưng cũng có thể dùng th ở bất kỳ hàng nào (ví dụ cột đầu mỗi hàng).
Quan sát thấy bảng không có đường viền theo mặc định. Muốn thêm viền, giáo trình dùng thuộc tính style với border, và border-collapse: collapse ở table để gộp viền các ô thành một nét:
<table style="border-collapse: collapse;">
<tr>
<th style="border: 1px solid black">Thuộc tính</th>
<th style="border: 1px solid black">Mô tả</th>
</tr>
<tr>
<td style="border: 1px solid black">accent-color</td>
<td style="border: 1px solid black">Thuộc tính xác định màu sắc của các điều khiển</td>
</tr>
<tr>
<td style="border: 1px solid black">align-content</td>
<td style="border: 1px solid black">Thuộc tính xác định căn chỉnh cho các item trong một hộp chứa</td>
</tr>
</table>Lưu ý: Một giao diện dạng bảng có thể tạo bằng nhiều cách khác nhau (
div, flexbox, grid...). Tuy nhiên hãy dùngtablekhi nội dung thật sự là dữ liệu dạng bảng (điểm số, giá cả, lịch học); đừng dùng bảng để dàn bố cục trang.
Mẹo: Viết
stylelặp lại ở từng ô như trên rất dài. Từ buổi 6 bạn sẽ học viết một quy tắc CSSth, td { border: 1px solid black; }dùng chung cho mọi ô.
Bạn muốn tự dựng một bảng và kéo thử số hàng, số cột? Hãy dùng mô phỏng sau trước khi sang phần gộp ô.
Xây bảng HTML: gộp ô bằng colspan và rowspan
chọn ô, kéo núm ở góc dưới phải hoặc bấm +/−| Column 1 | Column 2 | Column 3 |
|---|---|---|
| Row 1 Cell 1 | Row 1 Cell 2 | Row 1 Cell 3 |
| Row 2 Cell 2 | Row 2 Cell 3 | |
| Row 3 Cell 1 | ||
<th>/<td>. Phải xóa thẻ của 3 ô bị che: Ô 2.1, Ô 3.2, Ô 3.3. Hàng đầu dùng <th>.3.2. Gộp hàng, cột
Khi cần một ô chiếm nhiều cột hoặc nhiều hàng, ta dùng hai thuộc tính:
colspan: gộp hai hay nhiều cột thành một ô (ô trải ngang).rowspan: gộp hai hay nhiều hàng thành một ô (ô trải dọc).
<thead> phần đầu<tbody> phần thân<tfoot> phần chânô được gộp| Môn họcrowspan=2 | Điểmcolspan=2 | Kết quảrowspan=2 | |
|---|---|---|---|
| Quá trình | Cuối kỳ | ||
| HTML | 8,0 | 9,0 | Đạt |
| CSS | 7,5 | 8,0 | Đạt |
| JavaScript | 6,0 | 9,0 | Đạt |
| Trung bình điểm cuối kỳcolspan=3 | 8,7 | ||
<td colspan="2">A</td>Gộp ngang: hàng đó bớt một ô td.
<td rowspan="2">A</td>Gộp dọc: hàng dưới bớt một ô td.
<table> <caption>Bảng điểm…</caption><thead><tr><th rowspan="2">Môn học</th><th colspan="2">Điểm</th><th rowspan="2">Kết quả</th></tr><tr><th>Quá trình</th><th>Cuối kỳ</th></tr></thead><tbody> … các hàng <tr> dữ liệu … </tbody><tfoot><tr><td colspan="3">Trung bình…</td><td>8,7</td></tr></tfoot></table>
Hàng đầu của thead chỉ có 3 ô th vì hai ô rowspan chiếm luôn chỗ ở hàng thứ hai, nên hàng thứ hai chỉ còn 2 ô th. Chỉ gộp ô khi thật cần để bảng rõ ràng.
colspan gộp các ô theo chiều ngang, rowspan gộp theo chiều dọc; thead, tbody, tfoot chia bảng thành phần đầu, phần thân dữ liệu và phần chân tổng kết.
Sơ đồ cho thấy cách ô gộp "chiếm chỗ" của các ô khác: khi một ô có rowspan="2" thì ở dòng kế tiếp bạn bỏ bớt một td vì vị trí đó đã bị ô trên chiếm. Tương tự, ô colspan="3" thay thế ba td trong cùng dòng. Ví dụ của giáo trình dùng bảng 3 cột; ô "Row 1 Cell 1" gộp 2 hàng, ô "Row 3 Cell 1" gộp 3 cột:
<table style="border-collapse: collapse;">
<tr>
<th style="border: 1px solid black">Column 1</th>
<th style="border: 1px solid black">Column 2</th>
<th style="border: 1px solid black">Column 3</th>
</tr>
<tr>
<td rowspan="2" style="border: 1px solid black">Row 1 Cell 1</td>
<td style="border: 1px solid black">Row 1 Cell 2</td>
<td style="border: 1px solid black">Row 1 Cell 3</td>
</tr>
<tr>
<td style="border: 1px solid black">Row 2 Cell 2</td>
<td style="border: 1px solid black">Row 2 Cell 3</td>
</tr>
<tr>
<td colspan="3" style="border: 1px solid black">Row 3 Cell 1</td>
</tr>
</table>Đếm số ô thực tế mỗi dòng: dòng 2 có 3 ô (kể cả ô gộp), dòng 3 chỉ có 2 ô (vì ô đầu bị rowspan của dòng trên chiếm), dòng 4 chỉ có 1 ô colspan="3". Một cách kiểm tra nhanh là cộng colspan các ô của mỗi dòng (và tính cả ô rowspan từ dòng trên): tổng luôn bằng số cột của bảng.
Để tự kiểm chứng điều này bằng mã, ví dụ JavaScript dưới đây đếm số cột "thực" mỗi dòng của bảng vừa tạo (bạn chưa cần hiểu hết DOM, nó chỉ minh họa quy tắc):
<table id="t" border="1">
<tr><th>A</th><th>B</th><th>C</th></tr>
<tr><td rowspan="2">1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td></tr>
<tr><td colspan="3">6</td></tr>
</table>
<script>
document.querySelectorAll("#t tr").forEach((tr, i) => {
const span = [...tr.children].reduce((s, c) => s + (c.colSpan || 1), 0);
console.log("Dòng " + (i + 1) + ": " + tr.children.length + " ô, tổng colspan = " + span);
});
</script>Kết quả: dòng 1 có 3 ô, dòng 2 có 3 ô, dòng 3 có 2 ô (vì ô trên đã chiếm một chỗ), dòng 4 có 1 ô với tổng colspan 3.
Cảnh báo: Giáo trình lưu ý chỉ dùng
rowspan,colspankhi cần thiết để giúp bố cục bảng rõ ràng và tránh dùng quá nhiều. Đếm thiếu/thừa ô là nguyên nhân phổ biến nhất khiến bảng "lệch cột".
Nhà trường có công cụ tra cứu "Bảng HTML: colspan và rowspan" tại fit.neu.edu.vn/smartdoc/congcu/web-bang-html-gop-o.html để bạn tự kéo thử các ô.
3.3. Tiêu đề cho bảng
Bảng có thể có tiêu đề nhờ phần tử caption: đó là tên của bảng hoặc lời giải thích. Mặc định tiêu đề xuất hiện phía trên bảng. caption phải là con trực tiếp, đặt ngay sau thẻ mở table.
<table border="1">
<caption>Tiêu đề</caption>
<tr>
<td>Cột 1, Hàng 1</td><td>Cột 2, Hàng 1</td>
</tr>
<tr>
<td>Cột 1, Hàng 2</td><td>Cột 2, Hàng 2</td>
</tr>
</table>Muốn tiêu đề xuất hiện ở vị trí khác, thêm thuộc tính CSS caption-side. Ví dụ đưa tiêu đề xuống cuối bảng: <caption style="caption-side:bottom">Tiêu đề</caption>. Hãy chạy thử:
<table border="1">
<caption style="caption-side:bottom">Tiêu đề (đặt ở dưới)</caption>
<tr>
<td>Cột 1, Hàng 1</td><td>Cột 2, Hàng 1</td>
</tr>
<tr>
<td>Cột 1, Hàng 2</td><td>Cột 2, Hàng 2</td>
</tr>
</table>Mở rộng: Với trình đọc màn hình,
captionlà tên của bảng được đọc đầu tiên nên rất có giá trị cho khả năng tiếp cận (accessibility), tốt hơn một đoạnpđặt gần đó.
3.4. Đầu, thân và chân bảng
Một bảng đầy đủ có thể chia thành ba phần: phần đầu, phần thân chứa dữ liệu và phần chân chứa nội dung tổng kết hoặc ghi chú. Ba phần này khai báo bằng:
thead— phần đầu bảng;tbody— phần thân bảng;tfoot— phần chân bảng.
Cách chia này làm cấu trúc rõ ràng, thuận lợi cho định dạng CSS riêng từng phần, và cho trình duyệt/máy in lặp lại phần đầu khi bảng dài. Ví dụ giáo trình (hàng tiêu đề và hàng chân đều dùng colspan="4" trải hết bốn cột):
<table border="1">
<thead>
<tr>
<td colspan="4">Phần tiêu đề bảng</td>
</tr>
</thead>
<tbody>
<tr>
<td>Cột 1</td>
<td>Cột 2</td>
<td>Cột 3</td>
<td>Cột 4</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="4">Phần chân bảng</td>
</tr>
</tfoot>
</table>Hãy áp dụng cho một bảng thực tế hơn: bảng điểm có dòng tổng kết ở chân. Ở đây dùng th cho tiêu đề cột trong thead và tfoot cho điểm trung bình.
<table border="1" style="border-collapse: collapse">
<caption>Bảng điểm học kỳ</caption>
<thead>
<tr><th>Môn</th><th>Số tín chỉ</th><th>Điểm</th></tr>
</thead>
<tbody>
<tr><td>Thiết kế Web</td><td>3</td><td>8.5</td></tr>
<tr><td>Cơ sở dữ liệu</td><td>3</td><td>7.0</td></tr>
<tr><td>Toán rời rạc</td><td>2</td><td>9.0</td></tr>
</tbody>
<tfoot>
<tr><th colspan="2">Điểm trung bình (có trọng số)</th><td>8.06</td></tr>
</tfoot>
</table>(Điểm trung bình có trọng số: (8.5×3 + 7.0×3 + 9.0×2) / 8 = 64.5 / 8 ≈ 8.06.) Một chi tiết thú vị: dù bạn viết tfoot trước tbody trong mã, trình duyệt vẫn hiển thị chân bảng ở cuối.
| Phần tử | Vai trò | Ghi nhớ |
|---|---|---|
table |
Gốc của bảng | Mặc định không có viền |
caption |
Tiêu đề bảng | Ngay sau table; đổi vị trí bằng caption-side |
thead / tbody / tfoot |
Đầu / thân / chân | Cấu trúc rõ ràng |
tr |
Dòng | Chứa th/td |
th / td |
Ô tiêu đề / ô dữ liệu | th đậm và căn giữa |
colspan / rowspan |
Gộp cột / gộp hàng | Bớt td ở các dòng bị chiếm |
Vừa học xong bảng biểu, hãy làm nhóm bài 4.3: từ bảng điểm đơn giản, đến bảng có colspan ở tiêu đề nhóm, bảng có thead/tbody/tfoot, và cuối cùng là bảng lịch học kết hợp rowspan với colspan. Mẹo: hãy vẽ bảng ra giấy, đánh dấu ô nào gộp trước khi viết mã.
4. Danh sách
Giáo trình: Chương 2 — mục "Danh sách" (Danh sách không có thứ tự; Danh sách có thứ tự; Danh sách định nghĩa).
HTML có ba kiểu danh sách: danh sách không có thứ tự (ul), danh sách có thứ tự (ol) và danh sách định nghĩa (dl). Trong hai kiểu đầu, từng mục là một phần tử li (list item).
4.1. Danh sách không có thứ tự
Danh sách không có thứ tự (unordered list) không đánh số thứ tự; mỗi mục thường được đánh dấu bằng một ký hiệu đầu dòng, mặc định là chấm tròn đen nhỏ. Dùng thẻ ul kết hợp các phần tử li:
<strong>Các kiểu dữ liệu trong JavaScript</strong>
<ul>
<li>boolean</li>
<li>null</li>
<li>undefined</li>
<li>number</li>
<li>string</li>
<li>symbol</li>
</ul>Có thể dùng thuộc tính style cho ul để chọn kiểu ký hiệu đầu dòng qua list-style-type: disc (chấm tròn đặc — mặc định), circle (vòng tròn rỗng), square (ô vuông). Chạy ví dụ ba kiểu sau:
<strong>Các kiểu dữ liệu trong JavaScript</strong>
<ul style="list-style-type:square">
<li>boolean</li>
<li>null</li>
<li>undefined</li>
</ul>
<ul style="list-style-type:circle">
<li>number</li>
<li>string</li>
</ul>
<ul style="list-style-type:disc">
<li>symbol</li>
</ul>Bạn cũng có thể lồng một ul hoặc ol vào bên trong một li để tạo danh sách nhiều cấp (menu có submenu, mục lục). Điều quan trọng: danh sách con nằm bên trong thẻ li cha, không nằm giữa hai li.
<ul>
<li>Điện thoại
<ul>
<li>iPhone</li>
<li>Samsung</li>
</ul>
</li>
<li>Máy tính xách tay</li>
</ul>4.2. Danh sách có thứ tự
Một danh sách có thể đánh thứ tự theo số hoặc chữ cái; đó là danh sách có thứ tự (ordered list), tạo bằng thẻ ol. Mặc định thứ tự bắt đầu từ số 1, các mục cũng là phần tử li.
<strong>Các kiểu dữ liệu trong JavaScript</strong>
<ol>
<li>boolean</li>
<li>null</li>
<li>undefined</li>
<li>number</li>
<li>string</li>
<li>symbol</li>
</ol>Danh sách có thứ tự có thể đánh số bằng nhiều kiểu qua list-style-type:
| Giá trị | Ý nghĩa |
|---|---|
decimal |
Số thập phân (mặc định): 1, 2, 3... |
decimal-leading-zero |
Số thập phân, thêm số 0 ở đầu nếu nhỏ hơn 10: 01, 02... |
armenian |
Hệ thống số Armenia |
cjk-ideographic |
Hệ thống chữ số Hán tự |
georgian |
Hệ thống số của Georgia |
hebrew |
Hệ thống số Do Thái |
Chạy thử với decimal-leading-zero để thấy ngay hiệu ứng; thay bằng hebrew hoặc georgian nếu muốn thử các hệ số khác:
<strong>Các kiểu dữ liệu trong JavaScript</strong>
<ol style="list-style-type: decimal-leading-zero">
<li>boolean</li>
<li>null</li>
<li>undefined</li>
<li>number</li>
</ol>Thuộc tính start của ol xác định số bắt đầu của dãy. Muốn bắt đầu từ 4 thay vì 1, viết <ol start="4">:
<strong>Các kiểu dữ liệu trong JavaScript</strong>
<ol start="4">
<li>boolean</li>
<li>null</li>
<li>undefined</li>
<li>number</li>
</ol>Danh sách bắt đầu ở số 4: mục đầu tiên "boolean" mang số 4, "null" là 5... Trong thực tế start hữu ích khi danh sách dài bị cắt thành nhiều phần bởi một đoạn văn xen giữa. Ngoài ra, thuộc tính type="a" của ol có thể đánh dấu bằng chữ cái, và ol còn có reversed để đếm ngược; các bài tập của Codelab hay dùng type="A" để đánh số đáp án A, B, C, D.
Mẹo: Chọn
olkhi thứ tự có ý nghĩa (các bước nấu ăn, xếp hạng, quy trình); chọnulkhi các mục ngang hàng (danh sách mua sắm, thể loại).
4.3. Danh sách định nghĩa
HTML hỗ trợ danh sách định nghĩa (definition list), trong đó các mục được liệt kê giống như trong từ điển hoặc bách khoa toàn thư. Đây là cách rất tốt để hiển thị thực đơn hoặc bảng chú giải các mục dữ liệu. Danh sách định nghĩa dùng ba thẻ:
dl— xác định danh sách (definition list);dt— thuật ngữ (definition term);dd— mô tả cho thuật ngữ đó (definition description).
<strong>Bảng tra cứu các phần tử HTML</strong>
<dl>
<dt>a</dt>
<dd>Phần tử liên kết</dd>
<dt>abbr</dt>
<dd>Phần tử viết tắt</dd>
<dt>article</dt>
<dd>Phần tử bài viết</dd>
</dl>Quan sát: dt nằm sát lề, dd thụt vào bên dưới. Một thuật ngữ có thể đi kèm nhiều dd (nhiều nghĩa), và nhiều dt có thể dùng chung một dd. Ví dụ một thực đơn:
<dl>
<dt>Phở bò</dt>
<dd>Phở nước dùng xương bò, 45.000đ</dd>
<dt>Cà phê sữa</dt>
<dd>Cà phê đá pha phin, 25.000đ</dd>
<dd>Có thể thêm đá viên hoặc ít đường</dd>
</dl>| Phần tử | Dùng khi | Ký hiệu mặc định |
|---|---|---|
ul |
Các mục ngang hàng | Chấm tròn (disc) |
ol |
Các mục có thứ tự | Số 1, 2, 3... |
dl + dt + dd |
Thuật ngữ – mô tả, thực đơn, FAQ | Không có ký hiệu; dd thụt vào |
Vừa học xong danh sách, hãy làm nhóm bài 4.4: dùng dl cho bảng thuật ngữ, danh sách lồng nhau cho mục lục sách, và trang Hỏi – Đáp (FAQ). Chú ý đặt danh sách con bên trong li.
5. Liên kết
Giáo trình: Chương 2 — mục "Liên kết" (Tạo liên kết; Liên kết cục bộ; Thuộc tính target; Hình ảnh liên kết; Tiêu đề liên kết; Liên kết đánh dấu).
5.1. Tạo liên kết
Liên kết (link / hyperlink) là thứ làm nên "siêu văn bản" của web. Liên kết được xác định bằng thẻ a (anchor), trong đó thuộc tính href (hypertext reference) chứa địa chỉ đích. Ví dụ liên kết tới trang chủ Minh's Blogs: <a href="https://minh-blogs.web.app">Tới trang Minh's Blogs</a>. Giáo trình lưu ý: không cần dấu gạch chéo ở cuối địa chỉ.
<p><a href="https://minh-blogs.web.app">Tới trang Minh's Blogs</a></p>
<p><a href="mailto:[email protected]">Gửi email</a> · <a href="tel:+84912345678">Gọi điện</a></p>Ngoài địa chỉ web, href còn nhận lược đồ mailto: (mở chương trình email) và tel: (gọi điện trên điện thoại) như ví dụ giáo trình ở phần section. Nhớ lại buổi 1 (Đường dẫn Web): địa chỉ đầy đủ có scheme://host/path.
5.2. Liên kết cục bộ
Ví dụ ở trên dùng URL tuyệt đối (địa chỉ web đầy đủ). Liên kết cục bộ — liên kết đến một trang khác trong cùng Website — được chỉ định bằng URL tương đối, chỉ cần tên tệp hoặc đường dẫn từ trang hiện tại, ví dụ <a href="article.html">Đọc thêm</a>.
| Loại | Ví dụ href |
Khi dùng |
|---|---|---|
| Tuyệt đối | https://fit.neu.edu.vn/ |
Sang website khác |
| Tương đối (cùng thư mục) | article.html |
Trang khác trong cùng website |
| Tương đối (thư mục con) | images/me.jpg |
Tài nguyên trong thư mục con |
| Tương đối (từ gốc) | /css/ |
Từ thư mục gốc của website |
5.3. Thuộc tính target
Thuộc tính target xác định nơi mở tài liệu được liên kết, với các giá trị:
_blank— mở trong cửa sổ hoặc tab mới;_self— mở trong cùng cửa sổ/tab khi bấm (mặc định);_parent— mở trong khung (frame) cha;_top— mở trong toàn bộ cửa sổ.
Ví dụ: <a href="https://www.vncodelab.com/" target="_blank">Vào trang Vncodelab</a>. Hãy chạy đoạn mã dưới đây để quan sát mã đọc thuộc tính (trong khung xem trước, việc điều hướng bị chặn nên liên kết chỉ để minh họa):
<a id="l1" href="https://www.vncodelab.com/" target="_blank">Vào trang Vncodelab (tab mới)</a><br>
<a id="l2" href="article.html">Đọc thêm (cùng tab)</a>
<script>
document.querySelectorAll("a").forEach(a => {
console.log(a.id + " → target = " + (a.getAttribute("target") || "_self (mặc định)"));
});
</script>Cảnh báo: Khi dùng
target="_blank"với liên kết sang website khác, nên thêmrel="noopener noreferrer"để trang mở ra không điều khiển được trang gốc của bạn (chống tấn công tabnabbing).
5.4. Hình ảnh liên kết
Liên kết có thể gắn vào một hình ảnh: đặt thẻ img bên trong thẻ a. Khi người dùng bấm vào ảnh, trình duyệt đi tới địa chỉ href.
<a href="article.html">
<img alt="JavaScript" width="90" height="60"
src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='90' height='60'%3E%3Crect width='90' height='60' fill='%23facc15'/%3E%3Ctext x='45' y='38' font-size='20' text-anchor='middle'%3EJS%3C/text%3E%3C/svg%3E">
</a>Thuộc tính alt ở đây càng quan trọng: nếu ảnh là liên kết duy nhất, alt chính là "tên" của liên kết mà trình đọc màn hình sẽ đọc.
5.5. Tiêu đề liên kết
Thuộc tính title cung cấp thông tin thêm về một phần tử liên kết; thường hiển thị dưới dạng chú giải (tooltip) khi người dùng rê chuột lên.
<a class="readmore" href="article.html" title="Đọc thêm về ngôn ngữ lập trình JavaScript">Đọc thêm</a>Hãy rê chuột lên "Đọc thêm": dòng giải thích hiện ra. Đừng đặt thông tin thiết yếu duy nhất vào title, vì người dùng điện thoại không có chuột để rê.
5.6. Liên kết đánh dấu
Liên kết đánh dấu (bookmark link) cho phép người đọc nhảy tới một phần cụ thể của trang web, rất hữu ích với trang dài. Gồm hai bước: (1) tạo dấu trang bằng một phần tử có thuộc tính id, ví dụ <h2 id="C2">Chương 2</h2>; (2) thêm liên kết tới dấu trang đó bằng # + id, ví dụ <a href="#C2">Chuyển đến Chương 2</a>. Khi bấm, trang cuộn tới vị trí dấu trang. Để liên kết tới dấu trang của trang khác: <a href="article.html#C2">Chuyển đến Chương 2</a>.
<nav>
<a href="#C1">Chuyển đến Chương 1</a> |
<a href="#C2">Chuyển đến Chương 2</a> |
<a href="#C3">Chuyển đến Chương 3</a>
</nav>
<h2 id="C1">Chương 1</h2>
<p>Tổng quan về thiết kế Website...</p>
<h2 id="C2">Chương 2</h2>
<p>Ngôn ngữ đánh dấu siêu văn bản HTML...</p>
<h2 id="C3">Chương 3</h2>
<p>CSS...</p>
<script>
document.querySelectorAll("nav a").forEach(a => {
const id = a.getAttribute("href").slice(1);
console.log(a.getAttribute("href") + " → " + (document.getElementById(id) ? "tìm thấy dấu trang" : "KHÔNG có dấu trang"));
});
</script>Mỗi id phải duy nhất trong trang và href="#C2" phân biệt hoa/thường với id="C2"; sai một chữ là liên kết "chết" (bấm không cuộn tới đâu).
Vừa học xong liên kết, hãy làm nhóm bài 4.5: dựng thanh điều hướng nav với ul và a, menu cuộn tới từng section, mục lục dùng dấu trang #id và dòng breadcrumb. Kiểm tra mọi href="#..." đều có id tương ứng.
Thực hành theo giáo trình
Giáo trình: Chương 2 — mục "Thực hành", Bài 2.2. Danh mục sản phẩm (Bài 2.1 tạo form và Bài 2.3 tạo favicon thuộc buổi 5 và buổi 3 tương ứng).
Mục tiêu: tạo trang web hiển thị danh mục sản phẩm và một danh sách sản phẩm tương tự với liên kết nhanh, dùng các thẻ vừa học. Các bước chính theo giáo trình:
- Tiêu đề
h1"Danh mục sản phẩm" để làm rõ mục đích của trang. - Bảng
tablecó viền (border="1"), ba cột "Sản phẩm", "Giá" và "Tình trạng";thcho tiêu đề mỗi cột; mỗitrlà thông tin một sản phẩm;tdchứa tên, giá, tình trạng còn hàng. - Tiêu đề phụ
h2"Sản phẩm tương tự". - Khối
navchứa danh sáchul, mỗilicó một liên kếtatới các sản phẩm khác.
Dưới đây là một bản hoàn chỉnh để bạn đối chiếu; hãy chạy, rồi tự gõ lại từ đầu và đổi nội dung sang sản phẩm của riêng bạn:
<h1>Danh mục sản phẩm</h1>
<table border="1">
<tr><th>Sản phẩm</th><th>Giá</th><th>Tình trạng</th></tr>
<tr><td>Laptop Alpha 14"</td><td>18.500.000đ</td><td>Còn hàng</td></tr>
<tr><td>Chuột không dây</td><td>250.000đ</td><td>Còn hàng</td></tr>
<tr><td>Bàn phím cơ</td><td>1.200.000đ</td><td>Hết hàng</td></tr>
</table>
<h2>Sản phẩm tương tự</h2>
<nav>
<ul>
<li><a href="laptop-beta.html">Laptop Beta 15"</a></li>
<li><a href="chuot-gaming.html">Chuột chơi game</a></li>
<li><a href="ban-phim-mem.html">Bàn phím màng</a></li>
</ul>
</nav>Bài toán mở rộng (tự làm): thêm caption cho bảng, đổi hàng tiêu đề sang thead, bọc bảng trong section và h2, thêm footer có address liên hệ.
Câu hỏi ôn tập
Các câu dưới đây lấy từ phần "Câu hỏi ôn tập lý thuyết" của chương 2 trong giáo trình, phần thuộc nội dung buổi này (đáp án đối chiếu Phụ lục).
2.1. Thẻ nào tạo ra chữ đậm mà KHÔNG mang ý nghĩa nhấn mạnh? (A. strong; B. b; C. h1; D. head)
Đáp án: B — b chỉ in đậm, còn strong mang nghĩa quan trọng.
2.2. Thành phần HTML nào tạo ra một ngắt dòng? (A. br; B. break; C. hr; D. p)
Đáp án: A — br; hr là đường kẻ ngang ngắt chủ đề, p tạo đoạn mới.
2.3. Thẻ nào định nghĩa một văn bản quan trọng? (A. i; B. important; C. strong; D. em)
Đáp án: C — strong.
2.4. Thẻ nào được sử dụng để nhấn mạnh văn bản? (A. p; B. i; C. strong; D. em)
Đáp án: D — em (i chỉ là in nghiêng, strong là quan trọng).
2.5. Thuộc tính nào được sử dụng để hợp 2 hàng trong 1 bảng? (A. rowpadding; B. cellpadding; C. rowspan; D. colspan)
Đáp án: C — rowspan (còn colspan gộp cột).
2.6. Để tạo liên kết trong thẻ a sử dụng thuộc tính gì? (A. href; B. src; C. link; D. ref)
Đáp án: A — href; src dành cho tài nguyên nhúng như ảnh.
2.8. Vì sao nên dùng các phần tử ngữ nghĩa để tổ chức cấu trúc trang? Đáp án: D — vì chúng mô tả rõ ý nghĩa của nội dung cho trình duyệt, công cụ tìm kiếm và trình đọc màn hình.
2.9. Thẻ nào tạo ra danh sách không có thứ tự? (A. ul; B. ol; C. bullet; D. list)
Đáp án: A — ul (ol là danh sách có thứ tự).
2.10. Đoạn mã HTML nào là ĐÚNG để tạo một đường dẫn?
Đáp án: B — <a href="http://www.w3schools.com">W3Schools.com</a>; các phương án url, name hay thiếu thuộc tính đều sai.
Lưu ý: Câu 2.7 (đơn vị kích thước ảnh) thuộc phần đa phương tiện của buổi 5.
Sai lầm thường gặp
| Sai lầm | Hậu quả | Cách đúng |
|---|---|---|
Dùng h1–h6 để làm chữ to/đậm |
Cấu trúc tài liệu sai, SEO và trình đọc màn hình bị rối | Dùng đúng mức tiêu đề theo cấu trúc; chỉnh cỡ chữ bằng CSS |
Dùng div cho mọi vùng của trang |
Máy không biết đâu là menu, đâu là nội dung chính | Dùng header, nav, main, section, article, footer |
Đặt nhiều thẻ main trong một trang |
Vi phạm quy tắc chỉ một main; trình đọc màn hình nhầm |
Chỉ một main ngang hàng với header, nav, footer |
| Gõ xuống dòng trong mã nguồn và mong thấy xuống dòng | Trình duyệt gộp khoảng trắng và dòng thừa | Dùng br hoặc tách thành các p; dùng pre cho mã |
Dùng b/i thay cho strong/em khi nội dung quan trọng |
Mất ý nghĩa ngữ nghĩa | Chọn thẻ theo ý nghĩa; hiển thị để CSS lo |
Quên bớt td ở dòng bị rowspan chiếm chỗ |
Bảng lệch cột | Đếm số ô thực tế mỗi dòng cho khớp số cột |
Đặt tr ngoài table, hoặc td ngoài tr |
Bảng hiển thị sai, mã không hợp lệ | table > tr > th/td (có thể xen thead/tbody/tfoot) |
Đặt danh sách con nằm giữa hai thẻ li |
Mã không hợp lệ, thụt lề sai | Đặt ul/ol con bên trong li cha |
Viết href sai hoặc href="#ten" không có id="ten" |
Liên kết chết, bấm không đi đâu | Kiểm tra từng liên kết; id phải duy nhất |
Dùng target="_blank" cho mọi liên kết |
Người dùng bị mở quá nhiều tab, rủi ro bảo mật | Chỉ dùng khi cần và kèm rel="noopener noreferrer" |
Tóm tắt
- Phần tử ngữ nghĩa mô tả ý nghĩa nội dung:
main(một),section,article,header,footer,nav,aside,figure/figcaption,hr;divvàspanlà phi ngữ nghĩa. - Văn bản:
h1–h6cho cấu trúc (không để làm chữ to),pđoạn văn,blockquote/q/cite/abbr/address/timecó ngữ nghĩa riêng;strong/emkhácb/ivề ý nghĩa;brngắt dòng (không có thẻ đóng);code+precho mã lệnh. - Bảng:
table,tr,th,td; gộp ô bằngcolspan,rowspan;captionlàm tiêu đề;thead,tbody,tfootchia đầu – thân – chân. - Danh sách:
ul(không thứ tự),ol(có thứ tự,start,list-style-type),dl/dt/dd(định nghĩa). - Liên kết:
a+href; URL tuyệt đối/tương đối;target(_blank,_self,_parent,_top); ảnh liên kết;title; dấu trang#id.