skip to content

In an HTML <table>, what does the <caption> element do, and where in the markup must it appear?

level: juniorimportance: should knowfreq 55%

answer

  1. a title that belongs to the table
  2. not a paragraph sitting above it
  3. position inside <table> is fixed
  4. first child, before colgroup and rows
  5. supplies the table's accessible name

basics

~20 s
<caption> gives an HTML table a visible title that also becomes the table's accessible name, so a screen-reader user knows what the table holds before entering it. It must be the first child of <table>, before any colgroup or row.

solid answer

~40 s

`<caption>` is the table's own title element. It must be the **first child** of `<table>` — before `<colgroup>`, `<thead>`, or any rows — and it renders above the table by default. Its real value is that it is programmatically tied to the table: assistive technology uses it as the table's accessible name, so when a screen-reader user lands on the table or lists the tables on a page, they hear "Quarterly revenue, 2025" rather than "table, 5 columns, 40 rows". A `<p>` or `<h2>` sitting above the table looks the same on screen but carries no such association — visually adjacent is not the same as programmatically associated. A caption may hold flow content, but keep it short, because it is announced as the table's name.

code

html · 19 lines
html
<table>
  <caption>Support tickets closed per week</caption>
  <thead>
    <tr>
      <th scope="col">Week</th>
      <th scope="col">Closed</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <th scope="row">Week 1</th>
      <td>42</td>
    </tr>
    <tr>
      <th scope="row">Week 2</th>
      <td>51</td>
    </tr>
  </tbody>
</table>

go deeper

for a junior

Know that <caption> titles a table and must be the first child of <table>. Say plainly that a heading sitting above the table is not connected to it in any machine-readable way.

for a middle

Be ready to explain that the caption supplies the table's accessible name, that screen-reader users browse a list of tables by that name, and that hiding it visually is preferable to deleting it.

for a senior

Show judgment about what a caption should say — scope, period, units — and about when to keep the caption versus label the table from an existing heading. Expect to justify the choice in a design review.

for a principal

Own the convention: decide whether every data table in the design system ships a caption slot by default, how visually hidden captions are provided, and how that rule is enforced in review or lint so titles never drift away from their tables.

## What the element is `<caption>` is a dedicated child element of `<table>` that names or briefly describes the table. It is the only element in HTML whose job is to title a table, and it exists precisely because a title written as a nearby paragraph or heading has no machine-readable link to the table it belongs to. ## Where it goes The content model of `<table>` fixes the order of its children: an optional `<caption>` first, then zero or more `<colgroup>` elements, then an optional `<thead>`, then the body rows (in `<tbody>` elements or bare `<tr>`s), then an optional `<tfoot>`. So the caption is always the very first thing inside `<table>`: ```html <table> <caption>Quarterly revenue, 2025 (millions USD)</caption> <colgroup> <col> <col span="4"> </colgroup> <thead> <tr> <th scope="col">Region</th> <th scope="col">Q1</th> <th scope="col">Q2</th> <th scope="col">Q3</th> <th scope="col">Q4</th> </tr> </thead> <tbody> <tr> <th scope="row">EMEA</th> <td>12.4</td><td>13.1</td><td>11.8</td><td>15.0</td> </tr> </tbody> </table> ``` Put the caption anywhere else and you are relying on the parser's error recovery rather than writing valid markup; browsers will still render something, but you have lost the guarantee. ## What it actually buys you Three things, and only the first is visual. **A rendered title.** By default browsers draw the caption above the table box, horizontally centred, as part of the table itself — so it moves and prints with the table instead of floating free. **An accessible name.** Accessible-name computation takes a table's name from its `<caption>` when one is present. That name is what a screen reader speaks when focus reaches the table, and it is what appears in the AT's list of tables on the page. Screen-reader users routinely pull up such a list to jump between tables; a page of unnamed tables reads as "table, table, table". **A stable anchor for the whole structure.** Because the caption is inside `<table>`, nothing about page reflow, column ordering, or component reuse can separate the title from its data. A heading placed above can be moved, wrapped, or rendered in a different DOM position by a layout change. ## Caption versus a heading above the table This is the point interviewers are usually probing. A sighted user sees no difference between an `<h3>` above the table and a `<caption>` inside it. A screen-reader user does: only the caption is announced as the table's name. If a design genuinely requires the heading treatment, you have two honest options — keep the `<caption>` and style it to match the heading, or point the table at the existing heading using an ARIA labelling attribute. What you must not do is assume proximity implies association. If the caption would be visually redundant, the answer is still to write it and hide it visually with a clipping utility class, not to delete it. Removing it removes the name for everyone who cannot see the layout. ## Writing a good caption Name what the table contains, plus the units or the period if they are not in the headers: "Quarterly revenue, 2025 (millions USD)" beats "Revenue". Keep it to a phrase — it is announced in one breath as the table's name, so a paragraph of explanation belongs after the table, not in the caption. Do not repeat the column headers in the caption; they are announced separately per cell. A caption's content model is flow content, so links or emphasis inside are legal, but restraint pays: interactive content inside a table's name is confusing to navigate. ## Common mistakes Placing the caption after `<thead>`; using `<caption>` on a layout table (a layout table should carry no caption at all, because a caption asserts that there is real tabular data here); and reaching for the obsolete `summary` attribute on `<table>`, which was removed from HTML — a long description belongs in prose near the table, associated with it if needed, not in a hidden attribute.

  • The design already shows an <h2> immediately above the table. Do you still need a <caption>?
    The table still needs a programmatic name. Cleanest is a `<caption>` styled to look like the heading, or visually hidden if the heading must stay. Failing that, point the table at the heading with `aria-labelledby` referencing the heading's id. A heading that merely sits above the table gives assistive technology nothing.
  • Can a <caption> contain anything other than plain text?
    Yes — its content model is flow content, so emphasis, links, or even a heading element are legal inside it. In practice keep it to a short phrase: the caption is announced in one breath as the table's name, and interactive content buried in a table's name is awkward to reach and to understand.

saying these in an interview costs you the question

  • Thinks <caption> is only for images or figures
  • Places <caption> after <thead> or at the end of the table
  • Assumes a paragraph above the table labels it
  • Says a caption is only needed when printing
  • Uses the obsolete summary attribute to describe the table

context