Styles

# Setup chunk
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  warning = FALSE,
  message = FALSE,
  fig.width = 7.2,
  fig.height = 5
)
options(rmarkdown.html_vignette.check_title = FALSE)

Introduction

In this vignette, we explain how to customise the visualisation of tables and plots. The vignette reviews the structure of the .yml files that define styles, and demonstrates how to create and apply custom styles. It also shows how to style tables and plots programmatically, without the need to create a .yml file.

library(visOmopResults)
library(here)
library(gt)
library(ggplot2)
library(dplyr)
library(officer)

The package currently includes two built-in styles for tables and plots. Styles are defined using .yml files. To list the available styles, use:

tableStyle()
plotStyle()

Branding styles using .yml

The package contains two built-in styles: "default" and "darwin". The .yml files for these styles can be found here.

.yml structure

We use the "darwin" style as an example. The code chunk below shows the structure of its .yml file:

library(yaml)
theme <- read_yaml(file = here("inst/brand/darwin.yml"))
cat("```yaml\n", as.yaml(theme), "```", sep = "")

The .yml structure can be divided into four main sections:

Style hierarchy

Each plot and table element follows a style hierarchy. If a value isn’t specified at the most specific level, it inherits from higher-level entries; if none are defined, the default ggplot2 (for plots) or the default for the specific table type is used. The table below shows the priority order for common plot and table options.

tibble(
  "type" = "Plot",
  "Part" = c("Background color", "Header (facet) color", "Header (facet) text color", "Header (facet) text bold", "Border color", "Grid color", "Axis color", "Legend position", "Font family", "Font size"),
  "Option 1" = c("defaults:visOmopResults:plot:background-color", "defaults:visOmopResults:plot:header-color", "defaults:visOmopResults:plot:header-text-color", "defaults:visOmopResults:plot:header-text-bold", "defaults:visOmopResults:plot:border-color", "defaults:visOmopResults:plot:grid-major-color", "defaults:visOmopResults:plot:axis-color", "defaults:visOmopResults:plot:legend-position", "defaults:visOmopResults:plot:font_family", "defaults:visOmopResults:plot:font_size"),
  "Option 2" = c("color:background", "color:foreground", "-", "color:foreground", "-", "color:foreground", "-", "-",  "typography:base:family", "defaults:visOmopResults:plot:font_size"),
  "Option 3" = c(rep("-", 9), "typography:base:size")
) |> 
  bind_rows(
    tibble(
      "type" = "Table section",
      "Part" = c("Background color", "Text bold", "Text color", "Text align", "Font size", "Font family", "Border color", "Border width"),
      "Option 1" = c("defaults:visOmopResults:table:[section_name]:background-color", "defaults:visOmopResults:table:[section_name]:text-bold", "defaults:visOmopResults:table:[section_name]:text-color", "defaults:visOmopResults:table:[section_name]:align", "defaults:visOmopResults:table:[section_name]:font-size", "defaults:visOmopResults:table:[section_name]:font-family", "defaults:visOmopResults:table:[section_name]:border-color", "defaults:visOmopResults:table:[section_name]:border-width"),
      "Option 2" = c("color:background", "-", "-", "-", "defaults:visOmopResults:table:font-size", "defaults:visOmopResults:table:font_family", "defaults:visOmopResults:table:border-color", "defaults:visOmopResults:table:border-width"),
      "Option 3" = c("-", "-", "-", "-", "defaults:visOmopResults:typography:base:size", "typography:base:family", "-", "-")
    )
  ) |>
  visTable(groupColumn = "type")

In the examples above the YML path is represented with colon separators. For example, plot:background-color refers to the background-color key inside the plot section.

Applying styles to tables and plots

The table-formatting functions (visTable(), visOmopTable(), and formatTable()) and plot functions accept a style argument. The style argument can be:

Example: apply the built-in "darwin" style to a plot:

result <- mockSummarisedResult() |> 
  filter(variable_name == "age")

barPlot(
  result = result,
  x = "cohort_name",
  y = "mean",
  facet = c("age_group", "sex"),
  colour = "sex",
  style = "darwin"
)

Example: use a custom .yml file (path provided):

barPlot(
  result = result,
  x = "cohort_name",
  y = "mean",
  facet = c("age_group", "sex"),
  colour = "sex",
  style = here("MyStyleFolder", "MyStyle.yml")
)

Use of _brand.yml

If style = NULL and no global options are provided (via setGlobalPlotOptions() or setGlobalTableOptions()), the built-in "default" style is used. However, if a _brand.yml file is present in the project directory, that file’s style will be used.

Alternative style customisation

You can customise styles programmatically without creating a .yml file by passing a named list to the style argument. The list should follow the same table section structure as the .yml.

Tables

Below is an example that sets table section styles for gt.

result |>
  visOmopTable(
    estimateName = c("Mean (SD)" = "<mean> (<sd>)"),
    groupColumn = "cohort_name",
    header = c("This is an overall header", "sex"),
    type = "gt",
    style = list(
      header = list(
        cell_text(weight = "bold"), 
        cell_fill(color = "red")
      ),
      header_name = list(
        cell_text(weight = "bold"), 
        cell_fill(color = "orange")
      ),
      header_level = list(
        cell_text(weight = "bold"), 
        cell_fill(color = "yellow")
      ),
      column_name = list(
        cell_text(weight = "bold")
      ),
      group_label = list(
        cell_fill(color = "blue"),
        cell_text(color = "white", weight = "bold")
      ),
      title = list(
        cell_text(size = 20, weight = "bold")
      ),
      subtitle = list(
        cell_text(size = 15)
      ),
      body = list(
        cell_text(color = "red")
      )
    ),
    .options = list(
      title = "My formatted table!",
      subtitle = "Created with the `visOmopResults` R package.",
      groupAsColumn = FALSE,
      groupOrder = c("cohort2", "cohort1")
    )
  )

Note that style objects differ across table engines, so the code must be adapted to the engine you use.

For flextable, styling objects come from the officer package. The structure is similar, but the style objects differ:

result |>
  visOmopTable(
    estimateName = c("Mean (SD)" = "<mean> (<sd>)"),
    groupColumn = "cohort_name",
    header = c("This is an overall header", "sex"),
    type = "flextable",
    style = list(
      header = list(
        cell = fp_cell(background.color = "red"),
        text = fp_text(bold = TRUE)
      ),
      header_level = list(
        cell = fp_cell(background.color = "orange"),
        text = fp_text(bold = TRUE)
      ),
      header_name = list(
        cell = fp_cell(background.color = "yellow"),
        text = fp_text(bold = TRUE)
      ),
      column_name = list(
        text = fp_text(bold = TRUE)
      ),
      group_label = list(
        cell = fp_cell(background.color = "blue"),
        text = fp_text(bold = TRUE, color = "white")
      ),
      title = list(
        text = fp_text(bold = TRUE, font.size = 20)
      ),
      subtitle = list(
        text = fp_text(font.size = 15)
      ),
      body = list(
        text = fp_text(color = "red")
      )
    ),
    .options = list(
      title = "My formatted table!",
      subtitle = "Created with the `visOmopResults` R package.",
      groupAsColumn = FALSE,
      groupOrder = c("cohort2", "cohort1")
    )
  )

Plots

Plot helpers return ggplot2 objects, so you can further modify them using + and regular ggplot2 calls:

library(ggplot2)

barPlot(
  result = result,
  x = "cohort_name",
  y = "mean",
  facet = c("age_group", "sex"),
  colour = "sex"
) +
  theme(
    strip.background = element_rect(fill = "#ffeb99", colour = "#ffcc00"),
    legend.position = "top",
    panel.grid.major = element_line(color = "transparent", linewidth = 0.25)
  ) +
  scale_color_manual(values = c("black", "black", "black")) +
  scale_fill_manual(values = c("#999999", "#E69F00", "#56B4E9"))

Using non-registered font families in ggplot2

To use a specific font family in ggplot2, the font must be:

  1. Installed in the operating system, and

  2. Available to R’s graphics device (registered, in the case of Windows).

Below is an example using the Calibri font.

1. Install the font in the system

On both macOS and Windows, install the .ttf file by double-clicking it and clicking Install.

Example source: https://www.freefontdownload.org/en/calibri.font

After installing new system fonts, restart R or RStudio so the font registry is refreshed.

2. Register the font

On macOS, most system fonts are automatically available to R’s Quartz graphics device (no need to register).

On Windows, however, the base graphics device does not automatically expose all installed system fonts. You must register a font before ggplot2 can use it. This can be done as follows:

windowsFonts(Calibri = windowsFont("Calibri"))

3. Create plots with styles that use the font

You can specify the font family in your YAML configuration, or directly in theme() using element_text(). Below is an example using the "darwin" plot style, which will use "Calibri" when available, otherwise falling back to "sans":

barPlot(
  result = result,
  x = "cohort_name",
  y = "mean",
  facet = c("age_group", "sex"),
  colour = "sex",
  style = "darwin"
)

Important notes

Final remarks

The .yml customisation system allows you to control most aspects of the visual appearance of your tables and plots. To learn more about brand.yml and how it interacts with other elements such as Shiny apps and Quarto/R Markdown documents, refer to https://posit-dev.github.io/brand-yml/.



Try the visOmopResults package in your browser

Any scripts or data that you put into this service are public.

visOmopResults documentation built on Feb. 4, 2026, 9:07 a.m.