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()

Tip

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" "hidden"
weight = 1 px(2) "3px" px(4) "5px"

cell_fill()

color = "wheat" "#9fd28d"
alpha = .5 .8

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
column_labels.border.vline
row_group.border.top
row_group.border.left
table_body.hlines
stub_border.color

summary_row.border.color

row_group.border.right
row_group.border.bottom
table_body.vlines
stub_border.color

summary_row.border.color

source_notes.border.lr
source_note.bottom.border
footnotes.border.lr
footnotes.bottom.border
table.border.top
column_labels.border.top
column_labels.border.bottom
column_labels.border.lr
table.border.left
table.border.right
grand_summary_row.border
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()
mfr model year
Ford GT 2017
Ferrari 458 Speciale 2015
Ferrari 458 Spider 2015
Ferrari 458 Italia 2014

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()
mfr model year
Ford GT 2017
Ferrari 458 Speciale 2015
Ferrari 458 Spider 2015
Ferrari 458 Italia 2014

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()
mfr model year
Ford GT 2017
Ferrari 458 Speciale 2015
Ferrari 458 Spider 2015
Ferrari 458 Italia 2014

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()
mfr model year
Ford GT 2017
Ferrari 458 Speciale 2015
Ferrari 458 Spider 2015
Ferrari 458 Italia 2014

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()
mfr model year
Ford GT 2017
Ferrari 458 Speciale 2015
Ferrari 458 Spider 2015
Ferrari 458 Italia 2014

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()
mfr model year
Ford GT 2017
Ferrari 458 Speciale 2015
Ferrari 458 Spider 2015
Ferrari 458 Italia 2014

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