What is the <tbody> tag in HTML?

Learn about the HTML <tbody> tag that structures table bodies. Syntax, practical examples, and best practices for accessible tables.
8 min read
Believemy logo

Introduction to the <tbody> tag

The <tbody> tag is a fundamental element in creating well-structured HTML tables. It defines the main body of a table, which contains the actual data, as opposed to the table header and footer.

When building complex tables to display information such as lists of students, course catalogs, or statistics, the <tbody> tag becomes essential for organizing your code semantically and accessibly. If you want to master the creation of professional tables and many other HTML elements, our comprehensive HTML course will guide you step by step through this learning process.

Good to know

💡 Did you know that even if you don't explicitly write the <tbody> tag, browsers automatically add it to the DOM? However, writing it explicitly improves code readability and maintainability.

 

Definition and syntax of <tbody>

Basic syntax

The <tbody> tag is used inside a <table> element and wraps the data rows of the table. Here is the fundamental structure:

HTML
<table>
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Data 1</td>
      <td>Data 2</td>
    </tr>
    <tr>
      <td>Data 3</td>
      <td>Data 4</td>
    </tr>
  </tbody>
</table>

The <tbody> tag is a container element that requires both opening and closing tags. It has no specific attributes in HTML5, but accepts global attributes like class, id, or style.

 

Key characteristics

Here are the essential characteristics of the <tbody> tag:

  • Grouping element: it groups one or more <tr> rows that make up the table body
  • Optional but recommended tag: browsers add it implicitly if absent
  • Position in the table: it must appear after <thead> and before <tfoot> if these elements are present
  • Multiplicity: a table can contain multiple <tbody> elements to group different data sections
  • Block element: it generates a block formatting context within the table

 

Position in HTML hierarchy

To understand where <tbody> fits, let's examine the complete structure of a semantic table:

HTML
<table>
  <caption>Believemy Course List</caption>
  <thead>
    <!-- Column headers -->
  </thead>
  <tbody>
    <!-- Main data -->
  </tbody>
  <tfoot>
    <!-- Table footer (totals, summaries) -->
  </tfoot>
</table>

This three-part structure (thead, tbody, tfoot) allows browsers and assistive technologies to better interpret the nature of the presented data.

 

Practical usage examples

Simple example: data table

Let's start with a concrete example of a table listing courses:

HTML
<table>
  <thead>
    <tr>
      <th>Course</th>
      <th>Duration</th>
      <th>Level</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>HTML Fundamentals</td>
      <td>10 hours</td>
      <td>Beginner</td>
    </tr>
    <tr>
      <td>Advanced CSS</td>
      <td>15 hours</td>
      <td>Intermediate</td>
    </tr>
    <tr>
      <td>Modern JavaScript</td>
      <td>25 hours</td>
      <td>Advanced</td>
    </tr>
  </tbody>
</table>

In this example, the <tbody> contains three data rows distinct from the headers. This clear separation makes the code easier to read and allows applying different CSS styles to each section.

 

Advanced example: multiple tbody

A lesser-known but very powerful feature is the ability to use multiple <tbody> elements in the same table to create logical data groups:

HTML
<table>
  <thead>
    <tr>
      <th>Student</th>
      <th>Course</th>
      <th>Progress</th>
    </tr>
  </thead>
  
  <tbody class="beginner-group">
    <tr class="group-title">
      <td colspan="3"><strong>Beginner Level</strong></td>
    </tr>
    <tr>
      <td>Marie Dupont</td>
      <td>HTML Basics</td>
      <td>75%</td>
    </tr>
    <tr>
      <td>Pierre Martin</td>
      <td>CSS Introduction</td>
      <td>60%</td>
    </tr>
  </tbody>
  
  <tbody class="advanced-group">
    <tr class="group-title">
      <td colspan="3"><strong>Advanced Level</strong></td>
    </tr>
    <tr>
      <td>Sophie Bernard</td>
      <td>JavaScript Pro</td>
      <td>90%</td>
    </tr>
  </tbody>
</table>

This technique is particularly useful for report tables or categorized data, as it allows applying distinct styles to each group and facilitates JavaScript manipulation.

 

Styling with CSS

One of the major advantages of explicitly using <tbody> is the ability to easily target this section with CSS. Here's a styling example:

CSS
/* General table style */
table {
  width: 100%;
  border-collapse: collapse;
  font-family: Arial, sans-serif;
}

/* Header styles */
thead {
  background-color: #2c3e50;
  color: white;
}

thead th {
  padding: 12px 15px;
  text-align: left;
}

/* Table body styles */
tbody tr {
  border-bottom: 1px solid #dddddd;
}

tbody tr:nth-of-type(even) {
  background-color: #f3f3f3;
}

tbody tr:hover {
  background-color: #e8f4f8;
  cursor: pointer;
}

tbody td {
  padding: 12px 15px;
}

This CSS code creates an elegant table with alternating row colors (zebra striping) and a hover effect. The tbody tr selector ensures these styles apply only to data rows, not headers.

 

Best practices for usage

Always structure your tables

Even though the <tbody> tag is technically optional, we strongly recommend always including it explicitly in your tables for several reasons:

  • Code clarity: the structure becomes immediately readable for you and your colleagues
  • Easier maintenance: modifications are simpler to make
  • More predictable CSS: CSS selectors target exactly what you want
  • More reliable JavaScript: DOM manipulation is more consistent
Warning

Warning: if you use JavaScript to manipulate a table and haven't explicitly written <tbody>, the browser will have added it to the DOM anyway. Your selectors must account for this!

 

Accessibility and semantics

The <tbody> tag contributes to your tables' accessibility. Screen readers use this information to help users navigate data efficiently. Combined with appropriate tags, it enables an inclusive experience.

For optimal accessibility, always combine <tbody> with:

  • A <caption> element describing the table content
  • <th> tags with the appropriate scope attribute
  • The aria-describedby attribute if additional explanations are needed
HTML
<table aria-describedby="table-description">
  <caption>Believemy Student Progress</caption>
  <thead>
    <tr>
      <th scope="col">Name</th>
      <th scope="col">Course</th>
      <th scope="col">Score</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>John Believemy</td>
      <td>Complete HTML</td>
      <td>95%</td>
    </tr>
  </tbody>
</table>
<p id="table-description">This table displays real-time progress.</p>

 

Using with responsive tables

In responsive design, <tbody> can be targeted to modify display on small screens. A common technique is to transform rows into stacked cards:

CSS
@media screen and (max-width: 600px) {
  table, thead, tbody, th, td, tr {
    display: block;
  }
  
  thead {
    position: absolute;
    top: -9999px;
    left: -9999px;
  }
  
  tbody tr {
    margin-bottom: 15px;
    border: 1px solid #ccc;
    border-radius: 8px;
    padding: 10px;
  }
  
  tbody td {
    border: none;
    position: relative;
    padding-left: 50%;
  }
  
  tbody td::before {
    content: attr(data-label);
    position: absolute;
    left: 10px;
    font-weight: bold;
  }
}

This approach requires adding a data-label attribute to each cell to display the column name on mobile.

 

Common mistakes to avoid

Forgetting parent-child structure

A common mistake is placing unauthorized elements directly in <tbody>. Only <tr> elements (table rows) can be direct children of <tbody>:

HTML
<!-- ❌ INCORRECT -->
<tbody>
  <td>Data</td>  <!-- td directly in tbody -->
  <p>Text</p>    <!-- p not allowed -->
</tbody>

<!-- ✅ CORRECT -->
<tbody>
  <tr>
    <td>Data</td>
  </tr>
</tbody>

 

Wrong section order

The order of elements in a table must follow a specific sequence. Here is the correct order:

  1. <caption> (optional, but must be first if present)
  2. <colgroup> (optional)
  3. <thead> (optional)
  4. <tbody> (one or more)
  5. <tfoot> (optional)
Good to know

Historical note: in HTML4, <tfoot> had to appear before <tbody> in the source code to allow the browser to display the table footer before the data fully loaded. In HTML5, this constraint was removed.

 

tbody vs thead vs tfoot

These three elements form the semantic structure of a complete table. Here are their differences:

ElementRoleTypical Content
<thead>Table headerColumn titles, often with <th>
<tbody>Table bodyMain data, content rows
<tfoot>Table footerTotals, summaries, notes

A notable advantage of this separation is that when printing a long table across multiple pages, browsers can automatically repeat <thead> and <tfoot> on each page, while <tbody> naturally divides.

 

When a table spans multiple printed pages, modern browsers intelligently handle the sections:

  • <thead> repeats at the top of each page
  • <tfoot> can repeat at the bottom of each page (browser-dependent)
  • <tbody> naturally divides between pages

This feature makes printed reports much more readable without additional effort on your part.

 

Browser compatibility

The <tbody> tag enjoys excellent compatibility with all modern and legacy browsers:

BrowserMinimum VersionSupport
Chrome1.0✅ Full
Firefox1.0✅ Full
Safari1.0✅ Full
Edge12✅ Full
Opera7.0✅ Full
Internet Explorer4.0✅ Full

You can use <tbody> with confidence without worrying about compatibility, as this element has been supported since the earliest versions of web browsers.

 

Frequently asked questions about <tbody>

Question

Is it mandatory to use <tbody> in an HTML table?

No, the <tbody> tag is not mandatory. If you don't write it, browsers automatically add it to the DOM around your <tr> rows that aren't in a <thead> or <tfoot>. However, we strongly recommend always writing it explicitly to improve your code's readability and avoid surprises when manipulating JavaScript or targeting CSS.

 

Question

Can you have multiple <tbody> in the same table?

Yes, absolutely! It's actually a very useful feature for logically grouping different data sections. For example, you could have one <tbody> for each product category or each company department. Each <tbody> can have its own CSS class for distinct styling.

 

Question

What's the difference between <tbody> and <div> in a table?

The <table> tag is not allowed inside an HTML table (except within a <td> or <th> cell). The <tbody> is the semantic element designed to group data rows. Using a <div> instead would break the table structure and could cause display and accessibility issues.

 

Question

How can I learn HTML effectively?

To master HTML and all its subtleties, including creating professional and accessible tables, we recommend following our comprehensive HTML course. You'll learn best practices, advanced techniques, and complete real projects to solidify your skills.

Related terms

Discover our hTML and CSS glossary

Browse the terms and definitions most commonly used in HTML and CSS development.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.