CSS Styling Tutorial To Clean Up Your HTML Tables Today
In our Tables Tutorial we created a table to present some data about the popularity of different content management systems. In this tutorial, we’re going to add some CSS styling to our table. This tutorial assumes that you have a solid understanding of CSS implementation. If you’re brand new to CSS you may struggle to follow along, and you’ll be better served by taking a few minutes to review our CSS tutorial before proceeding on with this Table Styling tutorial.
Contents
Table Improvements
Here’s our table code as we left it at the end of the Tables Tutorial:
<table> <caption>Most Popular Content Management Systems</caption> <thead> <tr> <th>CMS</th> <th>Usage *</th> <th>Change Since Jan 1</th> <th>Market Share *</th> <th>Change Since Jan 1</th> </tr> </thead> <tfoot> <tr> <td>Totals</td> <td>33.3%</td> <td></td> <td>76%</td> <td></td> </tr> <tr> <td colspan="5">* <strong>Usage</strong> is percentage of surveyed websites that use the associated CMS. <strong>Market Share</strong> is the percentage of surveyed websites powered by a CMS that use the associated CMS. For example, 25.8% of all surveyed websites use WordPress, and WordPress commands 59.1% market share of the total CMS market.</td> </tr> <tr> <td colspan="5">The data in this table is provided courtesy of <a href="http://w3techs.com" target="_blank">W3Techs</a> and was captured in February 2016. To learn more about this topic visit the <a href="http://w3techs.com/technologies/overview/content_management/all" target="_blank">overview of content management systems</a> from W3Techs.</td> </tr> </tfoot> <tbody> <tr> <td>WordPress</td> <td>25.8%</td> <td>+0.2%</td> <td>59.1%</td> <td>+0.3%</td> </tr> <tr> <td>Joomla</td> <td>2.8%</td> <td>No Change</td> <td>6.4%</td> <td rowspan="4">No Change</td> </tr> <tr> <td>Drupal</td> <td>2.2%</td> <td>+0.1%</td> <td>4.9%</td> </tr> <tr> <td>Magento</td> <td>1.3%</td> <td>+0.1%</td> <td>2.9%</td> </tr> <tr> <td>Blogger</td> <td>1.2%</td> <td>No Change</td> <td>2.7%</td> </tr> </tbody> </table>
And here’s how our table looks before adding any additional CSS styling:
CMS | Usage * | Change Since Jan 1 | Market Share * | Change Since Jan 1 |
---|---|---|---|---|
Totals | 33.3% | 76% | ||
* Usage is percentage of surveyed websites that use the associated CMS. Market Share is the percentage of surveyed websites powered by a CMS that use the associated CMS. For example, 25.8% of all surveyed websites use WordPress, and WordPress commands 59.1% market share of the total CMS market. | ||||
The data in this table is provided courtesy of W3Techs and was captured in February 2016. To learn more about this topic visit the overview of content management systems from W3Techs. | ||||
WordPress | 25.8% | +0.2% | 59.1% | +0.3% |
Joomla | 2.8% | No Change | 6.4% | No Change |
Drupal | 2.2% | +0.1% | 4.9% | |
Magento | 1.3% | +0.1% | 2.9% | |
Blogger | 1.2% | No Change | 2.7% |
At the end of our previous tutorial, we identifed five things that we could do to further improve the table.
- The table caption could use some styling to add emphasis and draw attention.
- The explanation and attribution comments in the table footer need to shrink in size a bit so that they aren’t quite as prevalent.
- The first column entries could be styled differently from the rest of the table data cells.
- We may want to center the contents of our td elements.
- This table doesn’t look very good on a small screen. We should make some changes so that it renders a little better on smaller devices.
In this tutorial, we’re going to improve the performance of our table by adding CSS styles to accomplish all of these objectives.
Fonts in Tables
Styling Table Text
Let’s start by taking care of the text-styling. Here are the changes we want to implement:
- The caption needs to increase in size so that is it more prominent. Let’s also add some padding to the top and bottom of the caption to give it a little breathing room.
- The table heading elements need to increase in size just a little to make them stand out from the table data.
- We also want to increase the size of the first column of table data elements.
- The footer explanation and attribution text need to shrink in size just a bit so that it doesn’t detract from the table data but remain easily readable. We also want to make sure they remain left-aligned.
- We want to center the text in all of our
td
elements.
Adjusting Font Size
We can control font size using the font-size
property like this:
/*Targets the caption text*/ table caption { font-size: 1.5em; padding: 10px 5px; } /*Targets the headings and first column*/ th, td:nth-child(1) { font-size: 1.1em; font-weight: 500; } /*Targets footer explanation and attribution*/ tfoot tr:nth-child(1n+2) { font-size: .9em; font-weight: normal; text-align: left; }
We’ve used a special selector for two of these rulesets called nth-child
. This selector is a powerful CSS tool which can be used to pinpoint elements based on their position relative to their parent element. There are a few different values you can use for the nth-child
selector:
- Numbers, such as 1, identify a specific child element. For example, we were able to target the first column of our table with the selector
td:nth-child(1)
. This selector targets thetd
element that is the first child of its parent element. By picking the firsttd
element in each row, we’ve targeted the first column. - Words like
odd
oreven
can be used to target every other child element. - Any formula using the format
an+b
can be used. In our case, we used1n+2
. This formula will target every child element that exists as a possible solution to that equation which includes every child element other than the first. For example:- Replace
n
with “0” and we get 1*0+2 = 2. - Replace
n
with “1” and we get 1*1+2 = 3. - Replace
n
with “2” and we get 1*2+2 = 4. - And so forth.
- Replace
Centering Table Data
Centering our table data entries is as easy as adding a single CSS rule. While we’re at it, let’s also add a little padding around each table data entry to add a little whitespace to the entire table.
td { text-align: center; padding: 5px; }
With our CSS in place, when we load our table we can see that the font styling has been changed.
CMS | Usage * | Change Since Jan 1 | Market Share * | Change Since Jan 1 |
---|---|---|---|---|
Totals | 33.3% | 76% | ||
* Usage is percentage of surveyed websites that use the associated CMS. Market Share is the percentage of surveyed websites powered by a CMS that use the associated CMS. For example, 25.8% of all surveyed websites use WordPress, and WordPress commands 59.1% market share of the total CMS market. | ||||
The data in this table is provided courtesy of W3Techs and was captured in February 2016. To learn more about this topic visit the overview of content management systems from W3Techs. | ||||
WordPress | 25.8% | +0.2% | 59.1% | +0.3% |
Joomla | 2.8% | No Change | 6.4% | No Change |
Drupal | 2.2% | +0.1% | 4.9% | |
Magento | 1.3% | +0.1% | 2.9% | |
Blogger | 1.2% | No Change | 2.7% |
A Look Back: How it Used to Be Done
Let’s take a break from the table we’ve been working on to take a look back at how things were done just a few years ago. This topic is of special interest to webmasters who have inherited an antiquated website with a lot of old HTML tables. In the past, it was common to use the obsolete <font>
element to assign font styles to table elements. The problem with this method? It was horrendously tedious since the <font>
element had to be added to each and every table cell. If you’ve ever looked at the source code of an antiquated website you might have seen a mountain of difficult-to-manage code that looks something like this:
<TABLE BORDER BGCOLOR=NAVY> <TR> <TH><FONT COLOR=WHITE FACE="Geneva, Arial" SIZE=6>fruit</FONT></TH> <TH><FONT COLOR=WHITE FACE="Geneva, Arial" SIZE=6>state</FONT></TH> </TR> <TR> <TD><FONT COLOR=WHITE FACE="Geneva, Arial" SIZE=6>apples</FONT></TD> <TD><FONT COLOR=WHITE FACE="Geneva, Arial" SIZE=6>Washington</FONT></TD> </TR> <TR> <TD><FONT COLOR=WHITE FACE="Geneva, Arial" SIZE=6>pineapples</FONT></TD> <TD><FONT COLOR=WHITE FACE="Geneva, Arial" SIZE=6>Hawaii</FONT></TD> </TR> </TABLE>
Yikes. This can all be done a lot more easily with CSS. Let’s look at an example. The following CSS (nested inside an HTML style
element or in an external style sheet creates a rule that applies to elements of the boldtable
class, and also to <td>
and <th>
elements inside the boldtable
class:
.boldtable, .boldtable td, .boldtable th { font-family: sans-serif; font-size: 20pt; color: white; background-color: navy; }
Now, we can clean up that table HTML, add a single class to the table
element, and control all of our table’s font styles with a single CSS ruleset.
<table class="boldtable"> <tr> <th>fruit</th> <th>state</th> </tr> <tr> <td>apples</td> <td>Washington</td> </tr> <tr> <td>pineapples</td> <td>Hawaii</td> </tr> </table>
If you we put that clean HTML together with those simple CSS rules, here’s what we get:
fruit | state |
---|---|
apples | Washington |
pineapples | Hawaii |
Thankfully, the <font>
element was deprecated in HTML 4.01 all the way back in 1999 and made obsolete with the release of HTML5. If you happen to run across this element, don’t hesitate to remove it and replace it with a modern CSS alternative.
Formatting Borders and Backgrounds
After adding just a few text-styling adjustments, our table already looks much better. However, we can make it stand out even more by adjusting the borders and backgrounds. Here’s what we’re going to do:
- We’ll remove all table borders so that we can use colors rather than borders to create separation between our rows of data.
- A popular table styling effect is to alternate the background color of table rows. Let’s implement that style.
- The table heading will stand out if we apply a more striking background color. Let’s use a darker color to draw attention to our
th
elements.
We can make all of those things happen with the following CSS statements:
/*Remove the borders from all table elements*/ table, th, td { border: none; } /*Apply a background color to the table heading*/ thead { background-color: #a7a37e; } /*Apply a background color to every other row in the table body*/ tbody tr:nth-child(even) { background-color: #efecca; } /*Apply a background color to every other row in the table footer*/ tfoot tr:nth-child(odd) { background-color: #efecca; }
You probably noticed that we’re using the nth-child
selector with the even
value for the table body rows, but the odd
value for the table footer rows. Why is this? The first row of our table is the header row, and we’ve applied a strong color to this row. If we’re going to alternate between rows with and without a background, then the first row after the header should have no background. This is why we used the nth-child(even)
selector to pick out the table body rows which should receive the background color. By starting our background on the second table body row, we leave the very first row without a background. There are 5 table body rows. So the last table body row will not have a background color. As a result, we need the first table footer row to have a background color in order for our pattern to remain consistent, and this is why we have used the nth-child(odd)
selector to identify the footer rows that should receive the background color. In order to create the every-other-row background color effect we’re also going to have to get rid of our rowspan
attribute and add td
elements using “No Change” as the content where the rowspan
element used to be.
CMS | Usage * | Change Since Jan 1 | Market Share * | Change Since Jan 1 |
---|---|---|---|---|
Totals | 33.3% | 76% | ||
* Usage is percentage of surveyed websites that use the associated CMS. Market Share is the percentage of surveyed websites powered by a CMS that use the associated CMS. For example, 25.8% of all surveyed websites use WordPress, and WordPress commands 59.1% market share of the total CMS market. | ||||
The data in this table is provided courtesy of W3Techs and was captured in February 2016. To learn more about this topic visit the overview of content management systems from W3Techs. | ||||
WordPress | 25.8% | +0.2% | 59.1% | +0.3% |
Joomla | 2.8% | No Change | 6.4% | No Change |
Drupal | 2.2% | +0.1% | 4.9% | No Change |
Magento | 1.3% | +0.1% | 2.9% | No Change |
Blogger | 1.2% | No Change | 2.7% | No Change |
Making a Table Responsive
Our data table now looks pretty good as long as you’re using a laptop or desktop computer to view it. However, when viewed with a small device, such as a small tablet or smartphone, our table is nearly unusable. You either have to zoom so far out that you can’t read the content, or you have to pan back and forth to read all of the content. We can write some additional rules that will be implements based on the results of a media query to resize and rearrange our table’s contents based on the size of a device screen size. The technique we’re going to use is explained in detail at CSS Tricks. By resizing the browser window, we can see that the table begins to have issues when the viewport shrinks below around 780 pixels. Here’s the media query we’ll use to set up 780px as our breakpoint.
@media only screen and (max-width: 780px) { /*CSS styles will be added here*/ }
Convert Table Elements
First, we need to convert the table elements to block level elements with a line of CSS that looks like this:
table, thead, tbody, tfoot, tr, th, td { display: block; }
This will allow us to break the elements out of their standard layout and position them as we wish.
Move the Table Header Off-Screen
We’re going to be adding new labels to our td
elements using CSS, but we want to keep the existing headers for accessibility purposes. To do this we’re going to position the header elements offscreen far enough that they won’t be seen, but assistive technologies will still be able to find them. We’re also going to move the Totals row from the table footer offscreen. While this was an interesting row to have, the information it contained is not critical to understanding the contents of the table.
thead tr, tfoot tr:nth-of-type(1) { position: absolute; top: -9999px; left: -9999px; }
Convert Each Table Data Entry Into its Own Row
Rather than position our td
elements in a row, we now want them to appear stacked on top of each other. By converting the td
elements into block level elements above, we’ve already stacked them on top of each other. Now we’ll apply 50% left-hand padding so that the contents begins in the middle of the td
element. We’ll also need to add position: relative;
to our td
elements so that when we use position: absolute;
to add new data lables, they will appear relative to the td element.
td { position: relative; padding-left: 50%; }
We already hid the table footer Totals line, but we kept the attribution and explanatory comments. Since these td
elements will be affected by the styles we wrote in the last step, we need to write more specific styles for these elements.
tfoot tr td { padding-left: 0%; text-align: left; }
These two rules will cause the text in our footer elements to be left-aligned and to take up the full width of the table.
Format and Add New Data Labels
Our old data labels, the table header th
elements, are hidden off screen. They’ll be picked up by assistive technologies, but for most visitors they are not visible. We can use CSS to position new data labels next to our table body td
elements with the following rules.
td:before { position: absolute; top: 5px; left: 5px; white-space: nowrap; text-align: left; }
First, we tell the browser to position the :before
content in absolute position relative to the td
element, but offset from the top and left sides by 5 pixels. This duplicates the padding added around the content in the td
elements. Next, we apply the white-space: nowrap
rule to keep the new data labels from wrapping, and align the text with the left-hand side of the td
element. Now we’re ready to add our labels.
tbody td:nth-child(1):before { content: "CMS"; } tbody td:nth-child(2):before { content: "Usage*"; } tbody td:nth-child(3):before { content: "+/- since Jan"; } tbody td:nth-child(4):before { content: "Market Share*"; } tbody td:nth-child(5):before { content: "+/- since Jan"; }
We add tbody
to the selector to ensure we don’t accidentally apply labels to the tfoot
elements appearing beneath our table caption.
The Finished Product
Once we pull together all of our code, the table code as well as the styling and responsive rules we’ve created, and render our table in a browser, here’s what we get. As you resize your browser window (or if you’re viewing this tutorial on a smartphone) you’ll see that our table automatically reformats once you reach a viewport width of less than 780 pixels, and is now readable on smaller screens.
CMS | Usage * | Change Since Jan 1 | Market Share * | Change Since Jan 1 |
---|---|---|---|---|
Totals | 33.3% | 76% | ||
* Usage is percentage of surveyed websites that use the associated CMS. Market Share is the percentage of surveyed websites powered by a CMS that use the associated CMS. For example, 25.8% of all surveyed websites use WordPress, and WordPress commands 59.1% market share of the total CMS market. | ||||
The data in this table is provided courtesy of W3Techs and was captured in February 2016. To learn more about this topic visit the overview of content management systems from W3Techs. | ||||
WordPress | 25.8% | +0.2% | 59.1% | +0.3% |
Joomla | 2.8% | No Change | 6.4% | No Change |
Drupal | 2.2% | +0.1% | 4.9% | No Change |
Magento | 1.3% | +0.1% | 2.9% | No Change |
Blogger | 1.2% | No Change | 2.7% | No Change |