Themes and Styling
Themes control everything that is not data — fonts, gridlines, backgrounds, legend placement — through a single, inheritance-based system.
A theme controls every part of a plot that is not tied to the data: the background color, the gridlines, the fonts, the legend position, the spacing. Crucially, changing the theme cannot change what the plot means — it only changes how it looks. That clean separation is itself a grammar idea.
Data ink vs. non-data ink
Every plot is made of two kinds of "ink":
- Data ink — the marks that encode data (points, bars, lines). Controlled by geoms, mappings, and scales.
- Non-data ink — axes, gridlines, background, labels, legend styling. Controlled by the theme.
The theme owns the entire right branch. You can hand the same data plot to ten different themes and get ten different looks with identical meaning.
Complete themes: instant restyling
ggplot2 ships complete themes that restyle everything at once. Compare the default grey theme with a few alternatives:
One function call, the whole appearance changes, the data untouched.
Other built-ins include theme_bw(), theme_light(), and
theme_void() (which removes all non-data ink — handy for maps).
Fine control with theme()
For surgical tweaks, theme() exposes hundreds of individual
elements. You target a named element and set it with an
element_*() helper:
element_text()— text (size, color, face, angle)element_line()— lines (gridlines, ticks, axis lines)element_rect()— rectangles (backgrounds, legend boxes)element_blank()— remove the element entirely
Read each line: move the legend to the top, delete the minor gridlines, and bold the axis titles. Each targets one named piece of non-data ink.
Theme inheritance
This is the conceptual heart of the theme system, and it explains why small theme calls have wide effects. Theme elements form an inheritance hierarchy: general elements pass their settings down to more specific ones, unless the specific one overrides them.
Set the root text element's font once, and every text element
inherits it — titles, axis labels, legend text — unless you override a
specific one:
Every label turned navy and grew, from a single root-level setting. That is inheritance: change the parent, and the children follow unless they say otherwise.
Why inheritance matters
Inheritance is what lets theme_minimal(base_size = 16) resize an
entire plot's text proportionally with one number. Without
inheritance you would set the size of every text element by hand — the
same drudgery the grammar removed from drawing. The theme system
applies the grammar's "describe once, propagate everywhere" philosophy
to styling.
Which of these does a theme control?
Which column is mapped to the x-axis.
The heights of the bars in a bar chart.
Non-data elements such as the panel background, gridlines, fonts, and legend position.
The statistical transformation applied to the data.
You set theme(text = element_text(color = "navy")) and all text — titles, axis labels, legend — turns navy. Why does one setting affect so many elements?
Because text is a special keyword that recolors the whole image.
Because ggplot2 ignores element-specific settings.
Theme elements inherit from more general ones, and text is the root text element, so every specific text element inherits its color unless it overrides it.
Because element_text always applies to every element type.
How do you completely remove the minor gridlines from a plot?
theme(panel.grid.minor = "none").
scale_y_continuous(minor_breaks = element_blank()).
theme(panel.grid.minor = element_blank()).
geom_blank().
Key takeaways
- A theme controls non-data ink — background, gridlines, fonts, legend position — never the data's meaning.
- Complete themes (
theme_minimal(),theme_classic(), ...) restyle everything in one call. theme()pluselement_text/line/rect/blank()give per-element control;element_blank()removes an element.- Theme elements inherit from general to specific, so one root
setting (like
base_size) can restyle the whole plot.
Small Multiples with Facets
Faceting splits one plot into a grid of panels by a variable — why shared scales make small multiples so powerful, and facet_wrap vs facet_grid.
Labels, Titles, and Annotations
Turning a correct chart into a communicative one — labs(), titles, direct annotations, and reference lines that guide the reader's eye.