Five functions in the package take styling as named lists rather than
as a long tail of arguments. gt_title_header() has
kicker_style, title_style,
subtitle_style, and date_style.
gt_legend_continuous() has title_style and
labels_style. gt_legend_discrete() has
heading_style, subtitle_style, and
label_style. gt_grid() and
gt_stack_tables() each have four, one per piece of their
shared header and footer.
They all read the same keys, so what you learn on one carries to the
others. This vignette runs through them on mtcars.
The keys
Every style list accepts the same thirteen names. Anything you leave out keeps its default.
| Key | Takes | Notes |
|---|---|---|
font |
A Google font name | Loaded through gt, so it survives
gtsave()
|
size |
Number or CSS string | |
color |
Hex color | |
weight |
Number or CSS keyword |
600, "bold"
|
italic |
TRUE / FALSE
|
|
spacing |
Number or CSS string | Letter spacing |
transform |
CSS string |
"uppercase", "lowercase"
|
align |
"left", "center",
"right"
|
|
line_height |
Number | |
margin_top, margin_bottom
|
Number or CSS string | |
padding_top, padding_bottom
|
Number or CSS string |
Any key that takes a length reads a bare number as pixels, so
size = 30 gives 30px. Pass a string when you
want other units, like size = "2rem" or
spacing = "0.08em".
A header block
gt_title_header() builds a header out of four parts,
each styled on its own. Only title is required. Start with
everything at its default.
cars %>%
gt() %>%
gt_theme_broadsheet() %>%
gt_title_header(
title = "Fuel economy and power",
kicker = "1974 Motor Trend",
subtitle = "Ten of the cars road tested that year",
date = as.Date("2026-07-25")
)|
1974 Motor Trend
Fuel economy and power
|
|||
|
Ten of the cars road tested that year
July 25, 2026
|
|||
| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| Hornet 4 Drive | 21.4 | 110 | 3.215 |
| Hornet Sportabout | 18.7 | 175 | 3.440 |
| Valiant | 18.1 | 105 | 3.460 |
The kicker arrives with a color and uppercase treatment already set,
since a kicker is nearly always a small colored line above the title.
The date is formatted as "July 25, 2026" when you pass a
Date. Any other value passes through as written, so
date = "Week 12" renders as Week 12.
Now tune it. Each list only has to name the keys you want to change.
cars %>%
gt() %>%
gt_theme_broadsheet() %>%
gt_title_header(
title = "Fuel economy and power",
kicker = "1974 Motor Trend",
subtitle = "Ten of the cars road tested that year",
date = as.Date("2026-07-25"),
kicker_style = list(color = "#0F5257", spacing = "0.16em", size = "0.7em"),
title_style = list(font = "Oswald", size = 34, weight = 600,
spacing = "-0.01em", margin_bottom = 2),
subtitle_style = list(size = "1.05em", color = "#5C574F", italic = TRUE),
date_style = list(size = "0.75em", transform = "uppercase", spacing = "0.1em")
)|
1974 Motor Trend
Fuel economy and power
|
|||
|
Ten of the cars road tested that year
July 25, 2026
|
|||
| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| Hornet 4 Drive | 21.4 | 110 | 3.215 |
| Hornet Sportabout | 18.7 | 175 | 3.440 |
| Valiant | 18.1 | 105 | 3.460 |
Because the lists merge over the defaults rather than replacing them,
setting kicker_style = list(size = 20) changes the size and
leaves the color and uppercase treatment alone.
Fonts
Naming a font loads it through gt’s own
font machinery, so it works in the browser and in a saved image. Leave
font unset and the element inherits whatever the theme is
using, which is usually what you want for a title sitting on a themed
table.
cars %>%
gt() %>%
gt_theme_terminal() %>%
gt_title_header(
title = "Inherited from the theme",
subtitle = "No font named, so both pick up the theme's monospace",
title_style = list(size = 26),
subtitle_style = list(size = "0.95em")
)Inherited from the theme |
|||
No font named, so both pick up the theme's monospace |
|||
| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| Hornet 4 Drive | 21.4 | 110 | 3.215 |
| Hornet Sportabout | 18.7 | 175 | 3.440 |
| Valiant | 18.1 | 105 | 3.460 |
Legend text
The legends read the same keys. gt_legend_continuous()
styles its title and its tick labels.
cars %>%
gt() %>%
gt_theme_swiss() %>%
gt_color_ranks(mpg, domain = c(10, 35)) %>%
gt_legend_continuous(
title = "Miles per gallon",
title_style = list(font = "Oswald", size = 12, transform = "uppercase",
spacing = "0.12em", color = "#12263F"),
labels_style = list(size = 11, color = "#5A6B7E")
)| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| Hornet 4 Drive | 21.4 | 110 | 3.215 |
| Hornet Sportabout | 18.7 | 175 | 3.440 |
| Valiant | 18.1 | 105 | 3.460 |
Miles per gallon
1035
|
|||
gt_legend_discrete() styles a heading, a subtitle, and
the swatch labels.
cars %>%
gt() %>%
gt_theme_broadsheet() %>%
gt_legend_discrete(
c("Under 20 mpg" = "#DB9070", "20 mpg and over" = "#9DC5A7"),
heading = "Fuel economy",
subtitle = "Grouped at the 20 mpg mark",
location = "top",
heading_style = list(font = "Oswald", size = 22, transform = "uppercase"),
subtitle_style = list(size = 12, italic = TRUE, color = "#5C574F"),
label_style = list(size = 12, weight = 500)
)Fuel economy
Grouped at the 20 mpg mark
Under 20 mpg20 mpg and over
|
|||
| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| Hornet 4 Drive | 21.4 | 110 | 3.215 |
| Hornet Sportabout | 18.7 | 175 | 3.440 |
| Valiant | 18.1 | 105 | 3.460 |
One exception worth knowing. With
label_placement = "inside", each label is printed on its
own swatch and takes black or white by whichever contrasts better with
that swatch, so a color in label_style is
ignored in that mode. Every other key still applies.
Grids and stacks
gt_grid() and gt_stack_tables() wrap
several tables in a shared header and footer, and style each piece the
same way.
small <- cars %>% slice_head(n = 3) %>% gt() %>% gt_theme_booktabs()
gt_grid(
list(small, small),
ncol = 2,
labels = c("First three", "Repeated"),
title = "Two blocks, one header",
subtitle = "The header belongs to the grid, not to either table",
caption = "Caption sits above the rule",
source_note = "Source note sits below it",
caption_rule = TRUE,
title_style = list(font = "Oswald", size = 26, transform = "uppercase"),
subtitle_style = list(size = 13, color = "#5A6B7E", margin_bottom = 18),
caption_style = list(size = 11, color = "#12263F"),
source_note_style = list(size = 11, color = "#5A6B7E", italic = TRUE),
label_style = list(font = "Oswald", size = 12, transform = "uppercase")
)| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
There is one real difference here. A grid is composed HTML rather
than a gt table, so it has no theme to inherit from.
Elements with no font fall back to a system stack instead
of picking up the tables’ typography. Name a font on the
grid’s own lists when you want the header to match the blocks under
it.
Ordering
gt_title_header() calls gt::tab_header(),
which replaces the whole header. gt_legend_continuous() and
gt_legend_discrete() ride in that same header when
location = "top". Call gt_title_header()
first, or it will overwrite the legend you just added.
cars %>%
gt() %>%
gt_theme_almanac() %>%
gt_color_ranks(mpg, domain = c(10, 35)) %>%
gt_title_header(
title = "Header first",
title_style = list(font = "Oswald", size = 24)
) %>%
gt_legend_continuous(location = "top")Header first |
|||
1035
|
|||
| car | mpg | hp | wt |
|---|---|---|---|
| Mazda RX4 | 21.0 | 110 | 2.620 |
| Mazda RX4 Wag | 21.0 | 110 | 2.875 |
| Datsun 710 | 22.8 | 93 | 2.320 |
| Hornet 4 Drive | 21.4 | 110 | 3.215 |
| Hornet Sportabout | 18.7 | 175 | 3.440 |
| Valiant | 18.1 | 105 | 3.460 |
That last call takes no palette or domain.
gt_color_ranks() records the scale it used, and the legend
reads it back, so the two cannot disagree.
