8. Tables & Lists
Tables
Tables allow you to format content into rows and columns. The concept is similar to that of spreadsheets.
As is the case with spreadsheets, HTML tables are best used to display data. Using a table to display your data provides a logical structure and can provide semantic information about the content of the table.
Tables should not be used for design or layout purposes. They should be used to logically structure and present data.
Unlike the elements we have discussed so far, tables require several other interdependent elements. The <tr>
(table row) element is nested within the <table>
element to create a row in your table. Within the <tr>
, the <td>
(table data) element is used to create the cells which contain the content.
Here is the basic structure of an HTML table:
<table class="fahrvergnugen">
<tr>
<td>Row 1 - Column 1 data</td>
<td>Row 1 - Column 2 data</td>
</tr>
<tr>
<td>Row 2 - Column 1 data</td>
<td>Row 2 - Column 2 data</td>
</tr>
</table>
Notice how I indented the elements using the tab key. It would be a good idea to format your code in this manner. It makes the code so much more readable and easier to maintain.
Also notice that I added a class. A class is not required, but I'm going to use that as the selector in my CSS.
Output without any CSS styling:
Styling tables with CSS
There are several HTML attributes for the table element. However, they have been deprecated in HTML5.
Since most of these are HTML attributes that deal with styling, it makes sense to avoid them. It's best to keep all styling in the CSS so you can easily make changes later without disturbing the HTML.
Just in case you missed the previous 352 times I've mentioned this: HTML is for structure and meaning. CSS is for styling.
Let's use the class to apply some CSS styling:
.fahrvergnugen {
border: 1px solid #000;
}
Note that my class name ("fahrvergnugen") is completely meaningless. You could choose your own semantic class name that describes the purpose/meaning of the table.
Or you could just use the element name ("table") as the selector.
Or you could use a descendant selector to target tables within the main
element. On a website, you would likely want all tables within your main content to have the same styling:
main table {
border: 1px solid #000;
}
But in this lesson, I'm going to go with the "fahrvergnugen" class because it's fun to say :)
Output:
Now let's add a border to the <td>
elements:
.fahrvergnugen {
border: 1px solid #000;
}
.fahrvergnugen td {
border: 1px solid #000;
}
Or, we could (and should) reduce the amount of code by using a group selector. Let's combine those entries:
.fahrvergnugen, .fahrvergnugen td {
border: 1px solid #000;
}
Note that ".fahrvergnugen" IS the table element (I have added that class to the table element in the HTML). And the td
is inside the table
in our HTML structure.
If I was targeting all tables within the main
element, I would use this as the selector:
main table, main table td {
border: 1px solid #000;
}
By default, this will result in a double border:
To fix this, we can use the border-collapse
property:
.fahrvergnugen {
border-collapse: collapse;
}
.fahrvergnugen, .fahrvergnugen td {
border: 1px solid #000;
}
Output:
We can add padding to the <td>
elements to make it look better:
.fahrvergnugen {
border-collapse: collapse;
}
.fahrvergnugen, .fahrvergnugen td {
border: 1px solid #000;
}
.fahrvergnugen td {
padding: 6px;
}
Output:
There are all kinds of styling options that can be applied to tables. Just think about what you have in your toolbox already: classes, background-colors, background-images, borders, and so much more. You have the knowledge to create some very attractive and professional tables of data right now. Explore your creative side and you might come up with something great!
Creating accessible, semantic tables
Beyond the basic table structure described above, there are other elements that may be used in the creation of tables. The <th>
(table header) element is an essential part of most data tables.
<table class="fahrvergnugen">
<tr>
<th>Column 1 Heading</th>
<th>Column 2 Heading</th>
</tr>
<tr>
<td>Row 1 - Column 1 data</td>
<td>Row 1 - Column 2 data</td>
</tr>
<tr>
<td>Row 2 - Column 1 data</td>
<td>Row 2 - Column 2 data</td>
</tr>
</table>
Output:
The <th>
element attaches meaning to the structure of your data. It communicates to computer devices that the words inside the element describe the data in that column.
Grouping rows
You can attach more structure and meaning to your tables by adding <thead>
, <tbody>
, and <tfoot>
elements.
If you use either the <thead>
or <tfoot>
elements, you should use the <tbody>
element also.
<table class="fahrvergnugen">
<thead>
<tr>
<th>Column 1 Heading</th>
<th>Column 2 Heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row 1 - Column 1 data</td>
<td>Row 1 - Column 2 data</td>
</tr>
<tr>
<td>Row 2 - Column 1 data</td>
<td>Row 2 - Column 2 data</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Footer Information</td>
</tr>
</tfoot>
</table>
Output:
Colspan and rowspan
From the example above, you may have already guessed what the colspan
attribute does. It extends the cell horizontally by the number of columns you specify as a value.
The colspan
attribute may be applied to the <td>
and <th>
elements.
And rowspan
extends the cell vertically by the number of rows specified in the rowspan attribute. For an example of using rowspan
, see W3 Schools.
Tables and accessibility
Accessibility is the law of the land. It's important. So, make sure to pay close attention anytime you see the word "accessibility" in these lessons.
And you can use this WAVE evaluation tool to check your web pages for accessibility issues.
The courts have ruled that the Americans with Disabilities Act also applies to websites.
The federal government and your state government may also also have accessibility guidelines for certain types of websites.
But, in general, you should be fine if your website meets the AA level of the WCAG standards.
Many of the standards involve making sure that meaning can be extracted from your code programmatically, even if the user is unable to see the web page.
The <caption>
element is one way that you can provide more meaning when creating tables. It should be used to provide a title for the table.
By default, the caption text will display above the table. But this can be changed using the caption-side
CSS property.
<table class="fahrvergnugen">
<caption>Chicken Prices in Omaha</caption>
<thead>
<tr>
<th>Column 1 Heading</th>
<th>Column 2 Heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>Row 1 - Column 1 data</td>
<td>Row 1 - Column 2 data</td>
</tr>
<tr>
<td>Row 2 - Column 1 data</td>
<td>Row 2 - Column 2 data</td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="2">Footer Information</td>
</tr>
</tfoot>
</table>
Describing tables
In some cases, it might be necessary to provide a description or summary of your table. This can help communicate information about your table to users, including those with visual impairments.
In prior versions of HTML, there was a summary
attribute that was used for this purpose. However, this attribute has been deprecated.
You could provide a paragraph before the table for this purpose. Or you could provide this information in the caption
element. See the Web Accessibility Initiative documentation for more information.
With all of that said, the best option is to create a simple and logical table that doesn't require an explanation.
Lists
Like tables, lists require more than one element. Fortunately, there are not as many elements as the table element. Only two elements are required.
Unordered List:
<ul>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ul>
Output:
- item 1
- item 2
- item 3
Ordered List:
<ol>
<li>item 1</li>
<li>item 2</li>
<li>item 3</li>
</ol>
Output:
- item 1
- item 2
- item 3
<dl>
<dt>Term 1</dt>
<dd>Description 1</dd>
<dt>Term 2</dt>
<dd>Description 2</dd>
</dl>
Output:
- Term 1
- Description 1
- Term 2
- Description 2
Nested lists
You can nest lists in order to create different levels in your list structure. For example:
<ul>
<li>item 1</li>
<li>item 2
<ul>
<li>item 2a</li>
<li>item 2b</li>
</ul>
</li>
<li>item 3</li>
</ul>
Output:
- item 1
- item 2
- item 2a
- item 2b
- item 3
Notice that the nested <ul>
is inside of a <li>
element.
<ul>
<li>item 1</li>
<li>item 2
<ul>
<li>item 2a</li>
<li>item 2b</li>
</ul>
</li>
<li>item 3</li>
</ul>
The </li>
tag must go after the </ul>
tag:
<ul>
<li>item 1</li>
<li>item 2 <!-- Don't end the li here -->
<ul>
<li>item 2a</li>
<li>item 2b</li>
</ul>
</li> <!-- End it here -->
<li>item 3</li>
</ul>
The <ul>
is a child of that <li>
element. And the child must always end before the parent.
If you do not format this correctly, you might get the following error message when checking HTML validation:
"Element ul not allowed as child of element ul in this context."
Styling lists
The list-style
property is a shorthand property. It allows you to declare a string of values instead of using list-style-type
, list-style-image
, list-style-position
, etc. See W3 Schools for more information.
ul {
list-style: circle;
}
Output:
list-style
can also be applied to <li>
elements.And note that in most cases, you will need to be more specific with your selector. For examples, we could target unordered lists in the main content:
main ul {
list-style: circle;
}
Or you could add a class to the ul
element and use a class selector in the CSS.
Image bullets
There are several ways to apply image bullets to your lists. A couple of options are the list-style-image
and background-image
properties.
list-style-image
doesn't offer the designer much control over the position of the bullet. The bullet is automatically placed at the top left of the list item. Sometimes this doesn't line up right so you might want to use background-image
instead.
In this case, it works using list-style-image
.
ul {
list-style: url(images/green-bullet.png);
}
Output:
For a demonstration of using a CSS background-image for bullets, see this example.
Styling different levels of a list
We've talked about styling elements within elements. Lists are no different. You can use the structure of your HTML to style different levels in your lists.
<ul>
<li>item 1</li>
<li>item 2
<ul>
<li>item 2a</li>
<li>item 2b</li>
</ul>
</li>
<li>item 3</li>
</ul>
If I wanted to style the nested ul inside the parent ul, I could use this as a selector:
ul ul {
list-style: upper-alpha;
}
If I needed a more specific selector to target the li elements inside the nested ul, I could use:
ul ul li {
font-style: italic;
}
When using descendant selectors, we are going "deeper" into the HTML structure from left to right. In this case, we have a li inside of a ul that's inside of another ul. Take a look at the HTML code and make sure that you understand that contextual relationship.
Once again, you could be more specific with the selector, such as:
main ul ul li {
font-style: italic;
}
Or you could add a class to the parent ul and use something like:
.list-class ul li {
font-style: italic;
}
Also note that we have omitted one "level" in that hierarchy. The full "path" to the li elements inside the nested ul is:
<ul>
=> <li>
=> <ul>
=> <li>
<ul> <!-- 1 -->
<li>item 1</li>
<li>item 2 <!-- 2 -->
<ul> <!-- 3 -->
<li>item 2a</li>
<li>item 2b</li> <!-- 4 -->
</ul>
</li>
<li>item 3</li>
</ul>
- Everything is inside the parent
ul
element. - Then a
<li>
element - with a
<ul>
nested inside. - And then we have
<li>
elements inside of that.
So, this selector also works for styling all of the li
elements inside the nested ul
:
ul li ul li {
font-style: italic;
}