HTML Tables - Colspan and Rowspan

Chapter 31 15 mins

Learning outcomes:

  1. Spanning multiple columns using colspan
  2. Spanning multiple rows using rowspan

Introduction

So far in this unit, we've only considered simple tables with each involved cell consuming one column and one row, so to speak.

However, HTML provides developers with a great amount of power and flexibility in fine-tuning the structure of tables and achieving quite complex layouts using them. Part of this power and flexibility comes from two attributes available on all <th> and <td> elements — colspan and rowspan.

This chapter is dedicated to learning about these two attributes and how can we use them to create complex table layouts, where given header and/or data cells span two or more columns and/or two or more rows.

Spanning multiple columns

To get a table cell to span multiple columns, we use the colspan attribute.

The colspan attribute is used to specify the number of columns that a table cell should span.

By default, a table cell spans exactly one column. Using colspan, we can get it to span more than one column, for e.g. 2, 3, 4, and so on.

As an example, let's say we want to represent the following table in HTML:

ItemAvailable sizes
T-Shirt (Blue)-M-
Hoodie (Grey)S-L
Hoodi (Black)SML
Striped Shirt (Yellow)-M-

The important thing to note here is the fact that the 'Available sizes' header spans the space of three columns in the table. Likewise, in order to correctly replicate this table, we need to use colspan on this header.

Here's the code to replicate the table, leveraging the colspan attribute on the second <th> element (the one representing 'Available sizes'):

<table border="1">
   <thead>
      <th>Item</th>
      <th colspan="3">Available sizes</th>
   </thead>
   <tbody>
      <tr>
         <td>T-Shirt (Blue)</td>
         <td>-</td>
         <td>M</td>
         <td>-</td>
      </tr>
      <tr>
         <td>Hoodie (Grey)</td>
         <td>S</td>
         <td>-</td>
         <td>L</td>
      </tr>
      <tr>
         <td>Hoodi (Black)</td>
         <td>S</td>
         <td>M</td>
         <td>L</td>
      </tr>
      <tr>
         <td>Striped Shirt (Yellow)</td>
         <td>-</td>
         <td>M</td>
         <td>-</td>
      </tr>
   </tbody>
</table>

Following what we learnt in the previous chapter to semantically section our tables' rows, we put the header cells inside <thead> while the rest of the data cells denoting actual content of the table inside <tbody>.

Besides this, the second <th> element gets a colspan of "3" as it needs to span a total of three columns (beneath it).

The output is illustrated below:

ItemAvailable sizes
T-Shirt (Blue)-M-
Hoodie (Grey)S-L
Hoodi (Black)SML
Striped Shirt (Yellow)-M-

Good!

Keep in mind that colspan doesn't necessarily have to be on a <th> element; it can well be used on a <td> Let's consider an example to help demonstrate this.

Shown below is the time table of a supposed programming bootcamp, somewhere on Mars, teaching only on Mondays, Wednesdays and Fridays, from 10am to 2pm:

10:00 - 11:0011:00 - 12:0012:00 - 13:0013:00 - 14:00
MondayHTMLCSS
WednesdayHTMLJavaScriptCSS
FridayGitHTMLJavaScript

The data cells reading 'HTML', 'CSS', and so on, signify what is taught on which day during which timeframe.

For example, HTML is taught on Mondays from 10am to 12pm for two 1 hour sessions. Similarly, on Mondays and Wednesdays, CSS is taught from 12pm to 2pm, again for two consecutive sessions.

Notice how some data cells span multiple columns in order to depict that the underlying topic consumes more than one session — the likes of 'HTML' and 'CSS'.

Let's now replicate this table using HTML and some colspan magic:

<table border="1">
   <tr>
      <th></th>
      <th>10:00 - 11:00</th>
      <th>11:00 - 12:00</th>
      <th>12:00 - 13:00</th>
      <th>13:00 - 14:00</th>
   </tr>
   <tr>
      <th>Monday</th>
      <td colspan="2">HTML</td>
      <td colspan="2">CSS</td>
   </tr>
   <tr>
      <th>Wednesday</th>
      <td>HTML</td>
      <td>JavaScript</td>
      <td colspan="2">CSS</td>
   </tr>
   <tr>
      <th>Friday</th>
      <td>Git</td>
      <td colspan="2">HTML</td>
      <td>JavaScript</td>
   </tr>
</table>
10:00 - 11:0011:00 - 12:0012:00 - 13:0013:00 - 14:00
MondayHTMLCSS
WednesdayHTMLJavaScriptCSS
FridayGitHTMLJavaScript

All is great except for one thing: the cells spanning multiple columns have their text left-aligned. The original table presented above has this text center-aligned.

So how could we center-align text in a table cell?

Well, there is nothing special for aligning text inside a table cell; we use the common CSS property for doing so in any element that contains text — text-align.

The text-align CSS property

The text-align CSS property is used to specify the alignment of text in a given element. The possible values are:

  • left for left-alignment
  • right for right-alignment
  • center for center-alignment
  • justify for justified-alignment (where the words of every line are spaced out in a way such that the length of all lines is the same).

Following shown are examples of each of these on a dummy piece of text:

<p style="text-align: left">This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.</p>
<p style="text-align: right">This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.</p>
<p style="text-align: center">This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.</p>
<p style="text-align: justify">This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.</p>

This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.

This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.

This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.

This is some long text in the HTML paragraph element because we want to demonstrate the effect of the CSS text-align property which is an extremely useful property to use in all but the most simplest websites.

Perhaps the most common text alignment on the web is left-alignment, followed by center-alignment. Right-alignment is the lesser used one, with justified-alignment being the least used.

In the following snippet, we augment our HTML in order to centralize the text in every multiple-column-spanning <th> element:

<table border="1">
   <tr>
      <th></th>
      <th>10:00 - 11:00</th>
      <th>11:00 - 12:00</th>
      <th>12:00 - 13:00</th>
      <th>13:00 - 14:00</th>
   </tr>
   <tr>
      <th>Monday</th>
      <td colspan="2" style="text-align: center">HTML</td>
      <td colspan="2" style="text-align: center">CSS</td>
   </tr>
   <tr>
      <th>Wednesday</th>
      <td>HTML</td>
      <td>JavaScript</td>
      <td colspan="2" style="text-align: center">CSS</td>
   </tr>
   <tr>
      <th>Friday</th>
      <td>Git</td>
      <td colspan="2" style="text-align: center">HTML</td>
      <td>JavaScript</td>
   </tr>
</table>
10:00 - 11:0011:00 - 12:0012:00 - 13:0013:00 - 14:00
MondayHTMLCSS
WednesdayHTMLJavaScriptCSS
FridayGitHTMLJavaScript

Voila! And there's our alignment.

Back in the day, <th> and <td> element had an attribute called align to do what the CSS text-align property is doing above. It has been deprecated and should no longer be used in new HTML code.

Spanning multiple rows

Where spanning multiple columns is done with the help of the colspan attribute, as we just learnt a while ago, the same is done for rows using rowspan.

The rowspan attribute is used to specify the number of rows that a table cell should span.

Every table cell spans exactly one row by default. Using rowspan we can change this.

Time to turn to an example.

Consider the table below showcasing a bunch of programming languages and some of their popular frameworks:

Programming languageFramework
JavaScriptExpress.js
JavaScriptAngular
JavaScriptNext.js
PHPLaravel
PHPSymfony
JavaSpring

Since the first three data rows and then the next two ones correspond to the same programming languages, JavaScript and PHP, respectively, we can reduce the underlying data cells in these rows to single cells.

Something as follows:

Programming languageFramework
JavaScriptExpress.js
Angular
Next.js
PHPLaravel
Symfony
JavaSpring

Replicating this table using HTML is quite easy, for we seek the rowspan attribute on the first data cell in each of the two concerned rows.

Following is the HTML for the table, with the markup of the <tr> elements presented in one line for the sake of readability:

<table>
   <thead>
      <tr><th>Programming language</th><th>Framework</th></tr>
   </thead>
   <tbody>
      <tr><td rowspan="3">JavaScript</td><td>Express.js</td></tr>
      <tr><td>Angular</td></tr>
      <tr><td>Next.js</td></tr>
      <tr><td rowspan="2">PHP</td><td>Laravel</td></tr>
      <tr><td>Symfony</td></tr>
      <tr><td>Java</td><td>Spring</td></tr>
   </tbody>
</table>

Observe the second, third, and fifth <tr> elements here — they all contain one single <td> element. The reason of doing so is because by virtue of the colspan

Programming languageFramework
JavaScriptExpress.js
Angular
Next.js
PHPLaravel
Symfony
JavaSpring

As this snippet illustrates, if the markup of an HTML table is more readable when specifying the content of the <tr> elements in one single line, then we are better off at doing so.