Tabulate CSV Data

02 April 2020 MichaelCurrin MichaelCurrin

This tutorial shows how to use Jekyll to read a CSV and render the data as an HTML table.

This approach will:

  • use the CSV’s first row as the HTML table header.
  • use remaining rows for the body of the table.
  • preserve the order of the columns from the original CSV.
  • be flexible enough to work with any valid CSV that is referenced.

There is no need to specify what the names of the columns are, or how many columns there are. The trick to this tutorial is that, when we iterate over the row data, we pick up the first row and unpack that so we can get the header names.

Follow the steps below to convert a sample CSV of authors into an HTML table.

1. Create a CSV

Create a CSV file in your Data files directory so that Jekyll will pick it up. A sample path and CSV data are shown below:

_data/authors.csv

First name,Last name,Age,Location
John,Doe,35,United States
Jane,Doe,29,France
Jack,Hill,25,Australia

That data file will now be available in Jekyll like this:

{{ site.data.authors }}

2. Add a table

Choose an HTML or markdown file where you want your table to be shown.

For example: table_test.md

---
title: Table test
---

Inspect a row

Grab the first row and see what it looks like using the inspect filter.

{% assign row = site.data.authors[0] %}
{{ row | inspect }}

The result will be a hash (an object consisting of key-value pairs) which looks like this:

{
  "First name"=>"John",
  "Last name"=>"Doe",
  "Age"=>"35",
  "Location"=>"United States"
}

Note that Jekyll does in fact preserve the order here, based on the original CSV.

Unpack a row

A simple solution would be to hardcode the field names when looking up the row values by key.

{{ row["First name"] }}
{{ row["Last name"] }}

But we prefer a solution that will work for any CSV, without specifying the column names upfront. So we iterate over the row object using a for loop:

{% assign row = site.data.authors[0] %}
{% for pair in row %}
  {{ pair | inspect }}
{% endfor %}

This produces the following. Note the first item in each pair is the key and the second will be the value.

["First name", "John"]
["Last name", "Doe"]
["Age", "35"]
["Location", "United States"]

Create a table header row

Here we make a table with a single table row (tr), made up of table header (th) tags. We find the header name by getting the first element (at index 0) from pair. We ignore the second element as we don’t need the value yet.

<table>
  {% for row in site.data.authors %}
    {% if forloop.first %}
    <tr>
      {% for pair in row %}
        <th>{{ pair[0] }}</th>
      {% endfor %}
    </tr>
    {% endif %}
  {% endfor %}
</table>

For now, we do not display any content from the second row onwards. We achieve this by using forloop.first, since this will return true for the first row and false otherwise.

Add table data rows

In this section we add the data rows to the table. Now, we use the second element of pair to find the value.

For convenience, we render using the tablerow tag - this works like a for loop, but the inner data will be rendered with tr and td HTML tags for us. Unfortunately, there is no equivalent for the header row, so we must write that out in full, as in the previous section.

---
title: Table test
---

<table>
  {% for row in site.data.authors %}
    {% if forloop.first %}
    <tr>
      {% for pair in row %}
        <th>{{ pair[0] }}</th>
      {% endfor %}
    </tr>
    {% endif %}

    {% tablerow pair in row %}
      {{ pair[1] }}
    {% endtablerow %}
  {% endfor %}
</table>

With the code above, the complete table would look like this:

First name Last name Age Location
John Doe 35 United States
Jane Doe 29 France
Jack Hill 25 Australia

That’s it - you can now turn a CSV into an HTML table using Jekyll.

Next steps

  • Change the field names in the CSV.
  • Choose a different CSV.
  • Add CSS styling to your table.
  • Render the table using a JSON or YAML input file.
Next