Table Element
The <tbody> element encapsulates one or more rows (<tr>) that constitute the main body of data in a table. It separates the primary table content from headers (<thead>) and footers (<tfoot>), providing semantic structure that helps browsers, assistive technologies, and developers understand the table’s organization.
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Office Supplies Inventory</caption>
<thead>
<tr>
<th scope="col">Item</th>
<th scope="col">Category</th>
<th scope="col">Quantity</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr>
<td>Pens (Blue)</td>
<td>Writing</td>
<td>144</td>
<td>$12.99</td>
</tr>
<tr>
<td>Notebooks</td>
<td>Paper</td>
<td>50</td>
<td>$25.00</td>
</tr>
<tr>
<td>Staplers</td>
<td>Office Tools</td>
<td>12</td>
<td>$89.88</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
thead {
background-color: #34495e;
color: white;
}
tbody tr:nth-child(even) {
background-color: #f8f9fa;
}
tbody tr:hover {
background-color: #e9ecef;
}
</style>
Within a <table>, elements should appear in this order:
<caption> (optional)
<colgroup> (optional)
<thead> (optional)
<tbody> (one or more)
<tfoot> (optional)
Note
If you don’t explicitly include a <tbody> tag, the browser will automatically create one and place all <tr> elements (that aren’t in <thead> or <tfoot>) inside it. However, it’s best practice to include it explicitly.
The <tbody> element supports all global HTML attributes .
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Team Members</caption>
<thead>
<tr>
<th scope="col">Name</th>
<th scope="col">Role</th>
<th scope="col">Location</th>
</tr>
</thead>
<tbody>
<tr>
<td>Sarah Connor</td>
<td>Project Manager</td>
<td>New York</td>
</tr>
<tr>
<td>John Reese</td>
<td>Developer</td>
<td>San Francisco</td>
</tr>
<tr>
<td>Emma Watson</td>
<td>Designer</td>
<td>London</td>
</tr>
<tr>
<td>Michael Chen</td>
<td>QA Engineer</td>
<td>Toronto</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
thead {
background-color: #3498db;
color: white;
}
tbody tr:hover {
background-color: #f0f8ff;
cursor: pointer;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Department Expenses by Quarter</caption>
<thead>
<tr>
<th scope="col">Department</th>
<th scope="col">Amount</th>
</tr>
</thead>
<tbody class="q1">
<tr>
<td colspan="2"><strong>Q1 2024</strong></td>
</tr>
<tr>
<td>Engineering</td>
<td>$125,000</td>
</tr>
<tr>
<td>Marketing</td>
<td>$85,000</td>
</tr>
</tbody>
<tbody class="q2">
<tr>
<td colspan="2"><strong>Q2 2024</strong></td>
</tr>
<tr>
<td>Engineering</td>
<td>$142,000</td>
</tr>
<tr>
<td>Marketing</td>
<td>$92,000</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 10px;
text-align: left;
}
thead {
background-color: #2c3e50;
color: white;
}
tbody + tbody {
border-top: 3px solid #2c3e50;
}
tbody tr:first-child td {
background-color: #ecf0f1;
font-weight: bold;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Browser Market Share - 2024</caption>
<thead>
<tr>
<th scope="col">Browser</th>
<th scope="col">Desktop</th>
<th scope="col">Mobile</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Chrome</th>
<td>65.2%</td>
<td>62.8%</td>
</tr>
<tr>
<th scope="row">Safari</th>
<td>18.5%</td>
<td>24.3%</td>
</tr>
<tr>
<th scope="row">Firefox</th>
<td>8.1%</td>
<td>0.9%</td>
</tr>
<tr>
<th scope="row">Edge</th>
<td>5.2%</td>
<td>4.1%</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 10px;
}
thead {
background-color: #8e44ad;
color: white;
}
tbody th {
background-color: #f0f0f0;
text-align: left;
}
td {
text-align: right;
}
</style>
One powerful feature of <tbody> is the ability to use multiple instances to group related rows:
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Student Grades by Class</caption>
<thead>
<tr>
<th scope="col">Student</th>
<th scope="col">Grade</th>
</tr>
</thead>
<tbody>
<tr>
<td colspan="2" class="section-header">
Mathematics
</td>
</tr>
<tr>
<td>Alice Johnson</td>
<td>A</td>
</tr>
<tr>
<td>Bob Smith</td>
<td>B+</td>
</tr>
</tbody>
<tbody>
<tr>
<td colspan="2" class="section-header">
Physics
</td>
</tr>
<tr>
<td>Alice Johnson</td>
<td>A-</td>
</tr>
<tr>
<td>Bob Smith</td>
<td>B</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
border: 1px solid #ddd;
padding: 8px;
text-align: left;
}
thead {
background-color: #27ae60;
color: white;
}
.section-header {
background-color: #95a5a6;
color: white;
font-weight: bold;
}
tbody + tbody {
border-top: 2px solid #34495e;
}
</style>
Visual Grouping
Separate related rows visually with borders or spacing between groups.
JavaScript Manipulation
Easily show/hide entire groups of rows with a single operation.
Styling Flexibility
Apply different styles to different data groups within the same table.
Semantic Meaning
Communicate logical groupings in your data structure.
Interactive code playground requires JavaScript. Here's the code:
<table>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody>
<tr><td>Widget A</td><td>$19.99</td></tr>
<tr><td>Widget B</td><td>$24.99</td></tr>
<tr><td>Widget C</td><td>$29.99</td></tr>
<tr><td>Widget D</td><td>$34.99</td></tr>
<tr><td>Widget E</td><td>$39.99</td></tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 10px;
text-align: left;
border: 1px solid #ddd;
}
thead {
background-color: #333;
color: white;
}
/* Alternate row colors */
tbody tr:nth-child(odd) {
background-color: #f9f9f9;
}
tbody tr:nth-child(even) {
background-color: #ffffff;
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<table>
<thead>
<tr>
<th scope="col">Task</th>
<th scope="col">Status</th>
</tr>
</thead>
<tbody>
<tr><td>Design mockups</td><td>Complete</td></tr>
<tr><td>Write documentation</td><td>In Progress</td></tr>
<tr><td>Code review</td><td>Pending</td></tr>
<tr><td>Deploy to staging</td><td>Not Started</td></tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 12px;
text-align: left;
border: 1px solid #ddd;
}
thead {
background-color: #2980b9;
color: white;
}
tbody tr {
transition: all 0.3s ease;
}
tbody tr:hover {
background-color: #3498db;
color: white;
transform: scale(1.02);
box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}
</style>
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Server Status Monitor</caption>
<thead>
<tr>
<th scope="col">Server</th>
<th scope="col">Status</th>
<th scope="col">Uptime</th>
</tr>
</thead>
<tbody>
<tr class="status-online">
<td>Server 1</td>
<td>Online</td>
<td>99.9%</td>
</tr>
<tr class="status-warning">
<td>Server 2</td>
<td>Warning</td>
<td>95.2%</td>
</tr>
<tr class="status-offline">
<td>Server 3</td>
<td>Offline</td>
<td>0%</td>
</tr>
<tr class="status-online">
<td>Server 4</td>
<td>Online</td>
<td>100%</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 10px;
text-align: left;
border: 1px solid #ddd;
}
thead {
background-color: #34495e;
color: white;
}
.status-online {
background-color: #d4edda;
color: #155724;
}
.status-warning {
background-color: #fff3cd;
color: #856404;
}
.status-offline {
background-color: #f8d7da;
color: #721c24;
}
</style>
When the first cell of a row is a header, use <th> with scope="row":
< th scope = " row " > January </ th >
< th scope = " row " > February </ th >
This helps screen readers announce “January: $10,000” instead of just “$10,000”.
For complex data relationships, use the headers attribute:
< th id = " name " scope = " col " > Name </ th >
< th id = " math " scope = " col " > Math </ th >
< th id = " science " scope = " col " > Science </ th >
< th id = " alice " scope = " row " > Alice </ th >
< td headers = " alice math " > 95 </ td >
< td headers = " alice science " > 88 </ td >
Interactive code playground requires JavaScript. Here's the code:
<table>
<caption>Product Categories</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Price</th>
</tr>
</thead>
<tbody class="group">
<tr class="group-header">
<td colspan="2">
<strong>▼ Electronics</strong>
</td>
</tr>
<tr>
<td>Laptop</td>
<td>$899</td>
</tr>
<tr>
<td>Mouse</td>
<td>$25</td>
</tr>
</tbody>
<tbody class="group">
<tr class="group-header">
<td colspan="2">
<strong>▼ Furniture</strong>
</td>
</tr>
<tr>
<td>Desk</td>
<td>$299</td>
</tr>
<tr>
<td>Chair</td>
<td>$199</td>
</tr>
</tbody>
</table>
<style>
table {
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 10px;
text-align: left;
border: 1px solid #ddd;
}
thead {
background-color: #16a085;
color: white;
}
.group-header {
background-color: #ecf0f1;
cursor: pointer;
}
.group-header:hover {
background-color: #bdc3c7;
}
</style>
/* Basic tbody styling */
/* Alternating row colors */
tbody tr :nth-child ( odd ) {
background-color : # f9f9f9 ;
tbody tr :nth-child ( even ) {
background-color : # ffffff ;
background-color : # e8f4f8 ;
/* Multiple tbody separation */
border-top : 2 px solid # 333 ;
/* First and last row in tbody */
border-top : 2 px solid # ccc ;
border-bottom : 2 px solid # ccc ;
/* Targeting specific tbody */
background-color : # fffacd ;
✅ Always include <tbody> even for simple tables
✅ Use multiple <tbody> elements to group related rows
✅ Use <th> with scope="row" for row headers
✅ Apply consistent styling across tbody elements
✅ Keep row count reasonable for performance (paginate if needed)
✅ Test with screen readers to ensure proper announcement
❌ Don’t mix content types - keep headers in <thead>, data in <tbody>
❌ Don’t use deprecated attributes - use CSS for styling
❌ Don’t skip semantic structure - always separate header from body
❌ Don’t create overly complex structures - keep it simple
❌ Don’t forget hover states - improve user interaction
< caption > Standard Data Table </ caption >
< th scope = " col " > Column 1 </ th >
< th scope = " col " > Column 2 </ th >
< th scope = " row " > Total </ th >
< caption > Grouped Data </ caption >
< th scope = " col " > Item </ th >
< th scope = " col " > Value </ th >
The <tbody> element is supported in all browsers:
✅ Chrome (all versions)
✅ Firefox (all versions)
✅ Safari (all versions)
✅ Edge (all versions)
✅ Opera (all versions)
✅ Internet Explorer (all versions)