Bảng

Bảng HTML hiển thị dữ liệu dạng bảng theo hàng và cột. Bạn nên chọn sử dụng một <table> dựa trên nội dung mà bạn đang hiển thị và nhu cầu của người dùng liên quan đến nội dung đó. Nếu dữ liệu đang được trình bày, so sánh, sắp xếp, tính toán hoặc tham chiếu chéo, thì <table> có lẽ là lựa chọn phù hợp. Nếu bạn muốn sắp xếp nội dung không ở dạng bảng, chẳng hạn như một nhóm lớn gồm các hình thu nhỏ, thì bảng không phải là lựa chọn phù hợp. Thay vào đó, hãy tạo một danh sách gồm các hình ảnh và tạo kiểu cho lưới bằng CSS.

Trong phần này, chúng ta sẽ thảo luận về tất cả các phần tử tạo nên bảng, cùng với một số tính năng hỗ trợ tiếp cận và khả năng sử dụng cần cân nhắc khi trình bày dữ liệu dạng bảng. Mặc dù Learn HTML không tập trung vào CSS, nhưng chúng ta sẽ tìm hiểu một số thuộc tính CSS dành riêng cho bảng. Để tìm hiểu thêm về CSS, hãy tham khảo khoá học Tìm hiểu về CSS.

Các phần tử trong bảng, theo thứ tự

Thẻ <table> bao bọc nội dung của bảng, bao gồm cả tất cả các phần tử của bảng. Vai trò ARIA ngầm định của <table>table; các công nghệ hỗ trợ biết rằng phần tử này là một cấu trúc bảng chứa dữ liệu được sắp xếp theo hàng và cột. Nếu bảng duy trì trạng thái lựa chọn, có chế độ điều hướng hai chiều hoặc cho phép người dùng sắp xếp lại thứ tự ô, hãy đặt role="grid". Nếu các hàng của grid có thể mở rộng và thu gọn, hãy sử dụng role="treegrid".

Bên trong <table>, bạn sẽ tìm thấy tiêu đề bảng (<thead>), nội dung bảng (<tbody>) và chân trang bảng (<tfoot>) (không bắt buộc). Mỗi phần này đều được tạo thành từ các hàng trong bảng (<tr>). Các hàng chứa tiêu đề bảng (<th>) và các ô dữ liệu trong bảng (<td>), lần lượt chứa tất cả dữ liệu. Trong DOM, trước bất kỳ thành phần nào trong số này, bạn có thể tìm thấy 2 tính năng bổ sung: chú thích bảng (<caption>) và nhóm cột (<colgroup>). Tuỳ thuộc vào việc <colgroup> có thuộc tính span hay không, thành phần này có thể chứa các phần tử cột bảng lồng nhau (<col>).

Các thành phần con của bảng theo thứ tự là:

  1. Phần tử <caption>
  2. Phần tử <colgroup>
  3. Phần tử <thead>
  4. Phần tử <tbody>
  5. Phần tử <tfoot>

Chúng ta sẽ xem xét các phần tử con của <table> (tất cả đều không bắt buộc nhưng nên có), sau đó xem xét các hàng, ô tiêu đề bảng và ô dữ liệu bảng. <colgroup> sẽ được đề cập sau cùng.

Chú thích bảng

Phương thức ưu tiên để đặt tên cho một bảng là phần tử ngữ nghĩa, <caption>. <caption> cung cấp tiêu đề bảng mô tả, được liên kết theo phương thức lập trình. Theo mặc định, tất cả người dùng đều có thể nhìn thấy và sử dụng tính năng này.

Phần tử <caption> phải là phần tử đầu tiên được lồng trong phần tử <table>. Việc thêm tiêu đề giúp tất cả người dùng biết ngay mục đích của bảng mà không cần phải đọc văn bản xung quanh. Ngoài ra, bạn có thể sử dụng aria-label hoặc aria-labelledby trên <table> để cung cấp tên có thể truy cập dưới dạng chú thích. Phần tử <caption> không có thuộc tính dành riêng cho phần tử.

Chú thích xuất hiện bên ngoài bảng. Bạn có thể đặt vị trí của chú thích bằng thuộc tính CSS caption-side. Đây là một phương pháp hay hơn so với việc sử dụng thuộc tính align không được dùng nữa. Thao tác này có thể đặt phụ đề ở trên cùng và dưới cùng. Chế độ định vị bên trái và bên phải bằng inline-startinline-end chưa được hỗ trợ đầy đủ. Top là bản trình bày mặc định của trình duyệt.

Tốt nhất là các bảng dữ liệu phải có tiêu đề và chú thích rõ ràng, đồng thời phải đủ rõ ràng để gần như tự giải thích được. Xin lưu ý rằng không phải người dùng nào cũng có khả năng nhận thức như nhau. Khi bảng "đưa ra một điểm" hoặc cần được diễn giải, hãy cung cấp bản tóm tắt ngắn gọn về điểm chính hoặc chức năng của bảng. Vị trí của bản tóm tắt đó phụ thuộc vào độ dài và mức độ phức tạp của bản tóm tắt. Nếu ngắn gọn, hãy dùng nội dung đó làm văn bản bên trong chú thích. Nếu dài hơn, hãy tóm tắt trong chú thích và cung cấp bản tóm tắt trong đoạn văn trước bảng, liên kết hai nội dung này với thuộc tính aria-describedby. Một lựa chọn khác là đặt bảng trong <figure> và đặt nội dung tóm tắt trong <figcaption>.

Phân chia dữ liệu

Nội dung của bảng bao gồm tối đa 3 phần: 0 hoặc nhiều tiêu đề bảng (<thead>), nội dung bảng (<tbody>) và chân trang bảng (<tfoot>). Tất cả đều không bắt buộc, với 0 hoặc nhiều phần được hỗ trợ.

Những phần tử này không giúp ích hoặc cản trở khả năng hỗ trợ tiếp cận của bảng, nhưng chúng hữu ích về khả năng sử dụng. Chúng cung cấp các hook tạo kiểu. Ví dụ: bạn có thể cố định nội dung tiêu đề, trong khi nội dung <tbody> có thể được đặt ở chế độ cuộn. Các hàng không được lồng trong một trong ba phần tử chứa này sẽ được bao bọc ngầm trong một <tbody>. Cả ba đều có cùng vai trò ngầm định là rowgroup. Không có phần tử nào trong số 3 phần tử này có thuộc tính dành riêng cho phần tử.

Những gì chúng ta đã có cho đến nay:

<table>
  <caption>MLW Students</caption>
  <thead></thead>
  <tbody></tbody>
  <tfoot></tfoot>
</table>

Phần tử <tfoot> ban đầu được chỉ định xuất hiện ngay sau <thead> và trước <tbody> vì lý do trợ năng. Đó là lý do bạn có thể gặp phải thứ tự nguồn không trực quan này trong các cơ sở mã cũ.

Nội dung bảng

Bảng có thể được chia thành tiêu đề, nội dung và chân trang, nhưng không có phần nào trong số này thực sự có tác dụng nếu bảng không chứa hàng, ô và nội dung. Mỗi hàng trong bảng <tr> chứa một hoặc nhiều ô. Nếu một ô là ô tiêu đề, hãy dùng <th>. Nếu không, hãy sử dụng <td>.

Biểu định kiểu của tác nhân người dùng thường hiển thị nội dung trong một ô tiêu đề bảng <th> ở dạng căn giữa và in đậm. Các kiểu mặc định này và tất cả kiểu dáng đều được kiểm soát tốt nhất bằng CSS thay vì các thuộc tính không dùng nữa từng có trên các ô, hàng riêng lẻ và thậm chí cả <table>.

Có các thuộc tính để thêm khoảng đệm giữa các ô và trong các ô, cho đường viền và cho căn chỉnh văn bản. Cellpadding và cellspacing (xác định khoảng cách giữa nội dung của một ô và đường viền của ô đó, cũng như giữa đường viền của các ô liền kề) phải được đặt bằng các thuộc tính border-collapseborder-spacing của CSS, tương ứng. Border-spacing sẽ không có hiệu lực nếu bạn đặt border-collapse: collapse. Nếu bạn đặt border-collapse: separate;, thì bạn có thể ẩn hoàn toàn các ô trống bằng empty-cells: hide;. Để tìm hiểu thêm về cách tạo kiểu cho bảng, bạn có thể xem một bản trình bày tương tác về các kiểu CSS liên quan đến bảng.

Trong các ví dụ, chúng tôi đã thêm một đường viền vào bảng và từng ô riêng lẻ bằng CSS để một số tính năng trở nên rõ ràng hơn:

Trong ví dụ này, chúng ta có một chú thích, một tiêu đề bảng và một nội dung bảng. Tiêu đề có một hàng chứa 3 ô tiêu đề <th>, do đó tạo ra 3 cột. Nội dung chứa 3 hàng dữ liệu: ô đầu tiên là ô tiêu đề cho hàng, vì vậy, chúng ta sử dụng <th> thay vì <td>.

Ô <th> có ý nghĩa ngữ nghĩa, với các vai trò ARIA ngầm định là columnheader hoặc rowheader. Thuộc tính này xác định ô là tiêu đề cho cột hoặc hàng của các ô trong bảng, tuỳ thuộc vào giá trị của thuộc tính scope được liệt kê. Trình duyệt sẽ mặc định là col hoặc row nếu bạn không đặt rõ ràng scope. Vì chúng ta đã sử dụng mã đánh dấu ngữ nghĩa, nên ô 1956 có 2 tiêu đề: Năm và Lou Minious. Mối liên kết này cho chúng ta biết rằng "1956" là "năm" tốt nghiệp của "Lou Minious". Trong ví dụ này, vì chúng ta có thể thấy toàn bộ bảng nên mối liên kết này rất rõ ràng. Việc sử dụng <th> sẽ cung cấp mối liên kết ngay cả khi cột hoặc hàng tiêu đề đã cuộn ra khỏi khung hiển thị. Chúng ta có thể đặt <th scope="col">Year</th><th scope="row">Lou Minious</th> một cách rõ ràng, nhưng với một bảng như thế này, các giá trị mặc định được liệt kê sẽ hoạt động. Các giá trị khác cho scope bao gồm rowgroupcolgroup, rất hữu ích với các bảng phức tạp.

Hợp nhất ô

Tương tự như MS Excel, Google Trang tính và Numbers, bạn có thể kết hợp nhiều ô thành một ô. Bạn có thể thực hiện việc này bằng các thuộc tính HTML colspanrowspan:

  • colspan hợp nhất hai hoặc nhiều ô liền kề trong một hàng.
  • rowspan hợp nhất các ô trên các hàng khi được thêm vào ô ở hàng đầu tiên trong số các hàng đã hợp nhất.

Trong ví dụ này, tiêu đề bảng chứa hai hàng. Hàng tiêu đề đầu tiên chứa 3 ô trải dài trên 4 cột: ô ở giữa có colspan="2". Thao tác này sẽ hợp nhất hai ô liền kề. Ô đầu tiên và ô cuối cùng bao gồm rowspan="2". Thao tác này sẽ hợp nhất ô với ô ở hàng liền kề, ngay bên dưới ô đó.

Hàng thứ hai trong tiêu đề bảng chứa hai ô; đây là các ô cho cột thứ hai và thứ ba trong hàng thứ hai. Không có ô nào được khai báo cho cột đầu tiên hoặc cột cuối cùng vì ô ở cột đầu tiên và cột cuối cùng trong hàng đầu tiên trải dài trên 2 hàng.

Trong trường hợp một ô được xác định bằng nhiều ô tiêu đề có mối liên kết mà bạn không thể đặt chỉ bằng các thuộc tính scope, hãy thêm thuộc tính headers cùng với danh sách các tiêu đề được liên kết, phân tách bằng dấu cách. Vì ví dụ này là một bảng phức tạp hơn, nên chúng ta xác định rõ phạm vi của tiêu đề bằng thuộc tính scope. Để rõ ràng hơn, chúng tôi đã thêm thuộc tính headers vào từng ô.

Các thuộc tính headers có thể không cần thiết trong trường hợp này, nhưng bạn cần nhớ rằng các thuộc tính này rất quan trọng khi bảng của bạn tăng độ phức tạp. Các bảng có cấu trúc phức tạp (chẳng hạn như bảng có tiêu đề hoặc ô được hợp nhất hoặc có nhiều hơn 2 cấp tiêu đề cột hoặc hàng) yêu cầu bạn phải xác định rõ các ô tiêu đề được liên kết. Trong những bảng phức tạp như vậy, hãy liên kết rõ ràng từng ô dữ liệu với từng ô tiêu đề tương ứng bằng một danh sách các giá trị id được phân tách bằng dấu cách của tất cả các tiêu đề được liên kết làm giá trị của thuộc tính headers.

Thuộc tính headers thường xuất hiện trên các phần tử <td>, nhưng cũng hợp lệ trên <th>.

Tuy nhiên, cấu trúc bảng phức tạp có thể gây khó khăn cho tất cả người dùng, chứ không chỉ người dùng trình đọc màn hình. Về mặt nhận thức và khả năng hỗ trợ trình đọc màn hình, các bảng đơn giản hơn, có ít hoặc không có ô trải rộng, ngay cả khi không thêm phạm vi và tiêu đề, vẫn dễ hiểu hơn. Bạn cũng có thể quản lý các vị trí này dễ dàng hơn!

Tạo kiểu cho bảng

Có hai phần tử tương đối khó hiểu đã được đề cập vắn tắt: phần tử nhóm cột <colgroup> và phần tử con duy nhất của phần tử này, phần tử cột <col> trống. Phần tử <colgroup> dùng để xác định các nhóm cột hoặc phần tử <col> trong một bảng.

Nếu được dùng, nhóm cột phải được lồng trong <table>, ngay sau <caption> và trước mọi dữ liệu bảng. Nếu các giá trị này trải dài trên nhiều cột, hãy sử dụng thuộc tính span.

Thứ tự phác thảo nội dung cho một bảng thường như sau, trong đó <table><caption> là hai phần tử cần có:

<table>
  <caption>Table Caption</caption>
  <colgroup>
    <col/>
  </colgroup>
  <thead>...

<colgroup><col> không có ý nghĩa ngữ nghĩa, điều này sẽ ảnh hưởng đến khả năng hỗ trợ tiếp cận của bảng. Tuy nhiên, các thuộc tính này giúp bạn tạo kiểu cho các cột bằng CSS, chẳng hạn như đặt chiều rộng.

Các kiểu liên quan <td><th> sẽ ghi đè các kiểu <col>. Trong CodePen, chúng ta đặt colspan để hợp nhất một số hàng của bảng, nhưng không phải tất cả. Nếu bộ chọn CSS nth-child được áp dụng cho <tr>, tuỳ thuộc vào hàng hoặc cột đã được hợp nhất, điều này có thể ảnh hưởng đến kiểu.

Trong trường hợp này, "tr > *:nth-child(2)" sẽ ảnh hưởng đến thành phần con thứ hai của mọi hàng. Đây có phải là kết quả bạn mong đợi không?

Rất tiếc, chỉ có một số ít tài sản được hỗ trợ. Các kiểu không được kế thừa vào các ô và cách duy nhất để nhắm đến các ô bằng <col> là sử dụng một bộ chọn phức tạp, chẳng hạn như bộ chọn quan hệ :has().

Kết xuất theo lớp của các phần tử dùng để thiết kế bảng HTML.

Nếu cả <table><colgroup> đều có màu nền, thì background-color của <colgroup> sẽ ở trên cùng. Thứ tự vẽ là: bảng, nhóm cột, cột, nhóm hàng, hàng, với các ô ở cuối và ở trên cùng, như minh hoạ trong sơ đồ các lớp bảng. Các phần tử <td><th> không phải là phần tử con của các phần tử <colgroup> hoặc <col> và không kế thừa kiểu của các phần tử đó.

Để tạo sọc cho bảng, bộ chọn cấu trúc CSS sẽ rất hữu ích. Ví dụ: tbody tr:nth-of-type(odd) {background-color: rgba(0 0 0 / 0.1);} sẽ thêm màu đen trong suốt vào mỗi hàng lẻ trong nội dung của bảng, đồng thời cho phép các hiệu ứng nền được đặt trên <colgroup> hiển thị xuyên suốt.

Theo mặc định, các bảng không có khả năng thích ứng. Thay vào đó, theo mặc định, chúng được điều chỉnh kích thước theo nội dung. Bạn cần có các biện pháp bổ sung để kiểu bố cục bảng hoạt động hiệu quả trên nhiều thiết bị. Nếu bạn thay đổi thuộc tính hiển thị CSS cho các phần tử bảng, hãy thêm các thuộc tính ARIA role. Mặc dù có vẻ dư thừa, nhưng thuộc tính CSS display có thể ảnh hưởng đến cây hỗ trợ tiếp cận trong một số trình duyệt.

Trình bày dữ liệu

Các phần tử trong bảng có ý nghĩa ngữ nghĩa mà công nghệ hỗ trợ sử dụng để giúp người dùng di chuyển qua các hàng và cột mà không bị lạc. Bạn không nên dùng phần tử <table> để trình bày. Nếu bạn cần có tiêu đề cho một danh sách, hãy sử dụng tiêu đềdanh sách. Nếu bạn muốn bố trí nội dung thành nhiều cột, hãy sử dụng bố cục nhiều cột. Nếu bạn muốn bố trí nội dung trong một lưới, hãy sử dụng lưới CSS.

Chỉ sử dụng bảng cho dữ liệu.

Hãy nghĩ theo cách này: nếu dữ liệu của bạn cần có bảng tính để trình bày tại một cuộc họp, hãy sử dụng <table>. Nếu muốn sử dụng các tính năng có trong phần mềm trình bày, chẳng hạn như Google Trang trình bày hoặc PowerPoint, thì có thể bạn cần một danh sách mô tả.

Tóm lại: nếu bạn không trình bày dữ liệu dạng bảng, đừng sử dụng <table>. Nếu bạn sử dụng bảng để trình bày, hãy đặt role="none".

Nhiều nhà phát triển sử dụng bảng để bố trí biểu mẫu, nhưng điều này là không cần thiết. Bạn cần biết về biểu mẫu HTML.

Kiểm tra mức độ hiểu biết của bạn

Kiểm tra kiến thức của bạn về bảng.

Phần tử nào được dùng để đánh dấu các ô là tiêu đề?

<header>
Hãy thử lại.
<caption>
Hãy thử lại.
<th>
Chính xác!

Thông tin nào có khả năng phù hợp với bố cục có bảng?

Một số thuật ngữ khoa học và nội dung mô tả về các thuật ngữ đó.
Hãy thử lại, câu hỏi này phù hợp hơn với <dl>.
Một bảng tính chứa thông tin chi tiết về học viên và điểm số của họ trong 3 học kỳ.
Chính xác!
Nguyên liệu cho một công thức.
Hãy thử lại, câu hỏi này phù hợp hơn với <ul>.