0% found this document useful (0 votes)
4 views

Styling Tables Creating Tables with CSS

This chapter covers two main topics related to table styling using CSS: formatting table elements and transforming non-tabular data into table-like structures. It provides detailed instructions on how to apply borders, padding, alignment, and additional styling techniques such as backgrounds and zebra striping to enhance the visual appearance of tables. The chapter also includes practical examples and CSS code snippets for better understanding.

Uploaded by

talajezzini2004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

Styling Tables Creating Tables with CSS

This chapter covers two main topics related to table styling using CSS: formatting table elements and transforming non-tabular data into table-like structures. It provides detailed instructions on how to apply borders, padding, alignment, and additional styling techniques such as backgrounds and zebra striping to enhance the visual appearance of tables. The chapter also includes practical examples and CSS code snippets for better understanding.

Uploaded by

talajezzini2004
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 13

Styling Tables

In this chapter I will explain two different topics that are largely unrelated except that they both involve tables.
First, I will demonstrate how to use CSS to format a table element. In Chapter 6 I described all of the various
HTML elements that are used to construct a table such as table, table row (tr), table header cell (th), and table
cell (td). Now I’ll show you the CSS attributes that are available to arrange these elements, visually. The second
topic is to explain how you can use CSS to turn non-tabular data into table-like elements so you can use similar
styling techniques.

Styling Tables
We have explained the markup elements used to create a table. You can refer back to that chapter for more
details; however, as a quick review, the following table uses most of the common table elements.

This provides a summary of the pieces used in the game of Chess. I will be using this table to demonstrate most
of the styling options. The markup is shown in Listing 13-1 and the resulting table is rendered as shown in
Figure 13-1.
Listing 13-1. A simple HTML table
<table>
<caption>Chess Pieces</caption>
<thead>
<tr>
<th>Name</th>
<th>Qty</th>
<th>Points</th>
<th>Symbol</th>
<th>Movement</th>
</tr>
</thead>
<tbody>
<tr>
<th>King</th><td>1</td><td>n/a</td>
<td><img src="king.png" alt="King" /></td>
<td>1 space in any direction</td>
</tr>
<tr>
<th>Queen</th><td>1</td><td>10</td>
<td><img src="queen.png" alt="Queen" /></td>
<td>any number of spaces in any direction</td>
</tr>
<tr>
<th>Rook</th><td>2</td><td>5</td>
<td><img src="rook.png" alt="Rook" /></td>
<td>any number if spaces forward, backwards, or sideways</td>
</tr>
<tr>
<th>Bishop</th><td>2</td><td>3</td>
<td><img src="bishop.png" alt="Bishop" /></td>
<td>any number of spaces diagonally</td>
</tr>
<tr>
<th>Knight</th><td>2</td><td>3</td>
<td><img src="knight.png" alt="Knight" /></td>
<td>2 spaces up or down and 1 space sideways OR 1 space up or down and 2 spaces
sideways; can jump pieces</td>
</tr>
<tr>
<th>Pawn</th><td>8</td><td>1</td>
<td><img src="pawn.png" alt="Pawn" /></td>
<td>generally 1 space forward; first move can be 2 spaces forward; captures 1 space forward
diagonally</td>
</tr>
</tbody>
<tfoot>

1
<tr> <th>Totals</th><td>16</td><td>40</td><td></td><td></td> </tr>
</tfoot>
</table>

Figure 13-1. The initial, unstyled table

Basic Table Styling


You can see from Figure 13-1 that we have some work to do as this looks awful. However, applying some
simple border, padding, and alignment attributes will do wonders.

Borders
There are four elements that you can place a border around: the entire table (table), the caption (caption), and
the cells (th and td). The table row (tr) element is a container element but does not have any visible content of
its own. Likewise, thead, tbody, and tfoot are also containers and have no visible content. You can apply styles
to these elements and they would be inherited by the child elements. However, border properties are not
inherited for good reason. I will come back to row borders later but for now, we’ll start with the table and cells.
The following CSS rules will add a thick border around the table and a thin border around the cells. This is
rendered as shown in Figure 13-2.
table {
border: 3px solid black;
}
th, td {
border: 1px solid black;
}

Figure 13-2. Add a border to the table and cells


2
So now each cell has a border around it; however, the browser has put a space between the borders.
This is controlled by the border-spacing attribute, which has a default value of 2px. You can increase this if you
want more space or set it to 0 to remove the space entirely. If I add the following to the table selector, the result
is shown in Figure 13-3.
border-spacing: 0;

Figure 13-3. Removing the border space

The spaces are gone but the borders are thicker now. They’re not actually thicker, but since they are touching,
the width of each is combined. If this is not the effect you want, instead of removing the space between the
border, you can use the border-collapse attribute to make adjoining cells share a common border. This
supports the following values:
• separate - (default) the borders between adjoining cells are drawn separately. The amount of space
between them is controlled by the border-spacing property as I’ve previously explained. This invokes the
browser’s separated borders model.
• collapsed - two adjoining borders are collapsed into a single shared border. This is referred to as the
collapsing border model.

What happens when adjoining borders have different style attributes: which one is used? The W3C
Recommendation provides simple and clear guidelines:

The following rules determine which border style “wins” in case of a conflict:
1. Borders with the ‘border-style’ of ‘hidden’ take precedence over all other conflicting borders. Any border
with this value suppresses all borders at this location.
2. Borders with a style of ‘none’ have the lowest priority. Only if the border properties of all the elements
meeting at this edge are ‘none’ will the border be omitted (but note that ‘none’ is the default value for the
border style.)
3. If none of the styles are ‘hidden’ and at least one of them is not ‘none’, then narrow borders are discarded
in favor of wider ones. If several have the same ‘border-width’ then styles are preferred in this order:
‘double’, ‘solid’, ‘dashed’, ‘dotted’, ‘ridge’, ‘outset’, ‘groove’, and the lowest: ‘inset’.
4. If border styles differ only in color, then a style set on a cell wins over one on a row, which wins over a
row group, column, column group and, lastly, table.

When two elements of the same type conflict, then the one further to the left (if the table’s ‘direction’ is ‘ ltr’;
right, if it is ‘rtl’) and further to the top wins.
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1), paragraph 17.6.2.1, Border conflict resolution
Replacing the border-spacing attribute with the following declaration will cause the table to be rendered as
shown in Figure 13-4.
border-collapse: collapse;

3
Figure 13-4. Using the border-collapse attribute

Empty Cells
If you’re using the separated borders model, you can control what happens to an empty cell using the empty-
cells attribute. This has two values: show and hide, with show being the default. Obviously, if the cell is empty
there is no content to display. However, the border can still be drawn around the cell and whatever background
is used can be shown as well.
If this value is set to show, the border and background will be shown; this will appear as an empty cell. If the
empty-cells attribute is set to hide, the border and background will be hidden. This will appear as if the cell did
not exist.

Note. The empty-cells attribute only works if the separated borders model is used. If you're using the collapsing
border model, this attribute is ignored.

Row Borders
Now let’s see about adding a row border. As I said, you can’t add a border to a row, only the cells within the
row. However, as I explained in the last chapter, you can set the border edges individually. For example, you
can set a border only for the top and bottom edges. Then you’ll need to set the left edge for the first cell and the
right edge for the last cell. To illustrate this technique, replace the entire CSS with the following rules to create a
border around the rows, not the individual cells.
table {
border: 3px solid black;
border-collapse: collapse;
}
th, td {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
table th:first-child, table td:first-child {
border-left: 1px solid black;
}
table th:last-child, table td:last-child {
border-right: 1px solid black;
}

The first rule creates a thick border around the entire table and includes the border-collapse attribute. The next
rule creates a thin top and bottom border around all of the cells (th and td). The last two rules use the :first-
child and :last-child pseudo-classes to set the left and right borders. This is rendered as shown in Figure 13-5.

4
Figure 13-5. Creating row borders

Personally, I don’t think this looks good for this particular table so I will revert back to the previous CSS for the
remaining demonstrations.

Padding and Alignment


I won’t say much about padding as I’ve explained this in the previous chapter. However, one of the issues with
the default style is that the borders are too close to the contents. You easily fix this by setting the padding on all
of the visible elements using the following rule.
th, td, caption {
padding: 5px;
}

Caution. You might be tempted to simply set the padding on the table element; however, the padding attribute is
not inherited. So, you'll need to set it on each element.

We explained the alignment attributes, which also apply to tables. By default, the table header cell (th) elements
are centered both horizontally and vertically. The table cell (td) elements are centered vertically but left
justified. As a general rule of thumb, text should be left justified and numbers are right justified. While perhaps
not as universally accepted, I recommend that images be centered. Certainly, in this table, the images would
look better centered. Notice the pawn is smaller than the rest and it appears misaligned.

Table cells are grouped into rows; there is no such container for columns. Column 2, for example, is just the
second cell of each row. To set the alignment of a column, we can use the :nth-of-type pseudo-selector that I
already explained. The following rules will set make the Qty and Points columns right justified, and the Symbol
column will be centered.
td:nth-of-type(1) { /*Qty that is the first td*/
text-align: right;
}
td:nth-of-type(2) { /*Points that is the 2nd td*/
text-align: right;
}
td:nth-of-type(3) { /*Symbol that is the 3rd td*/
text-align: center;
}

The :nth-of-type selector only counts elements of the specified type: the table cell, in this case. It will skip the
Name column since this is a header (th) element. The resulting table is shown in Figure 13-6.

5
Figure 13-6. Adjusting padding and alignment

Caption
Notice that the caption, visually, is outside of the table, by default, just above the table. Even though the caption
element is nested inside the table element, in terms of the table layout it is not part of the table.
To change the style of the caption you’ll need to style it separately. To keep the caption consistent with the table
you can add the following CSS rule. This will give the same size border and amount of padding as the table.
table caption {
border: 3px solid black;
}

However, the bottom border will be adjacent to the top border of the table, creating a line that is twice as wide
as the other borders. The border-collapse attribute won’t help in this scenario because the caption is not a table
element. Instead, I’ll make the width of the bottom edge 0, since it can use the table’s top border as its bottom
border. The final CSS rule will look like this, and it is rendered as shown in Figure 13-7.
table caption {
/*border: 3px solid black;*/
border-style: solid;
border-color: black;
border-width: 3px 3px 0px 3px;
}

Figure 13-7. Styling the caption

6
With the caption-side attribute, you can move this, although the only supported values are top and bottom. If
you choose to move it to below the table, set caption-side: bottom; and don’t forget to also fix the border
because now you’ll need the top edge to be 0 width instead of the bottom.

Additional Table Styling


We now have a decent-looking table; however, I will demonstrate a few more techniques, such as backgrounds
and highlighting, that you can use to improve the table layout.

Background
You can set a background color, image, or gradient on any of the table elements. I explained how each of these
can be used in the previous chapter so I won’t say much about them here. My typical approach is to provide
either a background color or gradient to the header cells. You can do this with a simple CSS rule like this; the
result is shown in Figure 13-8.
th {
background-color: #DDB;
background: linear-gradient(to bottom right, #FFF 0%, #DDB 100%);
}

Figure 13-8. Adding a gradient to the header cells

Notice, however, that the gradient starts over again with each cell. The top-left corner of every header cell is
white. You might actually prefer that, but you might rather have the gradient flow evenly across the whole
header row (or column). You can accomplish that by applying the gradient to the entire table, and then clearing
the background for the other cells, like this:
table {
background-color: #DDB;
background: linear-gradient(to bottom right, #F4F4F0 0%, #DDB 100%);
}
td {
background-color: white;
background-image: none;
}
Since the gradient is spread over a larger area, I changed the beginning color to be slightly darker to keep it
from looking too washed out in the first few cells. The resulting table is shown in Figure 13-9.

7
Figure 13-9. The revised header gradient

Tip. I am setting both the background-color and background-image in case the browser doesn't support gradients. The
border-image attribute is defined last, which will overwrite the color setting if both are supported. This is a good
practice to follow.

Zebra Striping
Another simple technique using the :nth-of-type pseudo-selector is to alternate the background color of each
row. This is known as zebra striping. This easily done with the following CSS rule.
tr:nth-of-type(even)>td {
background-color: #F4F4F0;
}

This returns every even row since the keyword even is used instead of a specific row number. You could also
use the odd keyword. However, we don’t want to apply the background to the entire row, since the header cell
(th) is part of the gradient applied earlier. The > operator is used to indicate only immediate children, and
combined with the td element selector, it will return only the table cell elements on the even rows. The result is
shown in Figure 13-10.

Figure 13-9. The revised header gradient

8
For one miscellaneous update, I’ll increase the font size of the caption using the following rule. As with the rest
of the text in this table, you can change all of the font attributes as well. Refer to Chapter 11 for the options
available.
caption {
font-size: xx-large;
}

Highlighting
You can easily highlight a row by adjusting the background color. This will work much like the zebra striping
except you select a single row. Also, in the striping example we didn’t update the header cell; in this example, I’ll
update the header cell as well. However, setting the background on a row has no effect, you need to set the
background on the row child elements, the table cells (td) and table header cells (th). The following CSS rule
will accomplish this:
tr:nth-child(3)>th, tr:nth-child(3)>td {
background-color: yellow;
}

Figure 13-10. Using zebra striping

You can also highlight a column using a similar technique. Again, you’ll need to combine two selectors:
one for the header cells and one for the other cells. The resulting table is shown in Figure 13-11.
th:nth-child(3), table td:nth-child(3) {
background-color: yellow;
}

9
Figure 13-11. Highlighting a row and a column

Tip. Notice that it is actually the fourth row that was highlighted if you count the header. If you look at the
markup, the table element has three children: a thead, tbody, and a tfoot element. The head and foot each
have a single child, a tr element. The body has six child tr elements. The tr:nth-child(3) selector will return
any row that happens to be the third child of its immediate parent. Since the body rows have a different
parent, the numbering starts back at 1. Also, I'm using :nth-child instead of :nth-of-type since I know that all
the siblings are rows. In this case :nth-child and :nth-of-type produce the same result. I recommend using
:nth-of-type in most cases as it will still work if other element types are later added.

Note. The individual elements within a table are stacked on top of each other, and it's important to know
the order of that stack, especially when using multiple backgrounds. The order is fairly intuitive: the table
element is on the bottom, on top of that lie the caption, thead, tbody, and tfoot elements. After that, the
row (tr) elements are placed and then finally, the cells (th and td). In most cases, only the caption and cells
are actually visible. However, if you are playing around with opacity, the other backgrounds can be
exposed.

10
Creating Tables with CSS
If you’ve searched the Web for articles on HTML tables, you’ve likely encountered some lively debate regarding the
use of HTML table elements. Some people state that you should never use them – that this should be done in CSS.
Opponents of this view push back and say that HTML is where this belongs, not CSS.

This might give you the notion that HTML tables and CSS tables (as the two views are sometimes referred to) are two
different techniques for accomplishing the same thing. But this is not true; these techniques were intended to solve
completely different problems.

Tabular data such as team standings, stock positions, or a list of contact details, should be in tables.
For example, if you are displaying stock positions and have four pieces of information for each stock: stock symbol,
yesterday’s closing position, percent gain or loss, and volume traded. Each piece of data such as $35.87, 0.51%, or 1.4
million, has no meaning unless you can associate these to the stock that they belong to.

It’s only when individual pieces of data (cells) are grouped together (rows) that they can have any meaning.

This is what HTML tables should be used for. Another way to look at it is that there is no other logical way to
organize these data points. If you tried grouping all the stock symbols together and then all of the closing positions, it
wouldn’t make any sense. There is inherent structure in the data, which should be captured in the HTML markup.

On the other hand, if you’re trying to lay out a web page, perhaps with a set of links on the left side and related articles
on the right side, for example, this is not tabular data. This is a job for CSS. The easiest way to distinguish between the
two scenarios is to ask is this the only logical way to structure the content. In this case, no, there are lots of ways this
could be done. You could put the links across the top of the page, and perhaps the article could be on the left.

Doing this in CSS also makes it a lot easier to adjust the layout when you need to render the page on different devices.
Accessibility is another important reason to not use tables for layout. Screen readers, for example, read the HTML,
and if you put non-tabular data into tables, the presentation of your site can be very confusing.

Display Attribute
First of all, you need to understand that the table elements work the way they do solely because of the value assigned
to the display attribute. In Chapter 10, we looked at a couple of values for the display attribute, primarily block and
inline. There are quite a few more values and they are mostly related to tables. Each of the table elements that I
explained in Chapter 6 is assigned one of these values as its default display attribute. In fact, it is the specific display
value that makes table elements work like they do. Table 13-1 lists each of the elements and the default display value
assigned to it.

Table 13-1. Table Display Attributes


HTML Element Default Display Attribute
table table
tr table-row
th, td table-cell
thead table-header-group
tbody table-row-group
tfoot table-footer-group
col table-column
colgroup table-column-group
caption table-caption

11
CSS Table Demonstration
You can accomplish the same layout with non-tabular elements by simply applying the correct value for the
display attribute. To demonstrate this, I’ll re-create the same table that was used at the beginning of the chapter
using only simple HTML elements such as div and p elements. This uses the class attribute to make it easier to
select the appropriate entities later. This is shown in Listing 13-2.
Listing 13-2. Using non-tabular elements
<div class="table">
<div class="head row">
<h3>Name</h3>
<h3>Qty</h3>
<h3>Points</h3>
<h3>Symbol</h3>
<h3>Movement</h3>
</div>
<div class="body row">
<h3>King</h3><p>1</p><p>n/a</p>
<p><img src="king.png" alt="King" /></p>
<p>1 space in any direction</p>
</div>
<div class="body row">
<h3>Queen</h3><p>1</p><p>10</p>
<p><img src="queen.png" alt="Queen" />
<p>any number of spaces in any direction</p>
</div>
<div class="body row">
<h3>Rook</h3><p>2</p><p>5</p>
<p><img src="rook.png" alt="Rook" /></p>
<p>any number if spaces forward, backwards, or sideways</p>
</div>
<div class="body row">
<h3>Bishop</h3><p>2</p><p>3</p>
<p><img src="bishop.png" alt="Bishop" /></p>
<p>any number of spaces diagonally</p>
</div>
<div class="body row">
<h3>Knight</h3><p>2</p><p>3</p>
<p><img src="knight.png" alt="Knight" /></p>
<p>2 spaces up or down and 1 space sideways OR 1 space up or down and 2 spaces sideways; can jump
pieces</p>
</div>
<div class="body row">
<h3>Pawn</h3><p>8</p><p>1</p>
<p><img src="pawn.png" alt="Pawn" /></p>
<p>generally 1 space forward; first move can be 2 spaces forward; captures 1 space forward diagonally</p>
</div>
<div class="foot row">
<h3>Totals</h3><p>16</p><p>40</p><p></p><p></p>
</div>
</div>

To style this using table layout, the entire CSS is provided in Listing 13-3. The display attributes are shown in
bold. The rest of the CSS declarations are applying the same styles that we did in the previous example. The
selectors are different because we’re using different elements but conceptually, this is identical to the previous
CSS. This will render the table exactly the same as the previous examples.

12
Listing 13-3. Using tabular layout
/* Simulate table layout on non-table elements */
.table {
display: table;
border: 3px solid black;
border-collapse: collapse;
background-color: #DDB;
background: linear-gradient(to bottom right, #F4F4F0 0%, #DDB 100%);
}
.row {
display: table-row;
}
.row>h3, .row>p {
display: table-cell;
border: 1px solid black;
padding: 5px;
vertical-align: middle;
}
.row img {
display: table-cell;
vertical-align: middle;
margin: 0 auto;
}

/* Alignment */
.row>h3 {
text-align: center;
font-size: medium;
}
.row>p:nth-child(2) { /*Qty*/
text-align: right;
}
.row>p:nth-child(3) { /*Points*/
text-align: right;
}

/* Background and zebra striping */


.body>p, .foot>p {
background-color: white;
background-image: none;
}
.body:nth-child(odd)>p, .body:nth-child(odd)>img {
background-color: #F4F4F0;
}

/* Highlighting */
.row:nth-child(4)>h3, .row:nth-child(4)>p {
background-color: yellow;
}
.row>h3:nth-child(3), .row>p:nth-child(3) {
background-color: yellow;
}

Caution I created this to demonstrate that there’s nothing special about the table elements other than their default styles. You
can use table layouts on any HTML elements. However, you should never actually build a table this way. Tabular data should be
put into table elements.

13

You might also like