Creating HTML tables

HTML table basics

In order to create an HTML table within the silverfin code editor, we start with the opening and closing tag for the table <table> </table>.

Shortcuts in the editor:

  • writing <table> automatically adds the closing tag
  • writing <table and pressing tab automatically gives you a basic HTML table structure (as seen below)
<table class="">
  <thead>
    <tr>
      <th class="">content</th>
      <th class="">content</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="">content</td>
      <td class="">content</td>
    </tr>
  </tbody>
</table>

Elements in an HTML table

Table headings
When using table headings we have to section off the table’s headings and the table’s body by using the <thead> tag (used to section off the column headings where we will name our rows/columns) and the <tbody> tag (used to section off the body of the table where we will add our content/data).

Both of these elements require an opening and closing tag:

  • <thead></thead>
  • <tbody></tbody>

To add titles to table rows and columns, we use the table heading element: , ensuring that we use an opening and closing tag: <th></th>.

Shortcuts in the editor:

  • writing <th> automatically adds the closing tag
  • writing <th and pressing tab automatically gives us a table head class and elements (as seen below)
<th class="">content</th>

N.B. The table heading element is used like a table data element, except with a relevant title. Just like table data, a table heading must be placed within a table row.


Table rows
The first step in entering data into the table is to add rows using the table row element opening and closing tags: <tr> </tr>

Shortcuts in the editor:

  • writing <tr> automatically adds the closing tag
  • writing <tr and pressing tab automatically gives us a row and some basic elements that would go inside a row (as seen below)
<tr>
  <td class="">content</td>
  <td class="">content</td>
</tr>

Table data
After adding our table rows we can now add data to the table by defining each cell in the row with the HTML table data opening and closing tags: <td> </td>

Shortcuts in the editor:

  • writing <td> automatically adds the closing tag
  • writing <td and pressing tab automatically gives us a table data class and elements (as seen below)
<td class="">content</td>

Basic table example

We now know everything we need to create a basic table.

<table>
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>4</td>
    </tr>
  </tbody>
</table>

Output:

204204

Creating more complex tables

Table widths
There are 3 possible setups when defining the widths on an HTML table:

  1. Width is defined for all columns
  2. Width is defined for all columns except one (that column will dynamically take the remaining available width)
  3. Width is not defined for any column (the column width will change dynamically depending on content)

Any other scenarios are not supported and will not work properly.

Understanding width percentages

One common misunderstanding regarding widths in the header is that the totals always need to match the width specified on the table, however, they always need to add up to 100%.

This is incorrect :
In the code snippet below we are setting the table width to span 50% of the total width of the page. However, each header is set to 25% of our specified width which means we are missing 50%. This will result in an error being thrown as seen in the output below.

<table class="usr-width-50">
  <thead>
    <tr>
      <th class="usr-width-25">Header 1</th>
      <th class="usr-width-25">Header 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="">content 1</td>
      <td class="">content 2</td>
    </tr>
  </tbody>
</table>

Output:

📘

HTML Table Error: Syntax Error 'Width classes should sum up to a 100 for a <tr>. Current sum is 50'. content 1 content 2

This is correct:

In the code snippet below we are setting the table width to span 50% of the total width of the page. We are then setting our header column to span 50% of 50% (i.e. 25% of the total page width per heading).

<table class="usr-width-50">
  <thead>
    <tr>
      <th class="usr-width-50">Header 1</th>
      <th class="usr-width-50">Header 2</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="">content 1</td>
      <td class="">content 2</td>
    </tr>
  </tbody>
</table>

Output:

688688

Table styling
As mentioned, the Silverfin platform allows us to access HTML classes starting with usr- to add styling to certain HTML elements.

Some examples of how we can add styling to our table:

  • By using the class usr-width-100 we make sure the table is aligned over the entire width of the page;
  • We can use usr-bordered to set borders for the whole table and add style to the header. This is equivalent to using # in markdown tables;
  • To set the alignment and width of cells we should use the usr-width- and usr-align- classes;
  • There are different types of borders that can be added to the table. For instance, if we want to add a double top line, we can use usr-double-line-top;
  • If we want to make the column headers bold, we can use the <b> HTML tag. You can also use <i> and <u> tags for italic and underline (or indeed a combination of these)
  • To add indentation to cells we can access the usr-indent- class. You can use 1 to 10 which are different levels of indentation.
<table class="usr-width-100 usr-bordered">
  <thead>
    <tr>
      <th class="usr-align-right usr-width-45"><b>Header 1</b></th>
      <th class="usr-align-center usr-double-line-top usr-width-55"><b>Header 2</b></th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="usr-indent-1">1</td>
      <td class="usr-indent-2">2</td>
    </tr>
    <tr>
      <td>3</td>
      <td>4</td>
    </tr>
  </tbody>
</table>

Output:

13451345

Example of HTML table using classes, styling & Liquid template language
Now let’s take a look at an example that combines everything we have learned so far but add in some liquid template language and logic.

{% assign range_profitloss = period.accounts | range:"100" %}

<table class="usr-width-100">
  <thead class="usr-repeated-header">
    <tr>
      <th class="usr-align-right usr-width-45">
      Right align with  <b>Bold</b> <em>Italic</em> <u>underline</u> 
      </th>
      <th class="usr-align-center usr-double-line-top usr-width-55">
      Centered double top
      </th>
    </tr>
  </thead>
  <tbody>
  {% for acc in range_profitloss %}
    {% if acc.name contains "Computer software"%}
      <tr>
        <td> {{ acc.number }}{{ acc.name }} </td>
        <td class="usr-align-right"> {{ acc.value }} </td>
      </tr>
    {% endif %}
  {% endfor %}
    <tr>
      <td class="usr-indent-1">
      {% input period.custom.table.width as:integer default:100 %}
      </td>
      <td>
      {::infotext} Info text {:/infotext}
      </td>
    </tr>
  </tbody>
</table>

Output:

13451345

Colspan

colspan is an attribute that allows us to specify the number of columns that the cell fills in both <td> and <th> tags. It provides the same functionality as “merge cell” in a spreadsheet program like Excel.

You should apply the attribute in the cell that you want to “merge/span”, defining the number of columns you want it to take. The syntax is as follows:

<th class="usr-line-bottom" colspan="2">cell content</th>

📘

"usr-width" & colspan

Bear in mind that the usr-width class cannot be used in rows with colspan. The width needs to be defined in any of the other <tr> as seen on the table underneath.

This can be useful when we want, for example, to group a few columns under the same category like in the example below:

{% capture all_borders_class %}usr-line-bottom usr-line-top usr-line-left usr-line-right{% endcapture %}

<table class="usr-width-100">
  <thead>
    <tr>
      <th class= "{{ all_borders_class }} usr-align-center" colspan="2">**Income**</th>
      <th class= "{{ all_borders_class }} usr-align-center" colspan="2">**Expenses**</th>
    </tr>
    <tr>
      <th class="usr-width-25 {{ all_borders_class }}">**Current year**</th>
      <th class="usr-width-25 {{ all_borders_class }}">**Previous year**</th>
      <th class="usr-width-25 {{ all_borders_class }}">**Current year**</th>
      <th class="usr-width-25 {{ all_borders_class }}">**Previous year**</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td class="{{ all_borders_class }}">£ 2,000</td>
      <td class="{{ all_borders_class }}">£ 3,000</td>
      <td class="{{ all_borders_class }}">£ 4,000</td>
      <td class="{{ all_borders_class }}">£ 5,000</td>
    </tr>
  </tbody>
</table>

Output:

13281328

Empty rows
colspan can also be useful when our table has empty rows and we don’t want to repeat the <td> tags many times.
If we don’t use colspan we would need to do this which is inefficient.

<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>

colspan allows us to create one <td> and set the total number of columns in the table as the colspan value which is much more efficient.

<table class="usr-bordered">
  <thead>
    <tr>
      <th>Header 1</th>
      <th>Header 2</th>
      <th>Header 3</th>
      <th>Header 4</th>
      <th>Header 5</th>
      <th>Header 6</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Row 1</td>
      <td>Row 1</td>
      <td>Row 1</td>
      <td>Row 1</td>
      <td>Row 1</td>
      <td>Row 1</td>
    </tr>
    <tr>
      <td colspan="6"></td>
    </tr>
  </tbody>
</table>

Output:

800800

Troubleshooting

CASE: Converting table in markdown to a table in HTML
CASE: Navigation header in HTML
CASE: Shared table definitions in HTML
CASE: Repeating headers in HTML tables
CASE: how to use grouping for HTML tables



Underlining:

  • For headers, it should be set via the class usr-line-bottom
  • Underlining of a word inside a cell can be done via the <u> element.

Alignment:

  • You can set the alignment for a whole column by specifying it within the first row.
  • Default alignment is left. As we can’t access the CSS properties of <td> or <the> elements, we have to specifically add the usr-align class for cells where we want to diverge from the default alignment.

Font:

  • When we want to modify the size of the text in HTML tables, we should use the markdown {::font} notation instead of HTML <font> as this is no longer supported in HTML 5 for size.

📘

{::font size="l"} Header {:/font}


Empty rows:

  • On every row we have, we need to define every column.
  • This also applies to rows that are completely empty.
  • It is not enough to define the entire structure of the row, with all the <td> elements. If there is no content in any of the columns of our row, the entire table is going to be ignored in export. For that reason, when we want to have an empty row we need to add at least one &nbsp; inside one of the <td> elements (this can't be used for 1% columns).

This markdown example:

|---|---{% if show_prev_year %}|---|---{% endif %}|---|---: 
| &nbsp;

Translates to the HTML structure:

<table>
  <thead>
    <tr>
      <th>&nbps;</th>
      <th></th>
      {% if show_prev_year %}
      <th></th>
      <th></th>
      {% endif %}
      <th></th>
      <th></th>
    </tr>
  </thead>
</table>

Rather than doing the above, we recommend using Colspan

  • White space/ line breaks will appear on your table when adding breaks within the <td> or <th> tags:
<table class="usr-width-100 usr-bordered">
  <thead>
  <tr>
    <th>
      **Header**
    </th>
  </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        Row 1
      </td>
    </tr>
  </tbody>
</table>

Input view:

226226

In order to solve the above issue, you can wrap the whole table within stripnewlines:

{% stripnewlines %}

<table class="usr-width-100 usr-bordered">
  <thead>
  <tr>
    <th>
      **Header**
    </th>
  </tr>
  </thead>
  <tbody>
    <tr>
      <td>
        Row 1
      </td>
    </tr>
  </tbody>
</table>

{% endstripnewlines %}

Updating markdown tables:
in the case you are updating your current markdown tables into HTML, you can think about these elements between both as equivalent.

📘

|<td>
newline<tr>


Capture & CSS classes

  • To avoid repeating many classes every time and make our code more readable we could use something like this. You can see that we can combine liquid syntax inside the HTML tags as well.
{% capture total_row_css %}usr-align-right usr-line-bottom usr-line-top usr-valign-bottom{% endcapture %}

<td class="{{ total_row_css }}"> ... /td>
<td class="{{ total_row_css }}"> ... /td>
<td class="usr-align-right usr-line-bottom usr-line-top usr-valign-bottom"> ... /td>
<td class="usr-align-right usr-line-bottom usr-line-top usr-valign-bottom"> ... /td>

Avoid empty rows in input view by leaving the body of the table without children elements:

  • Sometimes you need to create a separate table for template header e.g., that table needs a <thead> and a <tbody>. This <tbody> part will create additional white space. To avoid this, you can just add a <tbody> opening and closing tag without <tr>, This will avoid white-space.

Total width per <tr> should always add up to 100:

  • Please refer to the Table width section in the documentation if you encounter the following error.
  • HTML Table Error: Syntax Error 'Width classes should sum up to a 100 for a <tr>.

Tables can have a <tbody> without a <thead> but not a <thead> without a <tbody>:

  • HTML Table Error: Not a simple table. All children must be <td> OR there is a <thead> with <th> children only and a <tbody> with <td> children only.

{:/group} tags:

  • Multiple HTML tables can be grouped using the group tag in the same way as markdown tables.
  • However, at this point in time, there is no way to use the group tag for the table rows of a single HTML table. using the usr-repeated-header is a good alternative.

<p>, <h1>, <h2> tags

  • Whilst the above tags are supported within Silverfin they cannot be used within Silverfin HTML tables. If used you will encounter the following error.
  • HTML Table Error: Not a simple table. All children must be <td> OR there is a <thead> with <th> children only and a <tbody> with <td> children only.