Skip to main content

A Beginner's Guide to CSS | Part Seventeen - Tables

Submitted by helen on Monday, August 15, 2011 - 21:38; Modified on Wednesday, August 24, 2016 - 11:33

Welcome to another instalment of the A Beginner's Guide series. In this chapter we will be looking at an element that has gained a lot of unpopularity over the years: the table element. If you fall into the category of table-haters, hopefully this tutorial will encourage you to see the usefulness of tables. So let's get going.

What tables are used for ... and what they aren't used for

In the good old 1990s days of web design, people used tables to lay out their entire website (shockingly, some people still do, who should know better), but this is not what the table element is intended for. Tables are supposed to be used to hold data, not for layout purposes. I should note, I used to commit the aforementioned crime of using tables to lay out my websites, but, in my defence, that was over fifteen years ago, and I was just a naive kid.

In HTML4 (which, let's face it, no sane person should be using any more) and XHTML1.0, a website layout should be comprised of div elements, combined with lists, for navigation. HTML5, however, introduces several new elements, which add more semantic meaning to your content, such as header, footer and nav.

Tables are your friend

Some people have developed a phobia of tables, because it has been drilled into them that tables are bad. As a result they go out of their way to create substitute tables with divs, which they perceive as being more standard compliant than tables. This is unnecessary and results in cumbersome code that is difficult to maintain. It's perfectly acceptable to use the table element, as long as you use it for its intended purpose — to store data.

How to create a table

A table is denoted by the table element and its rows and columns by tr and td elements, respectively, which are inserted between the opening and closing table tags, as seen below. Table headings should be represented by th elements, to add more semantic meaning to the table — as opposed to creating a heading class and applying it to your top row of tds. By default, ths are rendered in bold, to distinguish them from regular columns.

Example of a table

(X)HTML Code:


<table>
  <tr>
    <th>Heading One</th>
    <th>Heading Two</th>
    <th>Heading Three</th>
  </tr>
  <tr> 
  <td>Column One</td>
  <td>Column Two</td>
  <td>Column Three</td>
  </tr>
</table>

Result:

Heading One Heading Two Heading Three
Column One Column Two Column Three

Styling tables

Applying styles to a table may seem confusing because there are several elements involved and it can often be challenging to determine which element(s) you need to target with your CSS. Let's break down some common table styling tasks so you can feel more at ease with this exercise.

Applying a border to a table and its children

At times you will want to add a border to your table and/or its components. This involves using the CSS border property, which I'm sure you're already familiar with; if not, read more about borders in A Beginner's Guide to CSS | Part Twelve - Borders in CSS.

In the below example, we will create a red border around our table and its tds.

CSS Code:


#simpleBorder, #simpleBorder td {
  border:1px solid #ff0000;
}

(X)HTML Code:


<table id="simpleBorder">
  <tr>
    <td>One</td>
    <td>Two</td>
  </tr>
  <tr> 
    <td>Three</td>
    <td>Four</td> 
  </tr>
</table>

Result:

One Two
Three Four

As you can see, we now have a red border around our table and its cells ... but, hang on, what's up with the spacing between the borders? There are two "modes", if you like, for generating borders around a table: the separated borders model and the collapsing borders model. If you do not specify a property for border-collapse, it will default to separate, which will utilise the separated borders model. This will generate individual borders around each cell, along with a two pixel gap, by setting border-spacing to 2px. That's what's going on above.

The collapsing border model will remove the space between the cells, but will also mean that you cannot specify border spacing, which may or may not be an issue for you.

Anyway, getting back on track: what if we don't want any space around our cells, how do we get rid of it? Well, you have two options, as illustrated below.

The collapsing borders model

If you don't want separate borders around your cells, set border-collapse to collapse, which will invoke the collapsing borders model and prevent spacing between the cells. This may also mean that the border around the edge of your table collapses into the outer borders of your cells.

CSS Code:


#borderCollapseTable, #borderCollapseTable td {
  border:1px solid #ff0000;
}

#borderCollapseTable {
  border-collapse:collapse;
}

(X)HTML Code:


<table id="borderCollapseTable">
  <tr>
    <td>One</td>
    <td>Two</td>
  </tr>
  <tr>
    <td>Three</td>
    <td>Four</td> 
  </tr>
</table>

Result:

One Two
Three Four

The separated borders model

If you want to keep the separate borders around your cells (in other words not specifying a value for border-collapse or setting border-collapse to separate), you have the option of utilising border spacing, which is exempt from the collapsing borders model. Setting border-spacing to 0, will remove the spacing around your cells.

CSS Code:


#borderSpacingTable, #borderSpacingTable td {
  border:1px solid #ff0000;
}

#borderSpacingTable {
  border-spacing:0;
}

(X)HTML Code:


<table id="borderSpacingTable">
  <tr>
    <td>One</td>
    <td>Two</td>
  </tr>
  <tr> 
    <td>Three</td>
    <td>Four</td> 
  </tr>
</table>

Result:

One Two
Three Four

Applying a border to table rows

If you wish to apply a border to your table rows, you must ensure that border-collapse is set to collapse, otherwise the border will not render.

CSS Code:


#borderRowTable {
  border-collapse:collapse;
}

#borderRowTable tr {
  border:1px solid #3366FF;
}

(X)HTML Code:


<table id="borderRowTable">
  <tr>
    <td>One</td>
    <td>Two</td>
  </tr>
  <tr> 
    <td>Three</td>
    <td>Four</td> 
  </tr>
</table>

Result:

One Two
Three Four

Adding padding to individual cells

Before people really cared about separating layout from presentation, they would add padding to their cells using the HTML attribute cellpadding. However, (X)HTML5 has rendered the cellpadding attribute obsolete, in favour of CSS (Visit the W3C's quick info page on tables in (X)HTML5). Why? Because it isn't considered good practice to use HTML to control how an element looks — that's what CSS is for. Thus, to add padding around a cell, we apply the CSS padding property to the tds of our table. Let's take a look.

CSS Code:


#cellPadding td {
  padding:6px;
}

#cellPadding .cellOne {
  background-color:red; 
}

#cellPadding .cellTwo {
  background-color:orange; 
}

#cellPadding .cellThree {
  background-color:yellow; 
}

#cellPadding .cellFour {
  background-color:green; 
}

#cellPadding .cellFive {
  background-color:blue; 
  color:#fff;
}

#cellPadding .cellSix {
  background-color:indigo;
  color:#fff; 
}

(X)HTML Code:


<table id="cellPadding">
  <tr>
    <td class="cellOne">Red</td>
    <td class="cellTwo">Orange</td>
    <td class="cellThree">Yellow</td>
    <td class="cellFour">Green</td>
    <td class="cellFive">Blue</td>
    <td class="cellSix">Indigo</td>    
  </tr>
</table>

Result:

Red Orange Yellow Green Blue Indigo

Note, on mobile devices, you may need to click on the example above and drag it across, in order to see the full table.

Removing the space between cells

We did touch on this above, when we discussed table borders, but we'll go over it again here. You may have noticed that table cells are individually spaced out, by default, with a small gap between each cell — a two pixel gap, to be precise. If you do not specify a property for border-collapse, it will default to separate, thus invoking the separated borders model. This will render individual borders around each cell and set the border spacing for each cell — controlled via the CSS border-spacing property — to 2px. Let's remind ourselves roughly what separate borders looks like.

#ccc #999
#666 #333

To remove that space, we can either set border-spacing to 0 or we can set border-collapse to collapse. The reason you can't do both is because setting border-collapse to collapse will select the collapsed border module, which will collapse the borders but does not enable border spacing to be used. Whichever method you go with, depends on what you are trying to achieve.

  • If you need each cell to have an individual border, use border-spacing
  • If you want one seamless border, use border-collapse

CSS Code:


#noCellSpace {
  border-collapse:collapse;
  font-size:2em;
}

#noCellSpace td {
  border:4px solid #231059;
}

#noCellSpace .cellOne {
  background-color:#ccc;
}

#noCellSpace .cellTwo {
  background-color:#999;
}

#noCellSpace .cellThree {
  background-color:#666;
}

#noCellSpace .cellFour {
  background-color:#333;
  color:#fff;
}

(X)HTML Code:


<table id="noCellSpace">
    <tr>
    	<td class="cellOne">#ccc</td>
    	<td class="cellTwo">#999</td>
    </tr>
    <tr>
    	<td class="cellThree">#666</td>
    	<td class="cellFour">#333</td> 
    </tr>
</table>

Result:

#ccc #999
#666 #333
As you can see, there is no space between the above cells.

Spacing out cells

If you wish to create more space between your cells, you may think that you can use the CSS margin property. While you're on the right track in that margins do indeed render around the outside of an element's box (as opposed to padding, which renders inside the box), the margin property has no effect on table cells.

To create space between table cells, you should use the CSS border-spacing property; this mimics the behaviour of the HTML cellspacing attribute, which is obsolete in (X)HTML5 (Visit the W3C page on tables in (X)HTML5) and the use of which is discouraged in XHTML 1.0. The reason for this is to separate the presentational aspect of a web page (CSS) from the markup side (HTML), resulting in more accessible code.

CSS Code:


#rowSpace {
  border-spacing:50px;
}

#rowSpace td { 
  background-color:#4fbf59;
}

(X)HTML Code:


<table id="rowSpace">
  <tr>
    <td>This is cell one</td>
    <td>This is cell two</td>
  </tr>
  <tr> 
    <td>This is cell three</td>
    <td>This is cell four</td> 
  </tr>
</table>

Result:

This is cell one This is cell two
This is cell three This is cell four

You can use the CSS border property and its longhand equivalents (border-width, border-style, border-color) to achieve the same effect, but these must be added to the td, unlike border-spacing, which must be applied to the table itself.

CSS Code:


#rowSpaceShorthand td { 
  background-color:#4fbf59;
  border:50px solid #fff;
}

(X)HTML Code:


<table id="rowSpaceShorthand">
  <tr>
    <td>This is cell one</td>
    <td>This is cell two</td>
  </tr>
  <tr> 
    <td>This is cell three</td>
    <td>This is cell four</td> 
  </tr>
</table>

Result:

This is cell one This is cell two
This is cell three This is cell four

CSS Code:


#rowSpaceBorderWidth td { 
  background-color:#4fbf59;
  border-width:50px;
  border-style:solid;
  border-color:#fff;
}

(X)HTML Code:


<table id="rowSpaceBorderWidth">
  <tr>
    <td>This is cell one</td>
    <td>This is cell two</td>
  </tr>
  <tr> 
    <td>This is cell three</td>
    <td>This is cell four</td> 
  </tr>
</table>

Result:

This is cell one This is cell two
This is cell three This is cell four

Centre aligning a table

In the olden days, we used the align property to align tables, or, even worse, the center element (shudder). But now, good old CSS handles all things formatting related. So, how do we align a table with CSS? Quite simple, we use the margin property and set it to 0 auto.

CSS Code:


#centreAligned {
  margin:0 auto;
  font-size:140%;
  border:4px solid #052523;
}

#centreAligned td {
  padding:8px 
}

(X)HTML Code:


<table id="centreAligned">
  <tr>
    <td>C</td>
    <td>D<td>
    <td>E</td>
    <td>F</td>
    <td>G</td>
    <td>A</td>
    <td>B</td>
  </tr>
</table>

Result:

C D E F G A B

Revision Notes

April 4th 2016

Made some minor text changes and added a white font colour to cells five and six in Adding padding to individual cells.

May 22nd 2013

I heavily revised this tutorial as it was in need of a revamp and added in info on the border models (separate and collapsing). I deliberately left this out, when I initially wrote the tutorial, because of the perceived complexity of the subject but then I thought 'What the hell? You guys are smart enough to understand!', so I included it.