Introduction
So far in this unit, we've explored a solid amount of concepts underpinning HTML tables.
In particular, we've gone through the very basics of setting up tables using the elements <table>
, <tr>
, <th>
, and <td>
, and then how to section tables in different groups of rows, using <thead>
, <tbody>
, and <tfoot>
.
Not only this, but in the last chapter, we also learnt about the <colgroup>
and <col>
elements and that how we can use them to style entire columns of a table at once.
We're nearing the completion of this unit, and in this chapter we'll get even closer to that point once we're done with understanding the intuition behind the scope
attribute of <th>
elements, used to specify the scope of given header cells in a table.
The scope
attribute of <th>
Recall the <th>
element from the HTML Tables — Basics chapter? It's used to define a header cell in a <table>
element.
Now, there is a particularly important attribute of <th>
that is often used to explicitly specify its scope in a table, i.e. which set of data cells the header applies to. This attribute is called scope
.
The scope
attribute of a <th>
element is used to specify its scope, that is, whether the header applies to an entire row, or column, etc.
Quoting from the official HTML standard, the scope
attribute of a <th>
:
Specifies which cells the header cell applies to
The five possible values of scope
are as follows:
row
— the header cell applies to the subsequent cells in the underlying row.col
— the header cell applies to the subsequent cells in the underlying column.rowgroup
— the header cell applies to the subsequent cells in the underlying group of rows.colgroup
— the header cell applies to the subsequent cells in the underlying group of columnsauto
— the scope is determined based on context. This is the default value in casescope
is omitted from a<th>
.
Let's dive deeper into each of the starting four values here to understand what scope
has to offer us...
The row
and col
scopes
The simpler of the four scope
values are row
and col
, the latter being the simplest.
row
scope of a <th>
element means that the header applies to the entire set of subsequent cells in its respective row.Such a scope is common when we have row headers as opposed to the column headers, which is the more typical usage of headers. We'll see an example shortly below.
On the same lines,
col
scope of a <th>
element means that the header applies to the entire set of subsequent cells in its respective column.Let's consider an example to help understand both the row
and col
scopes.
Say we have to represent the following table using HTML, showcasing the available time slots on weekdays for a meeting with the CEO of a company:
Mon | Tue | Wed | Thu | Fri | |
---|---|---|---|---|---|
12:00 - 12:30 | Available | ||||
12:30 - 13:00 | Available | Available | |||
13:00 - 13:30 | Available | ||||
13:30 - 14:00 | Available | Available | |||
14:00 - 14:30 | Available |
Notice that there are precisely two different kinds of headers: the ones for the weekdays are column headers, governing their entire columns, whereas the ones for the time slots are row headers, governing their entire rows.
Here's the HTML to replicate this table's content and structure:
<table border="1">
<thead>
<tr>
<td> </td>
<th>Mon</th>
<th>Tue</th>
<th>Wed</th>
<th>Thu</th>
<th>Fri</th>
</tr>
</thead>
<tr>
<th>12:00 - 12:30</th>
<td>Available</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>12:30 - 13:00</th>
<td></td>
<td></td>
<td>Available</td>
<td>Available</td>
<td></td>
</tr>
<tr>
<th>13:00 - 13:30</th>
<td></td>
<td></td>
<td>Available</td>
<td></td>
<td></td>
</tr>
<tr>
<th>13:30 - 14:00</th>
<td>Available</td>
<td></td>
<td></td>
<td></td>
<td>Available</td>
</tr>
<tr>
<th>14:00 - 14:30</th>
<td>Available</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
Mon | Tue | Wed | Thu | Fri | |
---|---|---|---|---|---|
12:00 - 12:30 | Available | ||||
12:30 - 13:00 | Available | Available | |||
13:00 - 13:30 | Available | ||||
13:30 - 14:00 | Available | Available | |||
14:00 - 14:30 | Available |
Evidently, as of now, there is no scope
attribute set on any <th>
element above, and honestly speaking, it isn't even needed in such simple cases where we have the headers at the very top and very left of a table.
However, if we want to be explicit regarding our header cells' scopes, we can definitely sprinkle scope
on them. This is done below:
<table border="1">
<thead>
<tr>
<td> </td>
<th scope="col">Mon</th>
<th scope="col">Tue</th>
<th scope="col">Wed</th>
<th scope="col">Thu</th>
<th scope="col">Fri</th>
</tr>
</thead>
<tr>
<th>12:00 - 12:30</th>
<td scope="row">Available</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">12:30 - 13:00</th>
<td></td>
<td></td>
<td>Available</td>
<td>Available</td>
<td></td>
</tr>
<tr>
<th scope="row">13:00 - 13:30</th>
<td></td>
<td></td>
<td>Available</td>
<td></td>
<td></td>
</tr>
<tr>
<th scope="row">13:30 - 14:00</th>
<td>Available</td>
<td></td>
<td></td>
<td></td>
<td>Available</td>
</tr>
<tr>
<th scope="row">14:00 - 14:30</th>
<td>Available</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</table>
The weekday header cells get scope="col"
since they apply to the subsequent data cells (<td>
elements) in their respective columns. Similarly, the time slot header cells get scope="row"
as they apply to the subsequent data cells in their respective rows.
As stated earlier, adding in scope
has absolutely NO effect on the styling of the header cells; it's only meant for accessibility and better explaining the structure of a table.
Following is the output we get with this addition of scope
:
Mon | Tue | Wed | Thu | Fri | |
---|---|---|---|---|---|
12:00 - 12:30 | Available | ||||
12:30 - 13:00 | Available | Available | |||
13:00 - 13:30 | Available | ||||
13:30 - 14:00 | Available | Available | |||
14:00 - 14:30 | Available |
Quite obviously, there's no visual dissimilarity between this table and the one shown previously without scope
.
The rowgroup
scope
Where the row
scope applies to a single column, the rowgroup
scope applies to an entire group of columns.
rowgroup
scope of a <th>
element means that the header cell applies to the entire set of subsequent rows in the containing row group.Recall that a group of rows in a table is denoted via the sectioning elements <thead>
, <tbody>
and <tfoot>
.
Thus, ideally, the scope value rowgroup
should only be used when the respective <th>
element is nested within either of these elements and is, likewise, a part of a row group.
rowgroup
must only be used when the <th>
element is part of a row group (i.e. <thead>
, <tbody>
, or <tfoot>
).Time for an example.
Recall the following table back from the HTML Tables — Table Sections chapter:
Programming language | Release year |
---|---|
Object-oriented | |
JavaScript | 1995 |
Java | 1995 |
C++ | 1985 |
Procedural | |
C | 1972 |
Pascal | 1970 |
We have a list of five programming languages along with their release year, grouped according to their paradigm, which is displayed at the top of every group.
The headers reading 'Object-oriented' and 'Procedural' both apply to the entire set of rows following them, within their containing <tbody>
element. This is the perfect use case of the rowgroup
scope on a header cell.
In the following example, we set scope="rowgroup"
on both these headers:
<table border="1">
<thead>
<tr>
<th>Programming language</th>
<th>Release year</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="rowgroup" colspan="2">Object-oriented</th>
</tr>
<tr>
<td>JavaScript</td>
<td>1995</td>
</tr>
<tr>
<td>Java</td>
<td>1995</td>
</tr>
<tr>
<td>C++</td>
<td>1985</td>
</tr>
</tbody>
<tbody>
<tr>
<th scope="rowgroup" colspan="2">Procedural</th>
</tr>
<tr>
<td>C</td>
<td>1972</td>
</tr>
<tr>
<td>Pascal</td>
<td>1970</td>
</tr>
</tbody>
</table>
Again, visually, there is no difference between this table and the one shown before — we get the exact same output:
Programming language | Release year |
---|---|
Object-oriented | |
JavaScript | 1995 |
Java | 1995 |
C++ | 1985 |
Procedural | |
C | 1972 |
Pascal | 1970 |
But at least now, more importantly than when we set scope="row"
or scope="col"
, thanks to scope="rowgroup"
, we have clearly labeled that the 'Object-oriented' and 'Procedural' headers apply to the entire subsequent set of rows in the containing <tbody>
element.
Elaborating on this a little more, the 'Object-oriented' header applies to the entire group colored pink whereas the 'Procedural' header applies to the one colored yellow:
Programming language | Release year |
---|---|
Object-oriented | |
JavaScript | 1995 |
Java | 1995 |
C++ | 1985 |
Procedural | |
C | 1972 |
Pascal | 1970 |
Simple, isn't this?
Now, let's see the fourth and last value of the scope
attribute in this series — colgroup
.
The colgroup
scope
Just how rowgroup
extends a header's scope to the entire containing row grouping element, the colgroup
scope does so albeit for the entire containing column grouping element.
Do you recall which element serves to group a set of columns together? It's <colgroup>
, as we learnt in the previous chapter, HTML Tables — Column Groups:
colgroup
scope of a <th>
element means that the header cell applies to the entire set of columns in the underlying column group.As with rowgroup
, the colgroup
scope should ideally only be used on a <th>
element when it's part of a <colgroup>
element.
<th>
on which we wish to set scope="colgroup"
be a part of a <colgroup>
.Let's see an example, one that we've already seen from the previous chapters.
Recall the following table from the HTML Tables — Table Sections chapter:
Programming language | Paradigms | ||
---|---|---|---|
Procedural | Object-oriented | Functional | |
JavaScript | Yes | Yes | Yes |
Java | - | Yes | Yes |
C++ | Yes | Yes | Yes |
Carefully notice the 'Paradigms' header, governing further three headers beneath it: 'Procedural', 'Object-oriented', and 'Functional'.
The 'Paradigms' header here is a perfect use case for scope="colgroup"
. This is because it ought to govern the data cells not just in one column but in all three columns.
So firstly, let's add in the desired amount of <colgroup>
elements to this table to create two column groups, one for 'Programming language' and one for 'Paradigms':
<table border="1">
<colgroup></colgroup>
<colgroup span="3"></colgroup>
<thead>
<tr>
<th rowspan="2">Programming language</th>
<th colspan="3">Paradigms</th>
</tr>
...
</table>
Now, with the column group structure in place, let's apply scope="colgroup"
to the 'Paradigms' header cell:
<table border="1">
<colgroup></colgroup>
<colgroup span="3"></colgroup>
<thead>
<tr>
<th rowspan="2">Programming language</th>
<th scope="colgroup" colspan="3">Paradigms</th>
</tr>
...
</table>
Here's the result we get:
Programming language | Paradigms | ||
---|---|---|---|
Procedural | Object-oriented | Functional | |
JavaScript | Yes | Yes | Yes |
Java | - | Yes | Yes |
C++ | Yes | Yes | Yes |
Needless to say, there's absolutely nothing visually different in this table than what we had above.
Following the footsteps of the previous section, in the example below we illustrate both the column groups to which the given headers apply — 'Programming language' goes with the one colored pink while 'Paradigms' goes with the one colored yellow:
Programming language | Paradigms | ||
---|---|---|---|
Procedural | Object-oriented | Functional | |
JavaScript | Yes | Yes | Yes |
Java | - | Yes | Yes |
C++ | Yes | Yes | Yes |
Things to note
Not all header cells require scope
One question that might pop in your mind at this stage is that: Is scope
required on every <th>
element or not?
Fortunately enough, no!
The scope
attribute is NOT required on every single <th>
element in an HTML table.
To be specific, when a <th>
element occurs
- in the very first row of a table, which is typically always the row of headers of the table, or
- in the very first column of a table, which is typically always the column of headers of the table,
there's really no need of adding scope
on the <th>
, for the browser (with the default scope="auto"
setting) can easily determine the scope on its own.
Likewise, the following is not really required:
<table>
<tr>
<th scope="col">Programming language</th>
<th scope="col">Release year</th>
</tr>
<tr>
<td>JavaScript</td>
<td>1995</td>
</tr>
<tr>
<td>Java</td>
<td>1995</td>
</tr>
<tr>
<td>C++</td>
<td>1985</td>
</tr>
</table>
We're completely OK in reducing this HTML down to the following, letting go off the scope="col"
attribute from the headers:
<table>
<tr>
<th>Programming language</th>
<th>Release year</th>
</tr>
<tr>
<td>JavaScript</td>
<td>1995</td>
</tr>
<tr>
<td>Java</td>
<td>1995</td>
</tr>
<tr>
<td>C++</td>
<td>1985</td>
</tr>
</table>
It's only when the <th>
s appear in positions apart from the ones given above that we need to think about adding scope
to them in order to be explicit about which data cells do they apply to.
scope
doesn't have any stylistic effect
Although, we have seen this point in action a handful of times above, it's important to re-emphasize on it.
The scope
attribute is NOT meant to produce any stylistic effect in a table; it's rather exclusively meant to make a table more accessible for screen readers by making it clear as to which data cells (<td>
s) correspond to which header, or set of headers.
Thus, no matter how many scope
s we have in a table, it'll be displayed the exact same way with or without them.
Further reading
To learn even more about the scope
attribute in HTML, consider the following resources: