Skip to contents

Lays a list of tables out in rows and columns as small multiples, one table per region or per quarter. gtExtras::gt_two_column_layout() handles exactly two tables and gt_stack_tables() stacks any number of them vertically. This covers the rest.

Usage

gt_grid(
  tables = NULL,
  ncol = 2,
  labels = NULL,
  label_style = list(),
  title = NULL,
  subtitle = NULL,
  caption = NULL,
  source_note = NULL,
  caption_rule = FALSE,
  title_style = list(),
  subtitle_style = list(),
  caption_style = list(),
  source_note_style = list(),
  gap = 24,
  align = c("top", "center", "bottom"),
  file = NULL,
  bg = "white",
  whitespace = 50,
  zoom = 2
)

Arguments

tables

A list of gt table objects.

ncol

Integer. The number of tables across. The number of rows follows from the length of tables. Defaults to 2.

labels

Character. An optional caption above each table, recycled against tables. Rendered in a neutral style rather than each table's own, and placed outside the table so a wide label does not stretch its panel. Defaults to NULL.

label_style

A list of style options for the per-table captions. See title_style for the keys. Defaults to an empty list.

title

Character. An optional heading above the whole grid. Set this instead of giving each table its own gt::tab_header(). Defaults to NULL.

subtitle

Character. An optional line below title. Defaults to NULL.

caption

Character. An optional note below the grid. Defaults to NULL.

source_note

Character. An optional second line below caption, right-aligned by default. Set both, with caption_rule = TRUE, for the split caption gt_538_caption() gives a single table. Defaults to NULL.

caption_rule

Logical. Should a hairline rule sit between caption and source_note? Defaults to FALSE.

title_style, subtitle_style, caption_style, source_note_style

Lists of style options. Recognized keys are font (a Google font name), size, color, weight, italic, spacing (letter spacing), transform (such as "uppercase"), and align, plus line_height, margin_top, margin_bottom, padding_top, and padding_bottom for nudging the blocks closer together or further apart. Any key you leave out keeps its default, so title_style = list(size = "34px") changes only the size. Same convention as gt_title_header(). Lengths take a number, read as pixels, or a CSS string such as "2rem"; a negative margin pulls an element up tight against the one above it.

gap

Numeric. The space between tables in pixels. Defaults to 24.

align

Character. How tables of differing height line up within a row. Either "top", "center", or "bottom". Defaults to "top".

file

Optional. A path to write a PNG to. If NULL, the grid is returned for the viewer instead. Defaults to NULL.

bg

Character. The background color, used when saving. Defaults to "white".

whitespace

Numeric. Padding left around the grid when saving, in pixels. Defaults to 50.

zoom

Numeric. The rendering zoom factor used when saving. Defaults to 2.

Value

An htmltools::browsable() tag list of the grid, which prints in the viewer; with file, invisibly file after writing the PNG to it.

Details

Unlike most of this package, this does not return a gt table. Separate tables have their own columns, widths, and headers, so there is no single table to hand back; the grid is assembled as HTML. That makes it a last step, after each table is themed and formatted, and it is why saving happens here through file rather than through gt_save_crop().

Each table also keeps its own heading. Use title when the tables are blocks of a single thing, as with a long ranking split in two, and per-table gt::tab_header()s when they are genuinely separate exhibits.

Saving needs the webshot2 package.

See also

gt_stack_tables() for a vertical stack, and gt_snake() for folding a single long table into blocks.

Examples

library(gt)

afc <- subset(sdv_example_standings, conference == "AFC")
by_division <- lapply(split(afc, afc$division), function(d) {
  gt(d[c("team_name", "wins", "losses", "points_for")]) |>
    gt_theme_broadsheet() |>
    tab_header(title = d$division[[1]])
})

gt_grid(by_division, ncol = 2)
AFC East
team_name wins losses points_for
New England Patriots 14 3 490
Buffalo Bills 12 5 481
Miami Dolphins 7 10 347
New York Jets 3 14 300
AFC North
team_name wins losses points_for
Pittsburgh Steelers 10 7 397
Baltimore Ravens 8 9 424
Cincinnati Bengals 6 11 414
Cleveland Browns 5 12 279
AFC South
team_name wins losses points_for
Jacksonville Jaguars 13 4 474
Houston Texans 12 5 404
Indianapolis Colts 8 9 466
Tennessee Titans 3 14 284
AFC West
team_name wins losses points_for
Denver Broncos 14 3 401
Los Angeles Chargers 11 6 368
Kansas City Chiefs 6 11 362
Las Vegas Raiders 3 14 241
# \donttest{ # one heading over the whole sheet gt_grid(by_division, ncol = 2, title = "The AFC by division", subtitle = "2025 NFL regular season", caption = "Data: nflreadr" )
The AFC by division
2025 NFL regular season
AFC East
team_name wins losses points_for
New England Patriots 14 3 490
Buffalo Bills 12 5 481
Miami Dolphins 7 10 347
New York Jets 3 14 300
AFC North
team_name wins losses points_for
Pittsburgh Steelers 10 7 397
Baltimore Ravens 8 9 424
Cincinnati Bengals 6 11 414
Cleveland Browns 5 12 279
AFC South
team_name wins losses points_for
Jacksonville Jaguars 13 4 474
Houston Texans 12 5 404
Indianapolis Colts 8 9 466
Tennessee Titans 3 14 284
AFC West
team_name wins losses points_for
Denver Broncos 14 3 401
Los Angeles Chargers 11 6 368
Kansas City Chiefs 6 11 362
Las Vegas Raiders 3 14 241
Data: nflreadr
# a 538-style split caption under the whole sheet gt_grid(by_division, ncol = 2, title = "The AFC by division", caption = gt::md("Teams are grouped by **division**."), source_note = "Data: nflreadr | Andrew Weatherman", caption_rule = TRUE )
The AFC by division
AFC East
team_name wins losses points_for
New England Patriots 14 3 490
Buffalo Bills 12 5 481
Miami Dolphins 7 10 347
New York Jets 3 14 300
AFC North
team_name wins losses points_for
Pittsburgh Steelers 10 7 397
Baltimore Ravens 8 9 424
Cincinnati Bengals 6 11 414
Cleveland Browns 5 12 279
AFC South
team_name wins losses points_for
Jacksonville Jaguars 13 4 474
Houston Texans 12 5 404
Indianapolis Colts 8 9 466
Tennessee Titans 3 14 284
AFC West
team_name wins losses points_for
Denver Broncos 14 3 401
Los Angeles Chargers 11 6 368
Kansas City Chiefs 6 11 362
Las Vegas Raiders 3 14 241
Teams are grouped by division.
Data: nflreadr | Andrew Weatherman
# tighten the subtitle up under the title, and open the gap to the grid gt_grid(by_division, ncol = 2, title = "The AFC", subtitle = "2025 regular season", title_style = list(margin_bottom = -2), subtitle_style = list(margin_bottom = 24) )
The AFC
2025 regular season
AFC East
team_name wins losses points_for
New England Patriots 14 3 490
Buffalo Bills 12 5 481
Miami Dolphins 7 10 347
New York Jets 3 14 300
AFC North
team_name wins losses points_for
Pittsburgh Steelers 10 7 397
Baltimore Ravens 8 9 424
Cincinnati Bengals 6 11 414
Cleveland Browns 5 12 279
AFC South
team_name wins losses points_for
Jacksonville Jaguars 13 4 474
Houston Texans 12 5 404
Indianapolis Colts 8 9 466
Tennessee Titans 3 14 284
AFC West
team_name wins losses points_for
Denver Broncos 14 3 401
Los Angeles Chargers 11 6 368
Kansas City Chiefs 6 11 362
Las Vegas Raiders 3 14 241
# styled without writing any css gt_grid(by_division, ncol = 2, title = "The AFC by division", subtitle = "2025 NFL regular season", title_style = list(font = "Oswald", size = 34, transform = "uppercase"), subtitle_style = list(italic = TRUE, color = "#8A8A8A") )
The AFC by division
2025 NFL regular season
AFC East
team_name wins losses points_for
New England Patriots 14 3 490
Buffalo Bills 12 5 481
Miami Dolphins 7 10 347
New York Jets 3 14 300
AFC North
team_name wins losses points_for
Pittsburgh Steelers 10 7 397
Baltimore Ravens 8 9 424
Cincinnati Bengals 6 11 414
Cleveland Browns 5 12 279
AFC South
team_name wins losses points_for
Jacksonville Jaguars 13 4 474
Houston Texans 12 5 404
Indianapolis Colts 8 9 466
Tennessee Titans 3 14 284
AFC West
team_name wins losses points_for
Denver Broncos 14 3 401
Los Angeles Chargers 11 6 368
Kansas City Chiefs 6 11 362
Las Vegas Raiders 3 14 241
# } # straight to an image; saving needs a headless Chrome (webshot2) # \donttest{ if (interactive() && rlang::is_installed("webshot2") && isTRUE(file.exists(chromote::find_chrome()))) { gt_grid(by_division, ncol = 2, file = tempfile(fileext = ".png"), bg = "#FBFAF7") } # }