Mastering HTML Tables: A Beginner’s Guide

Imagine unearthing relics of ancient code—an era where the web was woven with raw HTML, symbolic incantations conjuring structure within the digital realm. Among these, HTML tables stand tall; silent monoliths that have held the weight of data with unwavering strength.

In this labyrinth of tags and text, mastery of tables is not just a skill; it’s an art form—a craft that elucidates the subtleties of data presentation and web design principles. It’s about turning function into form, where <th> meets <td>, and semantic markup forges clarity from chaos.

This compendium is a map through the table terrain, where you’ll glean the HTML5 features, finesse your layout with CSS, and unleash the powers of accessibility. From tabular structures in their simplest guise to the spectacle of responsive design, each concept is a piece unlocked.

By the conclusion, expect to wield the prowess to summon responsive tables that dance to every device’s tune and render cross-browser elegance. You’re not just learning—you’re architecting experiences pixel by pixel, where every table row and cell padding whispers your command.

Table of contents

Introduction to tables

The HTML table is used for arranging data (such as text, images, links etc.) into the tabular design – basically, rows and columns.

When to Use Tables

A table in HTML makes a lot of sense when you want to organize data that would look best in a spreadsheet. An HTML table is a great way to display things such as financial data, calendars, pricing, feature comparison, the nutrition facts information panel, bowling scores, and many other tabular data.

There is a chance you have heard that the tables were unsemantic. However, that is not at all true. Tables semantically indicate tabular data and they are the best choice for displaying data of this kind.

When NOT to Use Tables

While some data looks great in tables, there are things that shouldn’t be arranged that way simply because it wouldn’t make any sense. There are also some other inappropriate CSS table uses that should be avoided if possible.

For example, you should never use tables for layout. The thing is that table elements semantically describe tabular data and using them for other purposes is a breach of semantic duty.

The general rule is that the websites should be accessible. One part of accessibility is screen readers which read tables from top to bottom, left to right. With the tables in HTML, the order of how the site is presented is determined by visual choices instead of the accessibility choices. In cases like that, screen readers don’t always work as you’d want them to.

Now to make the point even stronger, imagine a “sidebar on the left” layout. In that case, a table would dictate that the table comes first in source order. Not only would that be bad for accessibility, but the SEO would suffer as well because the primary content wouldn’t be in the spotlight.

A part of that issue could be solved with the semantic tags within the HTML table tags but that would also mean using double the HTML. The best thing to do would be simply not to use tables for layout but if you absolutely insist on that, use the ARIA role=”presentation” on the table to indicate it as such.

Table Elements

HTML tables usually come with a short description of their purpose. Sometimes, a more detailed description is provided via the summary attribute for the benefit of people using speech or Braille-based user agents.

See the Pen HTML Table & CSS Table by Ahmad Awais (@ahmadawais) on CodePen.

Table rows may be grouped into a head, foot, and body sections, (via the THEADTFOOT and TBODY elements). User agents may exploit the head/body/foot division to support scrolling of body sections independently of the head and foot sections. When we print the long HTML tables, the head and foot information is usually displayed on each page containing the table.

If you want to provide more structural information, you can also group columns. In addition to that, column properties may be declared at the start of the table definition using the COLGROUP and COL elements.

Table cells contain the header information and/or data and they can span multiple columns and rows. When you label each cell with the HTML 4 table mode, the non-visual user agents can communicate the information to the user more easily. Not only is this useful for users with disabilities but it makes it possible for modal wireless browsers with limited display capabilities to handle HTML tables.

We mentioned already that tables HTML should not be used for layout. Instead, you should use style sheets whenever necessary to achieve better results and better accessibility.

Head and Body

Let’s take a look at a basic example of HTML table style:

See the Pen Basic Table Styles by Tommy Hodgins (@tomhodgins) on CodePen.

Imagine looking at a row (horizontal) to see a single person and relevant information about them. When you look up and down a column (vertical), you will get a sense of the variety or pattern of data.

The first row is the header of the table and it contains no data – just the titles of the columns. You can semantically indicate that is the case with the <thead> element, which would wrap the first <tr> (it could wrap as many rows as needed that are all header information).

When you use <thead>, there must be no <tr> that is a direct child of <table>. All rows must be within either the <thead><tbody>, or <tfoot>.

Table Footer

Along with <thead> and <tbody>, there is <tfoot> for wrapping table rows that indicate the footer of the table. Like <thead>, best for semantically indicating these are not data rows but ancillary information.

The placement of <tfoot> is unique in HTML as it comes after <thead> and before <tbody>! So even though it might seem logical to find it at the end of <table>, it is actually not the case. Since the footer contains information necessary to understand the table, it is placed before the data in the source order for better accessibility.

Table footer can be used in long HTML tables to repeat the header, for example. However, it can be used for other purposes as well, for instance, with a layout where the position of elements jumps around from bottom to top depending on needs.

Table Elements and their Attributes

<tfoot> HTML Tag

The <tfoot> element identifies one or more <tr> elements as containing summary contents of a table’s columns. The <tfoot> element must be the direct descendant of a <table> element. In HTML5, <tfoot> can be placed either before or after <tbody> and <tr> elements, but must appear after any <caption>, <colgroup>, and <thead> elements.

<tbody> HTML Tag

The <tbody> element must be a direct descendant of a <table> element and is used to identify <tr> elements that comprise the body of the table. The <tbody> element should always come after a <thead> element and may come before or after a <tfoot> element.

<tr> HTML Tag


  • <tr align=””>
  • <tr valign=””>
  • <tr bgcolor=””>
  • <tr background=””>
  • <tr bordercolor=””>

The <tr> element is used to group together <th> or <td> values into a single row of table heading or data values. The <tr> element may be a direct child of a <table> element or nested within a parent <thead>, <tfoot>, or <tbody> element.

<thead> HTML Tag


  • align
  • valign

The <caption> element is used to add a caption to an HTML table. A <caption> must appear in an HTML document as the first descendant of a parent <table>, but it may be positioned visually at the bottom of the table with CSS.



  • span
  • align
  • bgcolor
  • width

The <col> element, typically implemented as a child element of a parent <colgroup>, can be used to target a column in an HTML table.



  • align
  • span
  • width

The <colgroup> element is used a parent container for one or more <col> elements which are used to target columns in an HTML table.

Basic Styling

See the Pen Data Table by alassetter (@alassetter) on CodePen.

Distinguishing different parts of the table is easy if the table has different colors and lines. CSS table border is another common element. By default, all table cells are spacing out from one another by 2px. Between the first row and the rest, you will notice a slight extra gap caused by the default border-spacing being applied to the <thead> and <tbody>pushing them apart a bit extra.

You can control the spacing:

table {border-spacing: 0.5rem;}

Or you can simply remove that space:

table {border-collapse: collapse;}

HTML table padding, HTML table heading, borders, and making <th> elements left-aligned is a simple yet effective way to style your HTML tables.

Important Style Rules for Tables

CSS tables and their properties work great if you use them right. There are, however, some details to keep in mind. For example, if you apply a certain font-family to the table, but then a different one to the cell – the cell wins because it is the actual element with the text inside.

These properties are either unique to table elements or they behave uniquely on table elements.


Possible values: baseline, sub, super, text-top, text-bottom, middle, top, bottom, %, length

Aligns the content inside a cell. Works particularly well in tables, although only the top/bottom/middle make much sense in that context.


Possible values: normal, pre, nowrap, pre-wrap, pre-line

Controls how text wraps in a cell. Some data may need to be all on one line to make sense.


Possible values: collapse, separate

Applied to the table to determine if borders collapse into themselves (sort of like margin collapsing only bi-directional) or not. What if two borders that collapse into each other have conflicting styles (like color)? The styles applied to these types of elements will “win”, in order of “strength”: cell, row, row group, column, column group, table.


Possible values: length

If border-collapse is separate, you can specify how far cells should be spaced out from each other. The modern version of cellspacing attribute. And speaking of that, padding is the modern version of the cellpadding attribute.


Possible values: length

Width works on table cells just about how you would think it does, except when there is some kind of conflict.

For instance, if you tell the table itself to be 400px wide then the first cell of a three-cell row to be 100px wide and leave the others alone, that first cell will be 100px wide and the other two will split up the remaining space.

But if you tell all three of them to be 20000px wide, the table will still be 400px and it will just give each of them a third of the space. That’s assuming white-space or elements like an image don’t come into play.


Possible values: length

Border works on any of the table elements and just about how you would expect. The quirks come in when you collapse the borders.

In this case, all table cells will have only one border width between them, rather than the two you would expect them to have (border-right on the first cell and border-left on the next cell).

In order to remove a border in a collapsed environment, both cells need to “agree” to remove it. Like td:nth-child(2) { border-right: 0; } td:nth-child(3) { border-left: 0; } Otherwise, source order/specificity wins which border is shown on which edge.


Possible values: auto, fixed

auto is the default. The width of the table and its cells depends on the content inside.

If you change this to fixed, the table and column widths are set by the widths of table and col elements or by the width of the first row of cells.

Cells in subsequent rows do not affect column widths, which can speed up rendering. If the content in subsequent cells can’t fit, the overflow property determines what happens.

Table Border

See the Pen Responstable 2.0: a responsive table solution by Jordy van Raaij (@jordyvanraaij) on CodePen.

Table border CSS makes it easier to see the table and it is also the best method for displaying borders. Add styles, within the <style></style> tags located in the head element, to show the border for the table, th and td elements within your HTML document.

Connecting Cells

To understand how connected cells work, we need to explain the two attributes that can go on any table cell element: HTML rowspan and HTML colspan. If a td has a colspan of 2 (i.e. <td colspan=”2″>) will take up the space of two cells in a row horizontally even though it would still be a single cell. The same goes for rowspan, but vertically.

Rowspan is a bit harder to grasp simply because columns are grouped differently than rows. For example, with colspan, you get the final value by simply adding up the values for each table cell in the row. With rowspan, on the other hand, the row below it gets +1 to its table cell count and needs one less table cell to complete the row.

Nesting Tables

See the Pen Nicked nested tables reference by Theun (@tjoen) on CodePen.

“Nesting tables” simply means placing a table inside another table which is doable but you need to include the complete structure with the <table> element. However, it might not be the best idea because of the confusing markup and worse accessibility.

However, there are situations when this is absolutely necessary and yes, it is doable. So, for example, if you need to import content from other sources, you can import a table and place it inside your table.

Zebra Striping Tables

See the Pen Full width zebra table by Mario Loncarek (@riogrande) on CodePen.

Colors are very helpful for the users to easily spot what they are looking for in the table. You can either set a background color to the table cell elements or you can set them on the table rows themselves.

This is the most basic example:

tbody tr:nth-child(odd) {background: #eee; }

Using tbody is useful if you don’t want to stripe header and footer rows. If you don’t want to let what is underneath show through, you can set the even rows as well.

If you need to support browsers that don’t understand: nth-child() (pretty damn old) you could use jQuery to do it.

Highlighting Rows and Columns

See the Pen Material Sortable Datatable by Azamat Mukhiddinov (@azamatms) on CodePen.

Highlighting rows is pretty easy; all it takes is adding a class name to a row.

Highlighting columns, on the other hand, takes a bit more effort. You can use the <col> element, which will allow you to set styles for cells that appear in the selected column. For example, a table with 4 columns in each row would need to have 4 <col> elements.

How to center an HTML Table

How to center a table in HTML? This question is pretty common among people designing their first HTML tables. The thing is that text-align:center doesn’t center a table as a whole – it just centers the text inside the cells.

Centering the whole table needs left and right margins set to auto, and top and bottom margins set to the values you need.

Say you want the top and bottom margins of your table to be one blank line (1em). The CSS code in the <table> tag is simply:

<table style=”margin:1em auto;”>

If you wish to wrap text next to a table, use float:left to float the table to the left of the subsequent text. To put a little space between the table and the text, you can also put the right margin on the table, like this:

<table style=”float:left; margin-right:10px;”>

If you want the table to be to the right of the neighboring text, use float:right instead. You can also set the left margin:

<table style=”float:right; margin-left:10px;”>

Something to keep in mind: Make sure you put the text that should be next to the table after the closing </table> tag for the table. Floats float next to subsequent content in the code, not content that precedes the float.


Your beautiful data deserves to be online

wpDataTables can make it that way. There’s a good reason why it’s the #1 WordPress plugin for creating responsive tables and charts.

An actual example of wpDataTables in the wild

And it’s really easy to do something like this:

  1. You provide the table data
  2. Configure and customize it
  3. Publish it in a post or page

And it’s not just pretty, but also practical. You can make large tables with up to millions of rows, or you can use advanced filters and search, or you can go wild and make it editable.

“Yeah, but I just like Excel too much and there’s nothing like that on websites”. Yeah, there is. You can use conditional formatting like in Excel or Google Sheets.

Did I tell you you can create charts too with your data? And that’s only a small part. There are lots of other features for you.

HTML Table Generator Tools

Tables generator

Very useful HTML table generator tool. Easy to use and it allows you to choose the theme you like best. You can learn more about it on the official website.


A simple and easy-to-use tool that also happens to be free of charge.


Truben allows you to make all kinds of HTML tables quickly and easily.


A handy tool that works similarly to word processors. It lets you create beautiful tables free of charge.

CSS Table generator

Great tool for creating stylish tables without the use of images.


Use table CSS elements and create gorgeous HTML tables with this online tool.


A simple tool for creating your favorite table style.


One of the simplest tools; perfect for people with little technical knowledge and/or slow internet connection.


This tool comes with a variety of generating options and creating great HTML tables is one of them.


A useful generator for designing HTML tables out of spreadsheet data.

FAQ on HTML Tables 

How do I create a basic HTML table?

Crafting a table in the realm of HTML is akin to building with digital LEGOs. Envision a matrix; wrap it in <table></table> tags. Inside, rows bloom with <tr>; within them, <td> cells hold your data. It’s harmonious, orderly—an arrangement of rows and columns, bridging structure and content.

Can HTML tables be responsive?

Certainly! In the dance of pixels across screens, make your tables move gracefully. Cascading Style Sheets (CSS) is your choreographer. Employ media queries, wrap your tables in divs, use percentage widths. Cast a spell with CSS’s max-width, overflow, and display properties; watch your tables adapt with the agility of a contortionist.

What are colspan and rowspan in HTML tables?

Imagine a grand banquet where some guests are more eminent. Colspan is the stretch of a ruler’s table; rowspan the tower of a wedding cake. Tag attributes colspan="number" and rowspan="number" let you merge cells across rows or columns, crafting a canvas for your data to reign supreme or tower high.

How do I style HTML tables with CSS?

Tables, dressed in style, exude sophistication. Invoke CSS to whisper elegance into the ears of plain HTML. Paint with properties like borderbackground-color, and text-align; adorn with padding and margin. With the artistry of CSS, tables transform into mesmerizing tapestries under your deft touch.

What is the purpose of the <thead><tbody>, and <tfoot> elements?

These are the bones of your table’s skeleton. <thead> hoists your header in esteem; <tbody> cradles the heart—the bulk of your content; <tfoot> anchors the footer, sometimes echoing whispers of a summary. Together, they segment the anatomy of your table, bestowing order and aiding in styles and scripts’ targeted enchantments.

How should I use <th> elements properly?

In the realm of HTML, <th> is the crown atop your table’s content. Reserve it for headers, giving birth to cells that lead with bold authority. They are seers, preluding the data beneath as column and row guides, an anchor for the eyes, and a beacon for accessibility.

Are HTML tables still relevant with CSS grid and flexbox?

Yes, for tabular data, tables hold unyielding relevance, faithfully preserving the sanctum of rows and columns. While CSS grid and flexbox weave magic in layout patterns, they speak a different tongue. When the storytelling of data beckons with precision, tables, in humble attire, answer the call.

How can I make HTML tables accessible for screen readers?

As a digital bard, you must ensure your tales traverse all ears. Use <scope> to establish dominion, pairing headers with their data. ARIA roles can be your amulets here, along with captions that orient the wandering, and succinct summaries. Make each navigation a guided journey, with no listener left behind.

What are the best practices for using HTML tables in web design?

Tables should never be contortionists in layout roleplay; reserve them for the dignified portrayal of data. Employ semantic markup; let every <th>, <caption>, and <summary> vocalize its intent. Dress them in CSS with care, never shrinking from the embrace of responsive web design principles.

How can I convert an HTML table to a CSV or Excel file using JavaScript?

Master JavaScript’s alchemy to transmute your HTML tables into CSV or Excel ores. Forge each row, cell by cell, into lines of comma-separated values. Invoke the creation of a Blob, and command the browser to unfurl a parchment for download. Here, your table’s essence is captured, ready for realms beyond.


Embarking on this journey across the grid-lines of HTML tables wasn’t merely an academic endeavor. It was an orchestration of rows and columns into a symphony of structured data, each element a note played in harmonious precision. Within the confines of <table> tags, a narrative unfolded—cell by cell, row by row.

As creators of digital tapestries, remember that tables are more than just rigid arrays; they’re versatile instruments. From holding the simplicity of tabular data to boasting enhancements with CSS styling, these vessels have been filled with a wealth of knowledge.

By embracing responsive design with an artisan’s touch, ensuring accessibility is more than an afterthought, and guarding the sanctity of tables for relevant content—each craftsperson molds the web’s fabric, maintaining its semantic richness.

Disperse with newfound insights—harness, construct, and infuse web pages with the utility and elegance that only masterfully crafted HTML tables can convey.

If you enjoyed reading this article on HTML tables, you should check out this one about Bootstrap tables.

We also wrote about a few related subjects like How to center a table with CSS, table background color, responsive tables with CSS, CSS tables and jQuery table plugins.

Bogdan Radusinovic
Bogdan Radusinovic

Senior SEO and Marketing Specialist

Articles: 137