Basic gt Styling Reference
gt allows for extensive and precise table styling. This is a non-comprehensive quick reference to aid users in easily knowing the basic, common functions and arguments and what they do.
There are two basic styling functions: tab_style allows for custom styling of one or more cells and tab_options modifies the (150+ provided) options of a table. gt continues adding more specific stand-alone styling functions with opt_*(), which can be found in its documentation.
tab_style(gt, style, locations)
style =
cell_text()
Give your hex codes names for easier coding: peach <- "#f9bc9c" & cell_border(color = peach)
| color = | "wheat" | "#9fd28d" | peach1 | |
|---|---|---|---|---|
| font = | google_fonts(name = "Merriweather") | "Garamond" | "sans-serif" | default_fonts() |
| size = | px(8) | "14px" | "xx-small" | "x-large" |
| align = | "center" | "left" | "right" | "justify" |
| valign = | "middle" | "top" | "bottom" | |
| style = | "normal" | "italic" | "oblique" | |
| weight = | "bold" | "lighter" | "bolder" | 8002 |
| decorate = | "line-through" | "underline" | "overline" | "underline overline" |
| transform = | "uppercase"3 | "lowercase" | "capitalize"3 | |
| indent = | px(15) | "25px" | pct(10) | |
| 1 See above callout tip. | ||||
| 2 Number from 1-1000 - only with variable fonts. | ||||
| 3 Code must be written in lowercase - example here shows the output. | ||||
cell_borders()
| sides = | "left" | "right" | "top" | c("top", "bottom") | "all" |
|---|---|---|---|---|---|
| color = | "wheat" | "#9fd28d" | |||
| style = | "solid" | "dashed" | "dotted" | ||
| weight = | 1 | px(2) | "3px" | px(4) | "5px" |
cell_fill()
locations =
Use one - or more with list() - of these to target cells.
| cells_title(groups = "title") | |||
| cells_title(groups = "subtitle") | |||
| cells_stubhead() | cells_column_labels(columns = ) | cells_column_spanners(spanners = ) | |
|---|---|---|---|
| cells_row_groups(groups = "grp1") | |||
| cells_stub(rows = 1) | cells_body(column = 2, row = 1) | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub_summary(groups = , rows = ) | cells_summary(groups = , columns = , rows = )
|
||
| cells_row_groups(groups = "grp2") | |||
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub() | cells_body() | cells_body() | cells_body() |
| cells_stub_summary(groups = , rows = ) | cells_summary(groups = , columns = , rows = )
|
||
| cells_stub_grand_summary(rows = ) | cells_grand_summary(columns = , rows = )
|
||
| cells_source_notes() | |||
| cells_footnotes() | |||
tab_options(gt, options)
Borders
All borders have three associated arguments: .color, .width, and .style. These are (almost) all the borders you can target.
heading.border.lr heading.border.bottom |
|||
row_group.border.top row_group.border.left |
|||
row_group.border.right row_group.border.bottom |
|||
source_notes.border.lr source_note.bottom.border |
|||
| footnotes.border.lr footnotes.bottom.border |
table.border.top column_labels.border.top |
|
| table_body.border.bottom table.border.bottom |
There’s one missing: table_body.border.top. It shares space with row_group.border.top in the first table and column_lables.border.bottom in the second table. You’ll only need to use it when you don’t have column labels or row groups.
Which Border Wins?
Scenario: You set the color for table.border.bottom.color, but it’s still gray. But you find if you set table.border.bottom.width at 3px, suddenly it is the color you set.
There is logic to this - the rules for how CSS handles border conflict. Every cell actually has 4 borders. They’re almost always collapsed because separate borders are ugly. When they collapse, CSS decides which one matters the most.
column_labels.border.bottom and table_body.border.top share the same border space so they can be an example here.
If we set a color for each of them, only one of them will show. Both of those options were rendered by gt in HTML file, but CSS prioritizes one of them.
border_fight %>%
tab_options(
column_labels.border.bottom.color = green,
table_body.border.top.color = peach
) %>%
as_raw_html()Here are the rules, tailored for gt table-making:
The style “hidden” beats everything - if any of the borders are “hidden”, none of the borders will show.
border_fight %>%
tab_options(
column_labels.border.bottom.color = green,
column_labels.border.bottom.style = "hidden",
column_labels.border.bottom.width = "2px",
table_body.border.top.color = peach,
table_body.border.top.style = "solid",
table_body.border.top.width = "2px"
) %>%
as_raw_html()The “none” style hides a border but doesn’t affect any others.
border_fight %>%
tab_options(
column_labels.border.bottom.color = green,
column_labels.border.bottom.style = "none",
column_labels.border.bottom.width = "2px",
table_body.border.top.color = peach,
table_body.border.top.style = "solid",
table_body.border.top.width = "2px"
) %>%
as_raw_html()Wider borders win.
border_fight %>%
tab_options(
column_labels.border.bottom.color = green,
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = "2px",
table_body.border.top.color = peach,
table_body.border.top.style = "solid",
table_body.border.top.width = "3px"
) %>%
as_raw_html()Then it goes to style in the order: “double”, “solid”, “dashed”, “dotted”.
border_fight %>%
tab_options(
column_labels.border.bottom.color = green,
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = "2px",
table_body.border.top.color = peach,
table_body.border.top.style = "double",
table_body.border.top.width = "2px"
) %>%
as_raw_html()If the only difference is color, then border that will show is the one associated with, in order of priority: cell, row, table part (header, body, or footer), then table.
border_fight %>%
tab_options(
column_labels.border.bottom.color = green,
column_labels.border.bottom.style = "solid",
column_labels.border.bottom.width = "2px",
table_body.border.top.color = peach,
table_body.border.top.style = "solid",
table_body.border.top.width = "2px"
) %>%
as_raw_html()If you were writing the CSS for an HTML table from scratch, this wouldn’t matter as much. But gt makes things easier by building in reasonable defaults, which means that occasionally things might not show up as you think they will. There is one surefire way to avoid any of this though, which is to set all your borders at >2px.
More options for tab_options
| Table Part | Attribute |
|---|---|
| .background.color | |
| table | |
| heading | |
| column_labels | |
| row_group | |
| stub | |
| summary_row | |
| grand_summary_row | |
| footnotes | |
| source_notes | |
| row.striping | |
| .text_transform | |
| column_labels | |
| row_group | |
| stub | |
| stub_row_group | |
| summary_row | |
| grand_summary_row | |
| Table Part | Attribute |
|---|---|
| .font.size | |
| table | |
| heading.title | |
| heading.subtitle | |
| column_labels | |
| row_group | |
| stub | |
| stub_row_group | |
| footnotes | |
| source_notes | |
| .font.weight | |
| table | |
| heading.title | |
| heading.subtitle | |
| column_labels | |
| row_group | |
| stub | |
| stub_row_group | |
| Table Part | Attribute |
|---|---|
| .padding | |
| heading | |
| column_labels | |
| row_group | |
| data_row | |
| summary_row | |
| grand_summary_row | |
| footnotes | |
| source_notes | |
| .padding.horizontal | |
| heading | |
| column_labels | |
| row_group | |
| data_row | |
| summary_row | |
| grand_summary_row | |
| footnotes | |
| source_notes | |