• Skip to main content
  • Select language
  • Skip to search
MDN Web Docs
  • Technologies
    • HTML
    • CSS
    • JavaScript
    • Graphics
    • HTTP
    • APIs / DOM
    • WebExtensions
    • MathML
  • References & Guides
    • Learn web development
    • Tutorials
    • References
    • Developer Guides
    • Accessibility
    • Game development
    • ...more docs
Learn web development
  1. MDN
  2. Learn web development
  3. CSS
  4. Styling boxes
  5. Styling tables

Styling tables

In This Article
  1. A typical HTML table
  2. Active learning: Styling our table
    1. Spacing and layout
    2. Some simple typography
    3. Graphics and colors
      1. Zebra striping
    4. Styling the caption
  3. Active learning: Style your own table
  4. Table styling quick tips
  5. Summary
Previous Overview: Styling boxes Next

 

Styling an HTML table isn't the most glamourous job in the world, but sometimes we have to do it. This article provides a guide to making HTML tables look good, with some of the features detailed in the previous articles.

Prerequisites: HTML basics (study Introduction to HTML), HTML tables (see the HTML tables module(TBD)), and an idea of how CSS works (study Introduction to CSS.)
Objective: To learn how to effectively style HTML tables.

A typical HTML table

Let's start by looking at a typical HTML table. Well, I say typical — most HTML table examples are about shoes, or the weather, or employees; we decided to make things more interesting by making it about famous punk bands from the UK. The markup looks like so:

<table summary="The most famous UK punk bands">
  <caption>A summary of the UK's most famous punk bands</caption>
  <thead>
    <tr>
      <th scope="col">Band</th>
      <th scope="col">Year formed</th>
      <th scope="col">No. of Albums</th>
      <th scope="col">Most famous song</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Buzzcocks</th>
      <td>1976</td>
      <td>9</td>
      <td>Ever fallen in love (with someone you shouldn't've)</td>
    </tr>
    <tr>
      <th scope="row">The Clash</th>
      <td>1976</td>
      <td>6</td>
      <td>London Calling</td>
    </tr>
      ... some rows removed for brevity
    <tr>
      <th scope="row">The Stranglers</th>
      <td>1974</td>
      <td>17</td>
      <td>No More Heroes</td>
    </tr>
  </tbody>
  <tfoot>
    <tr>
      <th scope="row" colspan="2">Total albums</th>
      <td colspan="2">77</td>
    </tr>
  </tfoot>
</table>

The table is nicely marked up, easily styleable, and accessible, thanks to features such as scope, , summary, <thead>, <tbody>, etc. Unfortunately, it doesn't look good when rendered on the screen (see it live at punk-bands-unstyled.html):

It just looks cramped, hard to read, and boring. We need to use some CSS to fix this up.

Active learning: Styling our table

In this active learning section we are going to work through styling our table example together.

  1. To start with, make a local copy of the sample markup, download both images (noise and leopardskin), and put the three resulting files in a working directory somewhere on your local computer.
  2. Next, create a new file called style.css and save it in the same directory as your other files.
  3. Link the CSS to the HTML by placing the following line of HTML inside your <head>:
    <link href="style.css" rel="stylesheet" type="text/css">

Spacing and layout

The first thing we need to do is sort out the spacing/layout — default table styling is so cramped! To do this, add the following CSS to your style.css file:

/* spacing */
table {
  table-layout: fixed;
  width: 100%;
  border-collapse: collapse;
  border: 3px solid purple;
}
thead th:nth-child(1) {
  width: 30%;
}
thead th:nth-child(2) {
  width: 20%;
}
thead th:nth-child(3) {
  width: 15%;
}
thead th:nth-child(4) {
  width: 35%;
}
th, td {
  padding: 20px;
}

The most important parts to note are as follows:

  • A table-layout value of fixed is generally a good idea to set on your table, as it makes the table behave a bit more predictably by default. Normally, table columns tend to be sized according to how much content they contain, which produces some strange results. With table-layout: fixed, you can size your columns according to the width of their headings, and then deal with their content as appropriate. This is why we've selected the four different headings with the thead th:nth-child(n) (:nth-child) selector ("Select the nth child that is a <th> element in a sequence, inside a <thead> element") and given them set percentage widths. The entire column width follows the width of its heading, making for a nice way to size your table columns. Chris Coyier discusses this technique in more detail in Fixed Table Layouts.

    We've coupled this with a width of 100%, meaning that the table will fill any container it is put in, and be nicely responsive (although it would still need some more work to get it looking good on narrow screen widths).
  • A border-collapse value of collapse is a standard best practice for any table style effort. By default, when you set borders on table elements, they will all have spacing between them, as the below image illustrates: This doesn't look very nice (although it might be the look you want, who knows?) With border-collapse: collapse; set, the borders collapse down into one, which looks much better:
  • We've put a border around the whole table, which is needed because we'll be putting some borders round the table header and footer later on — it looks really odd and disjointed when you don't have a border round the whole outside of the table and end up with gaps.
  • We've set some padding on the <th> and <td> elements — this gives the data items some space to breathe, making the table look a lot more legible.

At this point, our table already looks a lot better:

Some simple typography

Now we'll get our type sorted out a bit.

First of all, we've gone and found a font on Google Fonts that is suitable for a table about punk bands. You can go there and find a different one if you like; you'll just have to replace our provided <link> element and custom font-family declaration with the ones Google Fonts gives you.

First, add the following <link> element into your HTML head, just above your existing <link> element:

<link href='https://fonts.googleapis.com/css?family=Rock+Salt' rel='stylesheet' type='text/css'>

Now add the following CSS into your style.css file, below the previous addition:

/* typography */
html {
  font-family: 'helvetica neue', helvetica, arial, sans-serif;
}
thead th, tfoot th {
  font-family: 'Rock Salt', cursive;
}
th {
  letter-spacing: 2px;
}
td {
  letter-spacing: 1px;
}
tbody td {
  text-align: center;
}
tfoot th {
  text-align: right;
}

There is nothing really specific to tables here; we are generally tweaking the font styling to make things easier to read:

  • We have set a global sans-serif font stack; this is purely a stylistic choice. We've also set our custom font on the headings inside the <thead> and <tfoot> elements, for a nice grungy, punky look.
  • We've set some letter-spacing on the headings and cells, as we feel it aids readability. Again, mostly a stylistic choice.
  • We've center-aligned the text in the table cells inside the <tbody> so that they line up with the headings. By default, cells are given a text-align value of left, and headings are given a value of center, but generally it looks better to have the alignments set the same for both. The default bold weight on the heading fonts is enough to differentiate their look.
  • We've right-aligned the heading inside the <tfoot> so that it is visually associated better with its data point.

The result looks a bit neater:

Graphics and colors

Now onto graphics and colors! Because the table is full of punk and attitude, we need to give it some bright imposing styling to suit. Don't worry, you don't have to make your tables this loud — you can opt for something more subtle and tasteful.

Start by adding the following CSS to your style.css file, again at the bottom:

thead, tfoot {
  background: url(leopardskin.jpg);
  color: white;
  text-shadow: 1px 1px 1px black;
}
thead th, tfoot th, tfoot td {
  background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.5));
  border: 3px solid purple;
}

Again, there's nothing specific to tables here, but it is worthwhile to note a few things.

We've added a background-image to the <thead> and <tfoot>, and changed the color of all the text inside the header and footer to white (and given it a text-shadow) so it is readable. You should always make sure your text contrasts well with your background, so it is readable.

We've also added a linear gradient to the <th> and <td> elements inside the header and footer for a nice bit of texture, as well as giving those elements a bright purple border. It is useful to have multiple nested elements available so you can layer styles on top of one another. Yes, we could have put both the background image and the linear gradient on the <thead> and <tfoot> elements using multiple background images, but we decided to do it separately for the benefit of older browsers that don't support multiple background images or linear gradients.

Zebra striping

We wanted to dedicate a separate section to showing you how to implement zebra stripes — alternating rows of color that make the different data rows in your table easier to parse and read. Add the following CSS to the bottom of your style.css file:

tbody tr:nth-child(odd) {
  background-color: #ff33cc;
}
tbody tr:nth-child(even) {
  background-color: #e495e4;
}
tbody tr {
  background-image: url(noise.png);
}
table {
  background-color: #ff33cc;
}
  • Earlier on you saw the :nth-child selector being used to select specific child elements. It can also be given a formula as a parameter, so it will select a sequence of elements. The formula 2n-1 would select all the odd numbered children (1, 3, 5, etc.) and the formula 2n would select all the even numbered children (2, 4, 6, etc.) We've used the odd and even keywords in our code, which do exactly the same things as the aforementioned formulae. In this case we are giving the odd and even rows different (lurid) colors.
  • We've also added a repeating background tile to all the body rows, which is just a bit of noise (a semi-transparent .png with a bit of visual distortion on it) to provide some texture.
  • Lastly, we've given the entire table a solid background color so that browsers that don't support the :nth-child selector still have a background for their body rows.

This color explosion results in the following look:

Now, this may be a bit over the top and not to your taste, but the point we are trying to make here is that tables don't have to be boring and academic.

Styling the caption

There is one last thing to do with our table — style the caption. To do this, add the following to the bottom of your style.css file:

caption {
  font-family: 'Rock Salt', cursive;
  padding: 20px;
  font-style: italic;
  caption-side: bottom;
  color: #666;
  text-align: right;
  letter-spacing: 1px;
}

There is nothing remarkable here, except for the caption-side property, which has been given a value of bottom. This causes the caption to be positioned on the bottom of the table, which along with the other declarations gives us this final look (see it live at punk-bands-complete.html):

Active learning: Style your own table

At this point, we'd like you to take our example table HTML (or use some of your own!) and style it to make something considerably better designed and less garish than our table.

Table styling quick tips

Before moving on, we thought we'd provide you with a quick list of the most useful points illustrated above:

  • Make your table markup as simple as possible, and keep things flexible, e.g. by using percentages, so the design is more responsive.
  • Use table-layout: fixed to create a more predictable table layout that allows you to easily set column widths by setting width on their headings (<th>).
  • Use border-collapse: collapse to make table elements borders collapse into each other, producing a neater and easier to control look.
  • Use <thead>, <tbody>, and <tfoot> to break up your table into logical chunks and provide extra places to apply CSS to, so it is easier to layer styles on top of one another if required.
  • Use zebra striping to make alternative rows easier to read.
  • Use text-align to line up your <th> and <td> text, to make things neater and easier to follow.

Summary

With the dizzy exciting heights of styling tables now behind us, we need something else to occupy our time. Never fear — the next chapter provides a look at some advanced box effects, some of which have only landed in browsers very recently (such as blend modes and filters), and some of which are a bit more established (such as box shadows.)

Previous Overview: Styling boxes Next

 

Document Tags and Contributors

Tags: 
  • Article
  • Beginner
  • CodingScripting
  • CSS
  • Guide
  • Styling
  • Tables
 Contributors to this page: flash4syth, C0DEHERO, chrisdavidmills, richardzacur
 Last updated by: flash4syth, May 17, 2017, 8:43:49 AM
See also
  1. Complete beginners start here!
  2. Getting started with the Web
    1. Getting started with the Web overview
    2. Installing basic software
    3. What will your website look like?
    4. Dealing with files
    5. HTML basics
    6. CSS basics
    7. JavaScript basics
    8. Publishing your website
    9. How the Web works
  3. HTML — Structuring the Web
  4. Introduction to HTML
    1. Introduction to HTML overview
    2. Getting started with HTML
    3. What's in the head? Metadata in HTML
    4. HTML text fundamentals
    5. Creating hyperlinks
    6. Advanced text formatting
    7. Document and website structure
    8. Debugging HTML
    9. Assessment: Marking up a letter
    10. Assessment: Structuring a page of content
  5. Multimedia and embedding
    1. Multimedia and embedding overview
    2. Images in HTML
    3. Video and audio content
    4. From object to iframe — other embedding technologies
    5. Adding vector graphics to the Web
    6. Responsive images
    7. Assessment: Mozilla splash page
  6. HTML tables
    1. HTML tables overview
    2. HTML table basics
    3. HTML Table advanced features and accessibility
    4. Assessment: Structuring planet data
  7. CSS — Styling the Web
  8. Introduction to CSS
    1. Introduction to CSS overview
    2. How CSS works
    3. CSS syntax
    4. Selectors introduction
    5. Simple selectors
    6. Attribute selectors
    7. Pseudo-classes and pseudo-elements
    8. Combinators and multiple selectors
    9. CSS values and units
    10. Cascade and inheritance
    11. The box model
    12. Debugging CSS
    13. Assessment: Fundamental CSS comprehension
  9. Styling text
    1. Styling text overview
    2. Fundamental text and font styling
    3. Styling lists
    4. Styling links
    5. Web fonts
    6. Assessment: Typesetting a community school homepage
  10. Styling boxes
    1. Styling boxes overview
    2. Box model recap
    3. Backgrounds
    4. Borders
    5. Styling tables
    6. Advanced box effects
    7. Assessment: Creating fancy letterheaded paper
    8. Assessment: A cool-looking box
  11. CSS layout
    1. CSS layout overview
    2. Introduction
    3. Floats
    4. Positioning
    5. Practical positioning examples
    6. Flexbox
    7. Grids
  12. JavaScript — Dynamic client-side scripting
  13. JavaScript first steps
    1. JavaScript first steps overview
    2. What is JavaScript?
    3. A first splash into JavaScript
    4. What went wrong? Troubleshooting JavaScript
    5. Storing the information you need — Variables
    6. Basic in JavaScript — Numbers and operators
    7. Handling text — Strings in JavaScript
    8. Useful string methods
    9. Arrays
    10. Assessment: Silly story generator
  14. JavaScript building blocks
    1. JavaScript building blocks overview
    2. Making decisions in your code — Conditionals
    3. Looping code
    4. Functions — Reusable blocks of code
    5. Build your own function
    6. Function return values
    7. Introduction to events
    8. Assessment: Image gallery
  15. Introducing JavaScript objects
    1. Introducing JavaScript objects overview
    2. Object basics
    3. Object-oriented JavaScript for beginners
    4. Object prototypes
    5. Inheritance in JavaScript
    6. Working with JSON data
    7. Object building practise
    8. Assessment: Adding features to our bouncing balls demo
  16. Accessibility — Make the web usable by everyone
  17. Accessibility guides
    1. Accessibility overview
    2. What is accessibility?
    3. HTML: A good basis for accessibility
    4. CSS and JavaScript accessibility best practices
    5. WAI-ARIA basics
    6. Accessible multimedia
    7. Mobile accessibility
  18. Accessibility assessment
    1. Assessment: Accessibility troubleshooting
  19. Tools and testing
  20. Cross browser testing
    1. Cross browser testing overview
    2. Introduction to cross browser testing
    3. Strategies for carrying out testing
    4. Handling common HTML and CSS problems
    5. Handling common JavaScript problems
    6. Handling common accessibility problems
    7. Implementing feature detection
    8. Introduction to automated testing
    9. Setting up your own test automation environment
  21. Server-side website programming
  22. First steps
    1. First steps overview
    2. Introduction to the server-side
    3. Client-Server overview
    4. Server-side web frameworks
    5. Website security
  23. Django web framework (Python)
    1. Django web framework (Python) overview
    2. Introduction
    3. Setting up a development environment
    4. Tutorial: The Local Library website
    5. Tutorial Part 2: Creating a skeleton website
    6. Tutorial Part 3: Using models
    7. Tutorial Part 4: Django admin site
    8. Tutorial Part 5: Creating our home page
    9. Tutorial Part 6: Generic list and detail views
    10. Tutorial Part 7: Sessions framework
    11. Tutorial Part 8: User authentication and permissions
    12. Tutorial Part 9: Working with forms
    13. Tutorial Part 10: Testing a Django web application
    14. Tutorial Part 11: Deploying Django to production
    15. Web application security
    16. Assessment: DIY mini blog
  24. Express Web Framework (node.js/JavaScript)
    1. Express Web Framework (Node.js/JavaScript) overview
    2. Express/Node introduction
    3. Setting up a Node (Express) development environment
    4. Express tutorial: The Local Library website
    5. Express Tutorial Part 2: Creating a skeleton website
    6. Express Tutorial Part 3: Using a database (with Mongoose)
    7. Express Tutorial Part 4: Routes and controllers
    8. Express Tutorial Part 5: Displaying library data
    9. Express Tutorial Part 6: Working with forms
    10. Express Tutorial Part 7: Deploying to production
  25. Further resources
  26. Advanced learning material
    1. WebGL: Graphics processing
  27. Common questions
    1. HTML questions
    2. CSS questions
    3. JavaScript questions
    4. How the Web works
    5. Tools and setup
    6. Design and accessibility
  28. How to contribute