The Mad Hatter’s Guide to Data Viz and Stats in R
  1. Data Viz and Stats
  2. Arts
  3. Fonts in ggplot
  • Data Viz and Stats
    • Tools
      • Introduction to R and RStudio
    • Descriptive Analytics
      • Data
      • Inspect Data
      • Graphs
      • Summaries
      • Counts
      • Quantities
      • Groups
      • Distributions
      • Groups and Distributions
      • Change
      • Proportions
      • Parts of a Whole
      • Evolution and Flow
      • Ratings and Rankings
      • Surveys
      • Time
      • Space
      • Networks
      • Miscellaneous Graphing Tools, and References
    • Inference
      • Basics of Statistical Inference
      • 🎲 Samples, Populations, Statistics and Inference
      • Basics of Randomization Tests
      • Inference for a Single Mean
      • Inference for Two Independent Means
      • Inference for Comparing Two Paired Means
      • Comparing Multiple Means with ANOVA
      • Inference for Correlation
      • Testing a Single Proportion
      • Inference Test for Two Proportions
    • Modelling
      • Modelling with Linear Regression
      • Modelling with Logistic Regression
      • 🕔 Modelling and Predicting Time Series
    • Workflow
      • Facing the Abyss
      • I Publish, therefore I Am
      • Data Carpentry
    • Arts
      • Colours
      • Fonts in ggplot
      • Annotating Plots: Text, Labels, and Boxes
      • Annotations: Drawing Attention to Parts of the Graph
      • Highlighting parts of the Chart
      • Changing Scales on Charts
      • Assembling a Collage of Plots
      • Making Diagrams in R
    • AI Tools
      • Using gander and ellmer
      • Using Github Copilot and other AI tools to generate R code
      • Using LLMs to Explain Stat models
    • Case Studies
      • Demo:Product Packaging and Elderly People
      • Ikea Furniture
      • Movie Profits
      • Gender at the Work Place
      • Heptathlon
      • School Scores
      • Children's Games
      • Valentine’s Day Spending
      • Women Live Longer?
      • Hearing Loss in Children
      • California Transit Payments
      • Seaweed Nutrients
      • Coffee Flavours
      • Legionnaire’s Disease in the USA
      • Antarctic Sea ice
      • William Farr's Observations on Cholera in London
    • Projects
      • Project: Basics of EDA #1
      • Project: Basics of EDA #2
      • Experiments

On this page

  • 1 Setting up R Packages
  • 2 Using Preferred Fonts
    • 2.1 Live-loading Fonts from Google
  • 3 Adding local fonts from your computer
  • 4 Plot Theme using Desired fonts
  • 5 Data
  • 6 Basic Plot
  • 7 Using {marquee}
  • 8 Using {ggtext}
    • 8.1 element_markdown()
    • 8.2 element_markdown() in combination with HTML
  • 9 Wait, but Why?
  • 10 Conclusions
  • 11 References
  1. Data Viz and Stats
  2. Arts
  3. Fonts in ggplot

Fonts in ggplot

Using fonts from your machine and from Google

Author

Arvind V.

Published

August 2, 2025

Modified

September 30, 2025

library(tidyverse) ## data science package collection (incl. the ggplot2 package)
library(systemfonts) ## use custom fonts (need to be installed on your OS)
library(showtext) ## add google fonts to plots
library(scico) ## Colour palette
library(ggtext) ## add improved text rendering to ggplot2
library(gfonts) ## Use Google Fonts offline
library(ggrepel) ## Text-repelled labels
library(marquee) ## Annotations with fonts in ggplot

1 Setting up R Packages

We may have been using ggplot2 for a while now, but there is always more to learn about the aesthetics of our plots. In this module, we will explore how to use different fonts and themes to make our plots look more polished and professional.

We may also want to use fonts on our websites and we will look at using packages like sysfonts . gfonts, and showtext to add custom fonts to our plots and websites. For instance you may want your website to look this: Project Peasants !!

2 Using Preferred Fonts

We may prefer specific fonts for our plots, and we may also want to use these fonts on our websites. There are (atleast) two ways in which one can use fonts in R:

  • Live Downloading of Fonts: Downloading fonts from Google within the R session, using the showtext package.
  • Using Locally Installed Fonts: Using fonts that are already installed/downloaded on your computer, also using the sysfonts package.
NoteNew Package systemfonts

There is also a more recent, and comprehensive package called systemfonts We will postpone this for a later presentation (mainly because I am still figuring it out. 😅 )

ImportantGDPR Compliance

Using fonts that are already installed on your computer is GDPR compliant. Using fonts directly from Google may not be, as it may involve sending data to Google servers every time your website is loaded.

2.1 Live-loading Fonts from Google

We will want to add a few new fonts from Google to our graphs. The best way (currently) is to use the sysfonts package (which we loaded above) to bring into our work fonts from Google. To view and select the fonts you might want to work with, spend some time looking over Google Fonts.

Let us add a handful of fonts to our R session. We will use the font_add_google() function from the sysfonts package to download Google fonts into our session. These fonts will then be included into our session using showtext_auto().

This needs to be included in each Quarto document on your website.

```{r}
#| label: download-google-fonts
#| cache: true

## Clean the slate
systemfonts::clear_local_fonts()
systemfonts::clear_registry()
##
sysfonts::font_add_google(name = "Gochi Hand", family = "GochiHand")
font_add_google("Schoolbell", "Schoolbell")
font_add_google("Roboto Condensed", "RobotoCondensed")
font_add_google("Noto Sans", "Noto")
font_add_google("Jura", "Jura")
font_add_google("Ibarra Real Nova", "Ibarra")
font_add_google("Open Sans", "Open")
font_add_google("Anton", "Anton")
font_add_google("Tangerine", "Tangerine")
font_add_google("Fraunces", "Fraunces")

```
```{r}
#| label: enable-showtext

showtext_auto() # set these fonts as default for the session
sysfonts::font_families() # check which fonts are available in the session

```

Ensure that you use the right name for the font family, as shown above. It is text-sensitive. The family is up to you to choose. Using similar names for name and family is a good idea, as shown above.

3 Adding local fonts from your computer

Using Google fonts as shown above means that every time someone loads your website on their browser, the browser goes off to Google to download the fonts on the fly. As mentioned above, this will typically make your website non-compliant with GDPR.

One solution is to download fonts a priori from Google, or from elsewhere, and then import them into your session. The sysfonts::font_add() function allows us to do this. You will need to provide the path to the font files on your computer. That is our next step.

Now, you need to import these fonts into each Quarto document individually ( This website has done that for every document !! ) Think of it as a theme for your document. You will need to provide the path to the font files on your computer. The ../ sequence navigates up one folder level. Adjust the path as needed, to go right from your Quarto document folder up to project root and then down to the fonts folder.

Let’s assume we have gone off to Google Fonts and downloaded the following fonts to our fonts folder: Alegreya,Anton, Roboto Condensed, Schoolbell, Tangerine, and Ibarra Real Nova.

## Clean the slate
systemfonts::clear_local_fonts()
systemfonts::clear_registry()
##
showtext_opts(dpi = 96) # set DPI for showtext
sysfonts::font_add(
  family = "Alegreya",
  regular = "../../../../../../fonts/Alegreya-Regular.ttf",
  bold = "../../../../../../fonts/Alegreya-Bold.ttf",
  italic = "../../../../../../fonts/Alegreya-Italic.ttf",
  bolditalic = "../../../../../../fonts/Alegreya-BoldItalic.ttf"
)

sysfonts::font_add(
  family = "Anton",
  regular = "../../../../../../fonts/Anton-Regular.ttf"
) # Only one style is available

sysfonts::font_add(
  family = "RobotoCondensed",
  regular = "../../../../../../fonts/RobotoCondensed-Regular.ttf",
  bold = "../../../../../../fonts/RobotoCondensed-Bold.ttf",
  italic = "../../../../../../fonts/RobotoCondensed-Italic.ttf",
  bolditalic = "../../../../../../fonts/RobotoCondensed-BoldItalic.ttf"
)

sysfonts::font_add(
  family = "IbarraNova",
  regular = "../../../../../../fonts/IbarraRealNova-Regular.ttf",
  bold = "../../../../../../fonts/IbarraRealNova-Bold.ttf",
  italic = "../../../../../../fonts/IbarraRealNova-Italic.ttf",
  bolditalic = "../../../../../../fonts/IbarraRealNova-BoldItalic.ttf"
)

sysfonts::font_add(
  family = "Tangerine",
  regular = "../../../../../../fonts/Tangerine-Regular.ttf",
  bold = "../../../../../../fonts/Tangerine-Bold.ttf"
) # only these two are available

sysfonts::font_add(
  family = "Schoolbell",
  regular = "../../../../../../fonts/Schoolbell-Regular.ttf"
) # Only regular is available

showtext_auto() # set these fonts as default for the session

Let check of the fonts are now available in the session:

sysfonts::font_families() # check which fonts are available in the session
 [1] "sans"            "serif"           "mono"            "wqy-microhei"   
 [5] "Alegreya"        "Anton"           "RobotoCondensed" "IbarraNova"     
 [9] "Tangerine"       "Schoolbell"     

After running the chunks above in your session, you can check which fonts are available in your session by typing sysfonts::font_families() in your console, as shown above. We see that apart from the R-default sans, serif, and mono fonts, we have added the several fonts to our session.

4 Plot Theme using Desired fonts

Now that we have the fonts downloaded, we can use them in our plots. We will use the theme_xxxx() function to set a default theme for our plots, and then we will modify the theme elements to use our desired fonts. Let us set some ggplot2 theme aspects now!! Here is a handy picture showing ( most of ) the theme-able aspects of a ggplot plot.

For more info, type ?theme in your console.

Rosana Ferrero (@RosanaFerrero) on Twitter Sept 11, 2022
Figure 1: ggplot2 Theme Elements. Source: Rosana Ferrero ((RosanaFerrero?)) on Twitter Sept 11, 2022

So now that we understand the elements of the themes, let us set our ggplot theme:

theme_custom <- function() {
  theme_bw(base_size = 10) +

    theme_sub_axis(
      title = element_text(
        family = "Roboto Condensed",
        size = 8
      ),
      text = element_text(
        family = "Roboto Condensed",
        size = 6
      )
    ) +

    theme_sub_legend(
      text = element_text(
        family = "Roboto Condensed",
        size = 6
      ),
      title = element_text(
        family = "Alegreya",
        size = 8
      )
    ) +

    theme_sub_plot(
      title = element_text(
        family = "Alegreya",
        size = 14, face = "bold"
      ),
      title.position = "plot",
      subtitle = element_text(
        family = "Alegreya",
        size = 10
      ),
      caption = element_text(
        family = "Alegreya",
        size = 6
      ),
      caption.position = "plot"
    )
}

## Set the theme
ggplot2::theme_set(new = theme_custom())

## tinytable options
options("tinytable_tt_digits" = 2)
options("tinytable_format_num_fmt" = "significant_cell")
options(tinytable_html_mathjax = TRUE)


## Set defaults for flextable
flextable::set_flextable_defaults(font.family = "Roboto Condensed")

## Set the theme
ggplot2::theme_set(new = theme_custom())
NoteFonts in ggplot

Using showtext(auto) as shown above allows us to modify the non-graph elements of the ggplot chart: the axes, the title, the legend etc. If we wish to add text with fonts to the body of the chart itself, as with geoms such as textand label annotations , we need to do one more thing: use update_geom_defaults() as shown below:

## Use available fonts in ggplot text and other geoms too!
ggplot2::update_geom_defaults(geom = "text", new = list(
  family = "Roboto Condensed",
  face = "plain",
  size = 3.5,
  color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "label", new = list(
  family = "Roboto Condensed",
  face = "plain",
  size = 3.5,
  color = "#2b2b2b"
))

ggplot2::update_geom_defaults(geom = "marquee", new = list(
  family = "Roboto Condensed",
  face = "plain",
  size = 3.5,
  color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "text_repel", new = list(
  family = "Roboto Condensed",
  face = "plain",
  size = 3.5,
  color = "#2b2b2b"
))
ggplot2::update_geom_defaults(geom = "label_repel", new = list(
  family = "Roboto Condensed",
  face = "plain",
  size = 3.5,
  color = "#2b2b2b"
))

# repeat for any new text-using geom etc.
#

5 Data

We will work with a familiar dataset, so that we can concentrate on the chart aesthetics, without having to spend time getting used to the data: the penguins dataset again, from the palmerpenguins package now part of the R installation!.

As always, we will start with a table of the data:

data(penguins, package = "datasets")
penguins <- penguins %>% drop_na() # remove data containing missing data

## Create a nicely formatted table
## uses `kableExtra` package
##
penguins %>%
  kableExtra::kbl(caption = "Penguins Dataset") %>%
  kableExtra::kable_paper(
    full_width = FALSE,
    bootstrap_options = c("striped", "hover", "condensed", "responsive"),
    position = "center"
  ) %>%
  kableExtra::scroll_box(height = "350px")
Penguins Dataset
species island bill_len bill_dep flipper_len body_mass sex year
Adelie Torgersen 39.1 18.7 181 3750 male 2007
Adelie Torgersen 39.5 17.4 186 3800 female 2007
Adelie Torgersen 40.3 18.0 195 3250 female 2007
Adelie Torgersen 36.7 19.3 193 3450 female 2007
Adelie Torgersen 39.3 20.6 190 3650 male 2007
Adelie Torgersen 38.9 17.8 181 3625 female 2007
Adelie Torgersen 39.2 19.6 195 4675 male 2007
Adelie Torgersen 41.1 17.6 182 3200 female 2007
Adelie Torgersen 38.6 21.2 191 3800 male 2007
Adelie Torgersen 34.6 21.1 198 4400 male 2007
Adelie Torgersen 36.6 17.8 185 3700 female 2007
Adelie Torgersen 38.7 19.0 195 3450 female 2007
Adelie Torgersen 42.5 20.7 197 4500 male 2007
Adelie Torgersen 34.4 18.4 184 3325 female 2007
Adelie Torgersen 46.0 21.5 194 4200 male 2007
Adelie Biscoe 37.8 18.3 174 3400 female 2007
Adelie Biscoe 37.7 18.7 180 3600 male 2007
Adelie Biscoe 35.9 19.2 189 3800 female 2007
Adelie Biscoe 38.2 18.1 185 3950 male 2007
Adelie Biscoe 38.8 17.2 180 3800 male 2007
Adelie Biscoe 35.3 18.9 187 3800 female 2007
Adelie Biscoe 40.6 18.6 183 3550 male 2007
Adelie Biscoe 40.5 17.9 187 3200 female 2007
Adelie Biscoe 37.9 18.6 172 3150 female 2007
Adelie Biscoe 40.5 18.9 180 3950 male 2007
Adelie Dream 39.5 16.7 178 3250 female 2007
Adelie Dream 37.2 18.1 178 3900 male 2007
Adelie Dream 39.5 17.8 188 3300 female 2007
Adelie Dream 40.9 18.9 184 3900 male 2007
Adelie Dream 36.4 17.0 195 3325 female 2007
Adelie Dream 39.2 21.1 196 4150 male 2007
Adelie Dream 38.8 20.0 190 3950 male 2007
Adelie Dream 42.2 18.5 180 3550 female 2007
Adelie Dream 37.6 19.3 181 3300 female 2007
Adelie Dream 39.8 19.1 184 4650 male 2007
Adelie Dream 36.5 18.0 182 3150 female 2007
Adelie Dream 40.8 18.4 195 3900 male 2007
Adelie Dream 36.0 18.5 186 3100 female 2007
Adelie Dream 44.1 19.7 196 4400 male 2007
Adelie Dream 37.0 16.9 185 3000 female 2007
Adelie Dream 39.6 18.8 190 4600 male 2007
Adelie Dream 41.1 19.0 182 3425 male 2007
Adelie Dream 36.0 17.9 190 3450 female 2007
Adelie Dream 42.3 21.2 191 4150 male 2007
Adelie Biscoe 39.6 17.7 186 3500 female 2008
Adelie Biscoe 40.1 18.9 188 4300 male 2008
Adelie Biscoe 35.0 17.9 190 3450 female 2008
Adelie Biscoe 42.0 19.5 200 4050 male 2008
Adelie Biscoe 34.5 18.1 187 2900 female 2008
Adelie Biscoe 41.4 18.6 191 3700 male 2008
Adelie Biscoe 39.0 17.5 186 3550 female 2008
Adelie Biscoe 40.6 18.8 193 3800 male 2008
Adelie Biscoe 36.5 16.6 181 2850 female 2008
Adelie Biscoe 37.6 19.1 194 3750 male 2008
Adelie Biscoe 35.7 16.9 185 3150 female 2008
Adelie Biscoe 41.3 21.1 195 4400 male 2008
Adelie Biscoe 37.6 17.0 185 3600 female 2008
Adelie Biscoe 41.1 18.2 192 4050 male 2008
Adelie Biscoe 36.4 17.1 184 2850 female 2008
Adelie Biscoe 41.6 18.0 192 3950 male 2008
Adelie Biscoe 35.5 16.2 195 3350 female 2008
Adelie Biscoe 41.1 19.1 188 4100 male 2008
Adelie Torgersen 35.9 16.6 190 3050 female 2008
Adelie Torgersen 41.8 19.4 198 4450 male 2008
Adelie Torgersen 33.5 19.0 190 3600 female 2008
Adelie Torgersen 39.7 18.4 190 3900 male 2008
Adelie Torgersen 39.6 17.2 196 3550 female 2008
Adelie Torgersen 45.8 18.9 197 4150 male 2008
Adelie Torgersen 35.5 17.5 190 3700 female 2008
Adelie Torgersen 42.8 18.5 195 4250 male 2008
Adelie Torgersen 40.9 16.8 191 3700 female 2008
Adelie Torgersen 37.2 19.4 184 3900 male 2008
Adelie Torgersen 36.2 16.1 187 3550 female 2008
Adelie Torgersen 42.1 19.1 195 4000 male 2008
Adelie Torgersen 34.6 17.2 189 3200 female 2008
Adelie Torgersen 42.9 17.6 196 4700 male 2008
Adelie Torgersen 36.7 18.8 187 3800 female 2008
Adelie Torgersen 35.1 19.4 193 4200 male 2008
Adelie Dream 37.3 17.8 191 3350 female 2008
Adelie Dream 41.3 20.3 194 3550 male 2008
Adelie Dream 36.3 19.5 190 3800 male 2008
Adelie Dream 36.9 18.6 189 3500 female 2008
Adelie Dream 38.3 19.2 189 3950 male 2008
Adelie Dream 38.9 18.8 190 3600 female 2008
Adelie Dream 35.7 18.0 202 3550 female 2008
Adelie Dream 41.1 18.1 205 4300 male 2008
Adelie Dream 34.0 17.1 185 3400 female 2008
Adelie Dream 39.6 18.1 186 4450 male 2008
Adelie Dream 36.2 17.3 187 3300 female 2008
Adelie Dream 40.8 18.9 208 4300 male 2008
Adelie Dream 38.1 18.6 190 3700 female 2008
Adelie Dream 40.3 18.5 196 4350 male 2008
Adelie Dream 33.1 16.1 178 2900 female 2008
Adelie Dream 43.2 18.5 192 4100 male 2008
Adelie Biscoe 35.0 17.9 192 3725 female 2009
Adelie Biscoe 41.0 20.0 203 4725 male 2009
Adelie Biscoe 37.7 16.0 183 3075 female 2009
Adelie Biscoe 37.8 20.0 190 4250 male 2009
Adelie Biscoe 37.9 18.6 193 2925 female 2009
Adelie Biscoe 39.7 18.9 184 3550 male 2009
Adelie Biscoe 38.6 17.2 199 3750 female 2009
Adelie Biscoe 38.2 20.0 190 3900 male 2009
Adelie Biscoe 38.1 17.0 181 3175 female 2009
Adelie Biscoe 43.2 19.0 197 4775 male 2009
Adelie Biscoe 38.1 16.5 198 3825 female 2009
Adelie Biscoe 45.6 20.3 191 4600 male 2009
Adelie Biscoe 39.7 17.7 193 3200 female 2009
Adelie Biscoe 42.2 19.5 197 4275 male 2009
Adelie Biscoe 39.6 20.7 191 3900 female 2009
Adelie Biscoe 42.7 18.3 196 4075 male 2009
Adelie Torgersen 38.6 17.0 188 2900 female 2009
Adelie Torgersen 37.3 20.5 199 3775 male 2009
Adelie Torgersen 35.7 17.0 189 3350 female 2009
Adelie Torgersen 41.1 18.6 189 3325 male 2009
Adelie Torgersen 36.2 17.2 187 3150 female 2009
Adelie Torgersen 37.7 19.8 198 3500 male 2009
Adelie Torgersen 40.2 17.0 176 3450 female 2009
Adelie Torgersen 41.4 18.5 202 3875 male 2009
Adelie Torgersen 35.2 15.9 186 3050 female 2009
Adelie Torgersen 40.6 19.0 199 4000 male 2009
Adelie Torgersen 38.8 17.6 191 3275 female 2009
Adelie Torgersen 41.5 18.3 195 4300 male 2009
Adelie Torgersen 39.0 17.1 191 3050 female 2009
Adelie Torgersen 44.1 18.0 210 4000 male 2009
Adelie Torgersen 38.5 17.9 190 3325 female 2009
Adelie Torgersen 43.1 19.2 197 3500 male 2009
Adelie Dream 36.8 18.5 193 3500 female 2009
Adelie Dream 37.5 18.5 199 4475 male 2009
Adelie Dream 38.1 17.6 187 3425 female 2009
Adelie Dream 41.1 17.5 190 3900 male 2009
Adelie Dream 35.6 17.5 191 3175 female 2009
Adelie Dream 40.2 20.1 200 3975 male 2009
Adelie Dream 37.0 16.5 185 3400 female 2009
Adelie Dream 39.7 17.9 193 4250 male 2009
Adelie Dream 40.2 17.1 193 3400 female 2009
Adelie Dream 40.6 17.2 187 3475 male 2009
Adelie Dream 32.1 15.5 188 3050 female 2009
Adelie Dream 40.7 17.0 190 3725 male 2009
Adelie Dream 37.3 16.8 192 3000 female 2009
Adelie Dream 39.0 18.7 185 3650 male 2009
Adelie Dream 39.2 18.6 190 4250 male 2009
Adelie Dream 36.6 18.4 184 3475 female 2009
Adelie Dream 36.0 17.8 195 3450 female 2009
Adelie Dream 37.8 18.1 193 3750 male 2009
Adelie Dream 36.0 17.1 187 3700 female 2009
Adelie Dream 41.5 18.5 201 4000 male 2009
Gentoo Biscoe 46.1 13.2 211 4500 female 2007
Gentoo Biscoe 50.0 16.3 230 5700 male 2007
Gentoo Biscoe 48.7 14.1 210 4450 female 2007
Gentoo Biscoe 50.0 15.2 218 5700 male 2007
Gentoo Biscoe 47.6 14.5 215 5400 male 2007
Gentoo Biscoe 46.5 13.5 210 4550 female 2007
Gentoo Biscoe 45.4 14.6 211 4800 female 2007
Gentoo Biscoe 46.7 15.3 219 5200 male 2007
Gentoo Biscoe 43.3 13.4 209 4400 female 2007
Gentoo Biscoe 46.8 15.4 215 5150 male 2007
Gentoo Biscoe 40.9 13.7 214 4650 female 2007
Gentoo Biscoe 49.0 16.1 216 5550 male 2007
Gentoo Biscoe 45.5 13.7 214 4650 female 2007
Gentoo Biscoe 48.4 14.6 213 5850 male 2007
Gentoo Biscoe 45.8 14.6 210 4200 female 2007
Gentoo Biscoe 49.3 15.7 217 5850 male 2007
Gentoo Biscoe 42.0 13.5 210 4150 female 2007
Gentoo Biscoe 49.2 15.2 221 6300 male 2007
Gentoo Biscoe 46.2 14.5 209 4800 female 2007
Gentoo Biscoe 48.7 15.1 222 5350 male 2007
Gentoo Biscoe 50.2 14.3 218 5700 male 2007
Gentoo Biscoe 45.1 14.5 215 5000 female 2007
Gentoo Biscoe 46.5 14.5 213 4400 female 2007
Gentoo Biscoe 46.3 15.8 215 5050 male 2007
Gentoo Biscoe 42.9 13.1 215 5000 female 2007
Gentoo Biscoe 46.1 15.1 215 5100 male 2007
Gentoo Biscoe 47.8 15.0 215 5650 male 2007
Gentoo Biscoe 48.2 14.3 210 4600 female 2007
Gentoo Biscoe 50.0 15.3 220 5550 male 2007
Gentoo Biscoe 47.3 15.3 222 5250 male 2007
Gentoo Biscoe 42.8 14.2 209 4700 female 2007
Gentoo Biscoe 45.1 14.5 207 5050 female 2007
Gentoo Biscoe 59.6 17.0 230 6050 male 2007
Gentoo Biscoe 49.1 14.8 220 5150 female 2008
Gentoo Biscoe 48.4 16.3 220 5400 male 2008
Gentoo Biscoe 42.6 13.7 213 4950 female 2008
Gentoo Biscoe 44.4 17.3 219 5250 male 2008
Gentoo Biscoe 44.0 13.6 208 4350 female 2008
Gentoo Biscoe 48.7 15.7 208 5350 male 2008
Gentoo Biscoe 42.7 13.7 208 3950 female 2008
Gentoo Biscoe 49.6 16.0 225 5700 male 2008
Gentoo Biscoe 45.3 13.7 210 4300 female 2008
Gentoo Biscoe 49.6 15.0 216 4750 male 2008
Gentoo Biscoe 50.5 15.9 222 5550 male 2008
Gentoo Biscoe 43.6 13.9 217 4900 female 2008
Gentoo Biscoe 45.5 13.9 210 4200 female 2008
Gentoo Biscoe 50.5 15.9 225 5400 male 2008
Gentoo Biscoe 44.9 13.3 213 5100 female 2008
Gentoo Biscoe 45.2 15.8 215 5300 male 2008
Gentoo Biscoe 46.6 14.2 210 4850 female 2008
Gentoo Biscoe 48.5 14.1 220 5300 male 2008
Gentoo Biscoe 45.1 14.4 210 4400 female 2008
Gentoo Biscoe 50.1 15.0 225 5000 male 2008
Gentoo Biscoe 46.5 14.4 217 4900 female 2008
Gentoo Biscoe 45.0 15.4 220 5050 male 2008
Gentoo Biscoe 43.8 13.9 208 4300 female 2008
Gentoo Biscoe 45.5 15.0 220 5000 male 2008
Gentoo Biscoe 43.2 14.5 208 4450 female 2008
Gentoo Biscoe 50.4 15.3 224 5550 male 2008
Gentoo Biscoe 45.3 13.8 208 4200 female 2008
Gentoo Biscoe 46.2 14.9 221 5300 male 2008
Gentoo Biscoe 45.7 13.9 214 4400 female 2008
Gentoo Biscoe 54.3 15.7 231 5650 male 2008
Gentoo Biscoe 45.8 14.2 219 4700 female 2008
Gentoo Biscoe 49.8 16.8 230 5700 male 2008
Gentoo Biscoe 49.5 16.2 229 5800 male 2008
Gentoo Biscoe 43.5 14.2 220 4700 female 2008
Gentoo Biscoe 50.7 15.0 223 5550 male 2008
Gentoo Biscoe 47.7 15.0 216 4750 female 2008
Gentoo Biscoe 46.4 15.6 221 5000 male 2008
Gentoo Biscoe 48.2 15.6 221 5100 male 2008
Gentoo Biscoe 46.5 14.8 217 5200 female 2008
Gentoo Biscoe 46.4 15.0 216 4700 female 2008
Gentoo Biscoe 48.6 16.0 230 5800 male 2008
Gentoo Biscoe 47.5 14.2 209 4600 female 2008
Gentoo Biscoe 51.1 16.3 220 6000 male 2008
Gentoo Biscoe 45.2 13.8 215 4750 female 2008
Gentoo Biscoe 45.2 16.4 223 5950 male 2008
Gentoo Biscoe 49.1 14.5 212 4625 female 2009
Gentoo Biscoe 52.5 15.6 221 5450 male 2009
Gentoo Biscoe 47.4 14.6 212 4725 female 2009
Gentoo Biscoe 50.0 15.9 224 5350 male 2009
Gentoo Biscoe 44.9 13.8 212 4750 female 2009
Gentoo Biscoe 50.8 17.3 228 5600 male 2009
Gentoo Biscoe 43.4 14.4 218 4600 female 2009
Gentoo Biscoe 51.3 14.2 218 5300 male 2009
Gentoo Biscoe 47.5 14.0 212 4875 female 2009
Gentoo Biscoe 52.1 17.0 230 5550 male 2009
Gentoo Biscoe 47.5 15.0 218 4950 female 2009
Gentoo Biscoe 52.2 17.1 228 5400 male 2009
Gentoo Biscoe 45.5 14.5 212 4750 female 2009
Gentoo Biscoe 49.5 16.1 224 5650 male 2009
Gentoo Biscoe 44.5 14.7 214 4850 female 2009
Gentoo Biscoe 50.8 15.7 226 5200 male 2009
Gentoo Biscoe 49.4 15.8 216 4925 male 2009
Gentoo Biscoe 46.9 14.6 222 4875 female 2009
Gentoo Biscoe 48.4 14.4 203 4625 female 2009
Gentoo Biscoe 51.1 16.5 225 5250 male 2009
Gentoo Biscoe 48.5 15.0 219 4850 female 2009
Gentoo Biscoe 55.9 17.0 228 5600 male 2009
Gentoo Biscoe 47.2 15.5 215 4975 female 2009
Gentoo Biscoe 49.1 15.0 228 5500 male 2009
Gentoo Biscoe 46.8 16.1 215 5500 male 2009
Gentoo Biscoe 41.7 14.7 210 4700 female 2009
Gentoo Biscoe 53.4 15.8 219 5500 male 2009
Gentoo Biscoe 43.3 14.0 208 4575 female 2009
Gentoo Biscoe 48.1 15.1 209 5500 male 2009
Gentoo Biscoe 50.5 15.2 216 5000 female 2009
Gentoo Biscoe 49.8 15.9 229 5950 male 2009
Gentoo Biscoe 43.5 15.2 213 4650 female 2009
Gentoo Biscoe 51.5 16.3 230 5500 male 2009
Gentoo Biscoe 46.2 14.1 217 4375 female 2009
Gentoo Biscoe 55.1 16.0 230 5850 male 2009
Gentoo Biscoe 48.8 16.2 222 6000 male 2009
Gentoo Biscoe 47.2 13.7 214 4925 female 2009
Gentoo Biscoe 46.8 14.3 215 4850 female 2009
Gentoo Biscoe 50.4 15.7 222 5750 male 2009
Gentoo Biscoe 45.2 14.8 212 5200 female 2009
Gentoo Biscoe 49.9 16.1 213 5400 male 2009
Chinstrap Dream 46.5 17.9 192 3500 female 2007
Chinstrap Dream 50.0 19.5 196 3900 male 2007
Chinstrap Dream 51.3 19.2 193 3650 male 2007
Chinstrap Dream 45.4 18.7 188 3525 female 2007
Chinstrap Dream 52.7 19.8 197 3725 male 2007
Chinstrap Dream 45.2 17.8 198 3950 female 2007
Chinstrap Dream 46.1 18.2 178 3250 female 2007
Chinstrap Dream 51.3 18.2 197 3750 male 2007
Chinstrap Dream 46.0 18.9 195 4150 female 2007
Chinstrap Dream 51.3 19.9 198 3700 male 2007
Chinstrap Dream 46.6 17.8 193 3800 female 2007
Chinstrap Dream 51.7 20.3 194 3775 male 2007
Chinstrap Dream 47.0 17.3 185 3700 female 2007
Chinstrap Dream 52.0 18.1 201 4050 male 2007
Chinstrap Dream 45.9 17.1 190 3575 female 2007
Chinstrap Dream 50.5 19.6 201 4050 male 2007
Chinstrap Dream 50.3 20.0 197 3300 male 2007
Chinstrap Dream 58.0 17.8 181 3700 female 2007
Chinstrap Dream 46.4 18.6 190 3450 female 2007
Chinstrap Dream 49.2 18.2 195 4400 male 2007
Chinstrap Dream 42.4 17.3 181 3600 female 2007
Chinstrap Dream 48.5 17.5 191 3400 male 2007
Chinstrap Dream 43.2 16.6 187 2900 female 2007
Chinstrap Dream 50.6 19.4 193 3800 male 2007
Chinstrap Dream 46.7 17.9 195 3300 female 2007
Chinstrap Dream 52.0 19.0 197 4150 male 2007
Chinstrap Dream 50.5 18.4 200 3400 female 2008
Chinstrap Dream 49.5 19.0 200 3800 male 2008
Chinstrap Dream 46.4 17.8 191 3700 female 2008
Chinstrap Dream 52.8 20.0 205 4550 male 2008
Chinstrap Dream 40.9 16.6 187 3200 female 2008
Chinstrap Dream 54.2 20.8 201 4300 male 2008
Chinstrap Dream 42.5 16.7 187 3350 female 2008
Chinstrap Dream 51.0 18.8 203 4100 male 2008
Chinstrap Dream 49.7 18.6 195 3600 male 2008
Chinstrap Dream 47.5 16.8 199 3900 female 2008
Chinstrap Dream 47.6 18.3 195 3850 female 2008
Chinstrap Dream 52.0 20.7 210 4800 male 2008
Chinstrap Dream 46.9 16.6 192 2700 female 2008
Chinstrap Dream 53.5 19.9 205 4500 male 2008
Chinstrap Dream 49.0 19.5 210 3950 male 2008
Chinstrap Dream 46.2 17.5 187 3650 female 2008
Chinstrap Dream 50.9 19.1 196 3550 male 2008
Chinstrap Dream 45.5 17.0 196 3500 female 2008
Chinstrap Dream 50.9 17.9 196 3675 female 2009
Chinstrap Dream 50.8 18.5 201 4450 male 2009
Chinstrap Dream 50.1 17.9 190 3400 female 2009
Chinstrap Dream 49.0 19.6 212 4300 male 2009
Chinstrap Dream 51.5 18.7 187 3250 male 2009
Chinstrap Dream 49.8 17.3 198 3675 female 2009
Chinstrap Dream 48.1 16.4 199 3325 female 2009
Chinstrap Dream 51.4 19.0 201 3950 male 2009
Chinstrap Dream 45.7 17.3 193 3600 female 2009
Chinstrap Dream 50.7 19.7 203 4050 male 2009
Chinstrap Dream 42.5 17.3 187 3350 female 2009
Chinstrap Dream 52.2 18.8 197 3450 male 2009
Chinstrap Dream 45.2 16.6 191 3250 female 2009
Chinstrap Dream 49.3 19.9 203 4050 male 2009
Chinstrap Dream 50.2 18.8 202 3800 male 2009
Chinstrap Dream 45.6 19.4 194 3525 female 2009
Chinstrap Dream 51.9 19.5 206 3950 male 2009
Chinstrap Dream 46.8 16.5 189 3650 female 2009
Chinstrap Dream 45.7 17.0 195 3650 female 2009
Chinstrap Dream 55.8 19.8 207 4000 male 2009
Chinstrap Dream 43.5 18.1 202 3400 female 2009
Chinstrap Dream 49.6 18.2 193 3775 male 2009
Chinstrap Dream 50.8 19.0 210 4100 male 2009
Chinstrap Dream 50.2 18.7 198 3775 female 2009
Table 1: Penguins Dataset

6 Basic Plot

A basic scatter plot first, which we will decorate with fonts:

## Set the theme
ggplot2::theme_set(new = theme_custom())

p1 <- ggplot(penguins, aes(x = bill_len, y = bill_dep)) +
  geom_point(aes(color = body_mass), alpha = .6, size = 3.5) +

  ## custom colors from the scico package
  scico::scale_colour_scico(palette = "glasgow", direction = -1) +

  ## custom labels
  labs(
    title = "Bill Dimensions of Brush-Tailed Penguins (Pygoscelis)",
    subtitle = "A scatter plot of bill depth versus bill length.",
    caption = "Data: Gorman, Williams & Fraser (2014) PLoS ONE",
    x = "Bill Length (mm)",
    y = "Bill Depth (mm)",
    color = "Body mass (g)"
  )

p1
Figure 2: Scatter plot of bill depth versus bill length, colored by body mass.

We see that the ggplot theme uses the fonts that we have assigned to the different elements in the graph.

7 Using {marquee}

To be written up when I know it better.

8 Using {ggtext}

From Claus Wilke’s website → www.wilkelab.org/ggtext

The ggtext package provides simple Markdown and HTML rendering for ggplot2. Under the hood, the package uses the gridtext package for the actual rendering, and consequently it is limited to the feature set provided by gridtext.
Support is provided for Markdown both in theme elements (plot titles, subtitles, captions, axis labels, legends, etc.) and in geoms (similar to geom_text()). In both cases, there are two alternatives, one for creating simple text labels and one for creating text boxes with word wrapping.

NOTE: on some machines, the ggtext package may not work as expected. In this case, please do as follows, using your Console:

  • remove gridtext: remove.packages(gridtext).
  • Install development version of gridtext: remotes::install_github("wilkelab/gridtext")

8.1 element_markdown()

We can use our familiar markdown syntax right inside the titles and captions of the plot. element_markdown() is a theming command made available by the ggtext package.

element_markdown() → formatted text elements, e.g. titles, caption, axis text, striptext

## Set the theme
ggplot2::theme_set(new = theme_custom())

p1 +

  ## New code starts here: Two Step Procedure with ggtext
  ## 1. Markdown formatting of labels and title, using asterisks
  labs(
    title = "Bill Dimensions of Brush-Tailed Penguins (*Pygoscelis*)",
    subtitle = "A scatter plot of bill depth versus bill length.",
    caption = "Data: Gorman, Williams & Fraser (2014) *PLoS ONE*",
    x = "**Bill Length** (mm)",
    y = "**Bill Depth** (mm)",
    color = "Body mass (g)"
  ) +

  ## 2. Add theme related commands from ggtext
  ## render respective text elements
  theme(
    plot.title = ggtext::element_markdown(),
    plot.caption = ggtext::element_markdown(),
    axis.title.x = ggtext::element_markdown(),
    axis.title.y = ggtext::element_markdown()
  )

8.2 element_markdown() in combination with HTML

This allows us to change fonts and font-effects in titles, labels, and captions:

## use HTML syntax to change text color
p1 +
  labs(title = 'Bill Dimensions of Brush-Tailed Penguins <i style="color:#28A87D;">Pygoscelis</i>') +
  theme(
    plot.title = ggtext::element_markdown(),
    plot.caption = ggtext::element_markdown(),
    axis.title.x = ggtext::element_markdown(),
    axis.title.y = ggtext::element_markdown(),
    plot.margin = margin(t = 10, r = 10, b = 10, l = 10)
  )

## use HTML syntax to change font and text size
##
p1 +
  labs(title = 'Bill Dimensions of Brush-Tailed Penguins <b style="font-size:32pt;font-family:Tangerine;">Pygoscelis</b>') +
  theme(
    plot.title = ggtext::element_markdown(),
    plot.caption = ggtext::element_markdown(),
    axis.title.x = ggtext::element_markdown(),
    axis.title.y = ggtext::element_markdown(),
    plot.margin = margin(t = 10, r = 10, b = 10, l = 10)
  )

9 Wait, but Why?

  • Using appropriate fonts in our plots can make them more readable and visually appealing.
  • They may be mandated for publication in some journals, and for publications by organizations.
  • Using sysfonts , gfonts, and showtext allows us to use a wide variety of fonts from Google, making it easy to customize our plots.
  • Using ggtext allows us to add formatted text elements to our plots, making them more informative and visually appealing.
  • Note that downloading fonts from Google may not be GDPR compliant, so it is better to use locally installed fonts if possible.
  • gfonts allows us to programmatically download Google fonts a priori, and use them locally, making our websites GDPR compliant.

10 Conclusions

In this module, we have learned how to use custom fonts in our ggplot2 plots using the showtext package. We have also seen how to use the ggtext package to add markdown-formatted text elements to our plots.

11 References

  1. Thomas Lin Perdersen. https://www.tidyverse.org/blog/2025/05/fonts-in-r/
  2. Winston Chang. R Cookbook (2nd Edition). O’Reilly Media, 2019. http://www.cookbook-r.com/Graphs/Fonts/
R Package Citations
Package Version Citation
scico 1.5.0 Pedersen and Crameri (2023)
showtext 0.9.7 Qiu and See file AUTHORS for details. (2024b)
sysfonts 0.8.9 Qiu and See file AUTHORS for details. (2024a)
Pedersen, Thomas Lin, and Fabio Crameri. 2023. scico: Colour Palettes Based on the Scientific Colour-Maps. https://doi.org/10.32614/CRAN.package.scico.
Qiu, Yixuan, and authors/contributors of the included fonts. See file AUTHORS for details. 2024a. sysfonts: Loading Fonts into r. https://doi.org/10.32614/CRAN.package.sysfonts.
Qiu, Yixuan, and authors/contributors of the included software. See file AUTHORS for details. 2024b. showtext: Using Fonts More Easily in r Graphs. https://doi.org/10.32614/CRAN.package.showtext.
Back to top
Colours
Annotating Plots: Text, Labels, and Boxes

License: CC BY-SA 2.0

Website made with ❤️ and Quarto, by Arvind V.

Hosted by Netlify .