Skip to main content
v2026.11,858 entries · CC-BY 4.0
LAC HealthMedical & Research SuppliesReagents, PPE & instruments — chain-of-custody documented.Fast, traceable sourcing built for regulated research environments, from bench consumables to instrumentation.Shop lac.us CodeCASRAIlac.us

ggplot Themes: Built-in, theme(), and Global Defaults

How ggplot2 themes work: the nine built-in themes, theme() tweaks for one plot, and theme_set, theme_update and theme_replace for global defaults.

Written and maintained by CASRAI Editorial Board

Last updated

A ggplot2 theme controls everything on a plot that is not data: background, gridlines, axis lines, text, legend position. ggplot2 ships nine complete themes, theme() adjusts individual elements of one plot, and theme_set() changes the default for every plot you draw afterwards. The difference between those last two, and the exact difference between theme_update() and theme_replace(), is where most confusion comes from, so this guide leads with it.

What ggplot themes are used for in research

Themes make a figure fit its destination: a journal column, a slide, a poster. Because the theme is separate from the data layers, you can restyle a whole figure without touching the analysis code, and a lab can keep one theme definition so every figure looks consistent. For plotting basics see ggplots in R; this page covers only the styling layer. If a figure goes into a manuscript, pair it with a proper figure legend.

Install or access

ggplot2 is distributed through CRAN and documented at ggplot2.tidyverse.org. Install and load it from R:

install.packages("ggplot2")
library(ggplot2)

The extra theme collection ggthemes is optional. The CRAN page describes it as “Extra Themes, Scales and Geoms for ‘ggplot2′”; version 7.0.0 was published 2026-10-03 under GPL-2 and requires R (>= 4.1.0) and ggplot2 (>= 3.5.2). Install it with install.packages("ggthemes") only if the built-in themes are not enough. Cite the packages you use; see how to cite software, code and R packages.

Step-by-step: choose, tweak and set a theme

1. Pick a complete theme

Add a complete theme to a plot with +. Assuming your plot is stored as p:

p + theme_bw()

The ggplot2 reference lists these complete themes, all sharing the same arguments, theme_grey(base_size = 11, base_family = "", header_family = NULL, base_line_size = base_size/22, base_rect_size = base_size/22, ink = "black", paper = "white", accent = "#3366FF"):

Function What the reference says
theme_grey() / theme_gray() The default: grey background with white gridlines, designed so the data stands out.
theme_bw() Dark-on-light variation of the default; may work better for presentations displayed with a projector.
theme_linedraw() Only black lines of various widths on white. Includes some very thin lines (much less than 1 pt) which some journals may refuse.
theme_light() Similar to theme_linedraw() but with light grey lines and axes, directing attention to the data.
theme_dark() The dark version of theme_light(); can make thin coloured lines stand out.
theme_minimal() No background annotations.
theme_classic() Axis lines for x and y, no gridlines.
theme_void() A completely empty theme; its paper default is transparent.
theme_test() For visual unit tests of ggplot2 itself; not intended for figures.

The header_family argument sets the font family for axis titles, legend titles, the plot title and the tag; when NULL they inherit base_family. Source: ggplot2 reference, complete themes (checked 2026-10-29).

2. Tweak elements with theme()

Use theme() to change individual elements of the plot in front of you. Each element has a matching constructor: element_line() for lines, element_rect() for rectangles, element_text() for text, and element_blank() to remove an element. Examples taken from the ggplot2 reference:

p + theme(plot.title = element_text(size = rel(2)))
p + theme(plot.background = element_rect(fill = "green"))
p + theme(panel.grid.major = element_line(colour = "black"))
p + theme(legend.position = "bottom")
p + theme(strip.text.x = element_text(colour = "white", face = "bold"))

Elements inherit from more general ones. The reference’s own example: axis.title.x.bottom inherits from axis.title.x, which inherits from axis.title, which inherits from text. Likewise panel.grid inherits from line, and plot.title inherits from title and is left-aligned by default. Practical consequence: setting one high-level element such as text restyles many elements at once, while setting a specific one overrides only that element.

3. Set a theme for every plot

A plot-level + theme_bw() affects one plot. The active theme, by contrast, is applied automatically to every plot you draw. Replace it with theme_set() (also available as set_theme()), which returns the previous theme invisibly so you can restore it:

old <- theme_set(theme_bw())
p
theme_set(old)

Calling theme_set() with no argument resets the active theme to theme_grey(). Use theme_get() to inspect what is currently active.

4. Change part of the global theme

Two functions modify the active theme instead of replacing it, and they differ in an important way:

Function How it combines Unspecified settings
theme_update() Uses + Keep their existing values
theme_replace() Uses %+replace% Become NULL

The reference example: theme_update(panel.grid.minor = element_line(colour = "red")). Both also invisibly return the previous theme. Source: ggplot2 reference, theme_get (checked 2026-10-29).

5. Build one reusable lab theme

To keep figures consistent across a project, combine a complete theme with your tweaks in one function and add it to every plot, or pass it to theme_set() once at the top of a script:

theme_lab <- function() {
  theme_bw(base_size = 12) +
    theme(legend.position = "bottom")
}
p + theme_lab()

Putting the theme in a script that is kept with the analysis is also a small reproducibility gain; see computational reproducibility.

Output and how to read it

A theme never changes the data mapping, scales or statistics: if a plot looks different after adding a theme, only non-data elements moved. To confirm what a theme changed, compare the plot with and without it. For journal submission, check the journal’s figure instructions for minimum line weight before using theme_linedraw(), since the reference warns about very thin lines. theme_void() removes axes entirely, so it suits maps or diagrams but not a plot a reader must read values from. Related plot-specific guides: box plots in R, histograms in R, scatterplots in R.

Troubleshooting

My theme() changes disappeared

A complete theme replaces the whole theme, so a complete theme added after your theme() call resets those tweaks. Put the complete theme first and your theme() adjustments after it: p + theme_bw() + theme(legend.position = "bottom").

Every plot suddenly looks different

An earlier theme_set(), theme_update() or theme_replace() in the session changed the active theme. Run theme_set() with no argument to return to theme_grey(), or restore the object you saved from the earlier call.

Elements went missing after theme_replace()

Because %+replace% turns unspecified values in the element into NULL, replacing a partly specified element can drop settings you expected to keep. Use theme_update() to keep them.

Free alternatives

Option What it is Source
ggplot2 built-in themes The nine complete themes above; no extra package. ggplot2 reference
ggthemes 7.0.0 “Extra Themes, Scales and Geoms for ‘ggplot2′”; GPL-2; needs R (>= 4.1.0). CRAN package page

FAQ

What is the default ggplot theme?

theme_grey(), with a grey panel background and white gridlines.

What is the difference between theme() and theme_set()?

theme() added with + changes only that plot. theme_set() changes the active theme applied to every plot drawn afterwards.

How do I remove gridlines or a legend?

Set the element to element_blank(), for example theme(panel.grid = element_blank()), or set legend.position = "none".

Which theme is best for a journal figure?

The documentation does not name one. It notes that theme_bw() may suit projected presentations and that very thin lines in theme_linedraw() may be refused by some journals; follow the target journal’s figure guidelines.

Sources

Follow CASRAI

Research-administration guidance, standards updates and independent tool reviews.

Ask CASRAI · free to try

Ask about ggplot Themes: Built-in, theme(), and Global Defaults

Ask your first 2 questions free below. Subscribers get 150 a day for $29 a month.

An AI assistant specialized in research administration. It cites the sources behind every answer, labels web answers and says when it can't answer.

Answers draw on CASRAI's guides and dictionary plus the federal and funder documents we index: Federal Register, Grants.gov, Regulations.gov and UKRI.

Works on this site and inside Claude, Cursor and the AI tools you already use.

Everything CASRAI publishes — this page, the dictionary, the guides and the news — stays free to read, with no account and no card.

Referenced across the research world

University of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logoUniversity of Cambridge logoColumbia University logoCrossref logoUniversity of Edinburgh logoHarvard University logoUniversity of Oxford logoPrinceton University logoStanford School of Medicine logoUniversity College London logoORCID logo
  • University of Cambridge logo
  • Columbia University logo
  • Crossref logo
  • University of Edinburgh logo
  • Harvard University logo
  • University of Oxford logo
  • Princeton University logo
  • Stanford School of Medicine logo
  • University College London logo
  • ORCID logo

View CASRAI adoption →