Documentation menu

Standings table block

A ranked season table for a sports team or club: team name, played/won/drawn/lost, points for/against, and points, sorted by points descending with the top three rows marked. Unlike every block on the analytics & chart blocks page, this one never renders as an image — a real HTML <table> is the entire block, in every email client including Outlook.

How it works

Every one of the thirteen chart blocks in the analytics family renders a server-generated raster image with a text fallback alongside it, because a bar chart or a line graph genuinely has no equivalent HTML markup that displays consistently across clients. A ranked table doesn't have that problem: sorted rows and columns are exactly what <table> markup already renders natively and consistently everywhere, Outlook's Word-based engine included, so there's no image-plus-fallback split here — one render path, used unconditionally.

Rows are typed in directly in the inspector's row editor, one team per row — there's no live data-source binding yet, so you update the block by hand after each match, the same manual-update model a KPI scorecard's authored value uses before it's bound to a data source. Sorting happens at render time: rows are sorted by the Points column descending, and ties keep their originally authored order rather than being reshuffled, since Array.prototype.sort is a stable sort. The top three rows after sorting get a rank badge (🥇🥈🥉) instead of a plain number; every row below third gets a plain rank number.

Points is always a number you fill in yourself — it is never computed from wins/draws/losses, because leagues award points differently (a straight 3-point win, bonus points for a high-scoring loss, and so on) and hard-coding one formula would be wrong for most sports. Turn off Show draws column for a sport that has none (basketball, most tennis leagues) — doing so removes the "D" column from both the header and every row, rather than just hiding it visually. Highlight team matches a row's Team value case-insensitively and, when it matches, bolds the row's text and tints its background — useful for a parent digest so a family can spot their kid's team at a glance without scanning the whole table.

If no rows have a non-empty team name, the block still renders its title and card chrome, with a plain "Add at least one team to render the standings table" notice instead of an empty table — the same "don't throw mid-keystroke while building" convention every other analytics block's empty-data branch follows.

Standings table is pure content: there's nothing to answer, so — like Venue — it never appears in the responses dashboard, CSV export, or click heatmap. Nothing on it is a link.

Configurable fields:

  • Title — shown above the table; omit it and only the table renders.
  • Teams — the row list: Team, Played, Won, Drawn, Lost, Points for, Points against, Points.
  • Show draws column — toggles the "D" column on/off.
  • Highlight team (exact name match) — case-insensitive match against the Team column.
  • Background color, padding, border and border radius on the card.
  • Title color/size, and table text color/size.

Examples

Subject

Season standings after Week 10

The "Sports team" project purpose starts a new project with a Standings table already in place alongside Venue, Add to calendar, and RSVP — send a weekly digest that updates the same block with the latest results; see Sports teams & clubs for the full pattern, including how to keep one shared contact list across multiple squads or age-groups. A league newsletter recaps a full division's results in one email, with Highlight team left blank since there's no single "home" team to call out. A youth club sends the same standings email to every parent, with Highlight team set per-squad through a visibleWhen audience filter rather than sending a separate email per team.

What the static fallback looks like

<div style="margin:12px 0;background-color:#ffffff;padding:16px;border-radius:8px">
  <p style="margin:0 0 8px;font-weight:600;font-size:15px;color:#111827">Standings</p>
  <table style="width:100%;border-collapse:collapse;margin-top:4px">
    <tr>
      <th style="text-align:left;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:600">#</th>
      <th style="text-align:left;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:600">Team</th>
      <th style="text-align:right;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:600">Pts</th>
    </tr>
    <tr style="background-color:#eef2ff">
      <td style="padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:700">🥇 1</td>
      <td style="padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:700">Eagles</td>
      <td style="text-align:right;padding:4px 8px;border-bottom:1px solid #e5e7eb;font-weight:700">23</td>
    </tr>
  </table>
</div>

This is the block's real, only render — there's no separate fallback tier, since a table's the same markup in every client. (Played/Won/Drawn/Lost/PF/PA columns are omitted here for brevity; the row with the medal shows the highlighted-team tint applied to the same row.)