Also has a "dark" / "modern" version for the new RStudio theme

  base_family = "Arial Narrow",
  base_size = 11.5,
  plot_title_family = base_family,
  plot_title_size = 18,
  plot_title_face = "bold",
  plot_title_margin = 10,
  subtitle_family = base_family,
  subtitle_size = 12,
  subtitle_face = "plain",
  subtitle_margin = 15,
  strip_text_family = base_family,
  strip_text_size = 12,
  strip_text_face = "plain",
  caption_family = base_family,
  caption_size = 9,
  caption_face = "italic",
  caption_margin = 10,
  axis_text_size = base_size,
  axis_title_family = subtitle_family,
  axis_title_size = 9,
  axis_title_face = "plain",
  axis_title_just = "rt",
  plot_margin = margin(30, 30, 30, 30),
  grid_col = "#cccccc",
  grid = TRUE,
  axis_col = "#cccccc",
  axis = FALSE,
  ticks = FALSE


base_family, base_size

base font family and size

plot_title_family, plot_title_face, plot_title_size, plot_title_margin

plot title family, face, size and margi

subtitle_family, subtitle_face, subtitle_size

plot subtitle family, face and size


plot subtitle margin bottom (single numeric value)

strip_text_family, strip_text_face, strip_text_size

facet label font family, face and size

caption_family, caption_face, caption_size, caption_margin

plot caption family, face, size and margin


font size of axis text

axis_title_family, axis_title_face, axis_title_size

axis title font family, face and size


axis title font justification, one of [blmcrt]


plot margin (specify with ggplot2::margin())

grid_col, axis_col

grid & axis colors; both default to #cccccc


panel grid (TRUE, FALSE, or a combination of X, x, Y, y)


add x or y axes? TRUE, FALSE, "xy"


ticks if TRUE add ticks

Why Arial Narrow?

First and foremost, Arial Narrow is generally installed by default or readily available on any modern system, so it's "free"-ish; plus, it is a condensed font with solid default kerning pairs and geometric numbers.

Building upon theme_ipsum

The function is setup in such a way that you can customize your own one by just wrapping the call and changing the parameters. See source for examples.


There are distinctions between font names and various devices. Names that work for display graphics devices and bitmap ones such as png may not work well for PostScript or PDF ones. You may need two versions of a font-based theme function for them to work in a particular situation. This situation usually only arises when using a newer font with many weights but somewhat irregular internal font name patterns.

There is an option hrbrthemes.loadfonts which -- if set to TRUE -- will call extrafont::loadfonts() to register non-core fonts with R PDF & PostScript devices. If you are running under Windows, the package calls the same function to register non-core fonts with the Windows graphics device.


if (FALSE) {

# seminal scatterplot
ggplot(mtcars, aes(mpg, wt)) +
  geom_point() +
  labs(x="Fuel efficiency (mpg)", y="Weight (tons)",
       title="Seminal ggplot2 scatterplot example",
       subtitle="A plot that is only useful for demonstration purposes",
       caption="Brought to you by the letter 'g'") +

# seminal bar chart


count(mpg, class) %>%
  ggplot(aes(class, n)) +
  geom_col() +
  geom_text(aes(label=n), nudge_y=3) +
  labs(x="Fuel efficiency (mpg)", y="Weight (tons)",
       title="Seminal ggplot2 bar chart example",
       subtitle="A plot that is only useful for demonstration purposes",
       caption="Brought to you by the letter 'g'") +
  theme_ipsum(grid="Y") +