Tables

Create professional tables with a simple and flexible syntax.

Simple Table

#table(
  columns: 3,
  [*Name*], [*Age*], [*City*],
  [Alice], [25], [Paris],
  [Bob], [30], [Lyon],
  [Charlie], [35], [Marseille],
)

Table with Figure and Caption

#figure(
  table(
    columns: 3,
    [*Method*], [*Precision*], [*Recall*],
    [Baseline], [0.72], [0.68],
    [Model A], [0.85], [0.82],
    [NovaType], [0.94], [0.91],
  ),
  caption: [Performance comparison],
) <tab:results>

The results from @tab:results show...

Column Width

// Automatic width
#table(columns: 3, ...)

// Fixed width
#table(columns: (5cm, 3cm, 4cm), ...)

// Proportional width
#table(columns: (1fr, 2fr, 1fr), ...)

// Mixed
#table(columns: (auto, 1fr, 2cm), ...)

Alignment

#table(
  columns: 3,
  align: (left, center, right),
  [Left], [Center], [Right],
  [text], [text], [text],
)

Borders and Spacing

// Custom border
#table(
  columns: 3,
  stroke: 0.5pt + gray,
  [A], [B], [C],
  [1], [2], [3],
)

// No border
#table(
  columns: 3,
  stroke: none,
  [A], [B], [C],
)

// Internal padding
#table(
  columns: 3,
  inset: 10pt,
  [A], [B], [C],
)

Colors and Styles

#table(
  columns: 4,
  fill: (col, row) => {
    if row == 0 { rgb("#2563eb") }
    else if calc.odd(row) { rgb("#f1f5f9") }
    else { white }
  },
  table.header(
    #text(fill: white)[*Col 1*],
    #text(fill: white)[*Col 2*],
    #text(fill: white)[*Col 3*],
    #text(fill: white)[*Col 4*],
  ),
  [A], [B], [C], [D],
  [E], [F], [G], [H],
  [I], [J], [K], [L],
)

Cell Merging

#table(
  columns: 3,
  // Merged header
  table.cell(colspan: 3)[*General Title*],
  [Col A], [Col B], [Col C],
  [1], [2], [3],

  // Vertical merge
  table.cell(rowspan: 2)[Multi], [a], [b],
  [c], [d],
)

Repeated Headers

#table(
  columns: 3,
  table.header(
    [*Name*], [*Value*], [*Unit*],
  ),
  ..data.map(row => (row.name, row.value, row.unit)).flatten()
)

Data Table

// Define the data
#let data = (
  ("January", 1200, +5%),
  ("February", 1350, +12%),
  ("March", 1100, -18%),
)

// Generate the table
#table(
  columns: 3,
  [*Month*], [*Sales*], [*Change*],
  ..data.flatten()
)

Academic Style

#figure(
  table(
    columns: (1fr, auto, auto, auto),
    stroke: none,
    align: (left, center, center, center),
    inset: (x: 8pt, y: 6pt),

    // Top line
    table.hline(stroke: 1pt),
    [*Variable*], [*N*], [*Mean*], [*SD*],
    table.hline(stroke: 0.5pt),

    [Age], [150], [34.5], [12.3],
    [Height], [150], [172.1], [8.7],
    [Weight], [148], [71.2], [14.5],

    // Bottom line
    table.hline(stroke: 1pt),
  ),
  caption: [Descriptive statistics of the sample],
) <tab:stats>
Academic Convention

For scientific articles, use the "three-line" style (top, under header, bottom) without vertical borders.