---
title: "Styling with `theme()`, `element_text()`, and `guides()`"
format: html
---

Recall, that ggplot2 graphics are built in layers.  The first layer is the data and the mapping of data to aesthetics.  The second layer is the scales and guides that control how the data-mapped aesthetics are displayed.  The third layer is the theme, which controls the non-data ink on the canvas.

# Layers in ggplot2

Data Mapping (aes)   ───►  What data is plotted and mapped

Scales / Guides      ───►  How data-mapped aesthetics translate and display

Themes / Elements    ───►  The canvas styling (non-data ink)

This document focuses on the third layer, the theme, and how to control it with `theme()`, `element_text()`, and `guides()`.

## 1. `theme()`

`theme()` controls all non-data visual elements of the plot: it never touches data points, lines, bars, or coordinates, and instead styles the frame, grid lines, panel backgrounds, margins, and legend positioning.

Rule of thumb: if a visual property is derived directly from data values (e.g., coloring points by vehicle class), it belongs in `aes()` or `scale_*()`. If it's a fixed stylistic choice across the whole plot (e.g., background color, legend position), it belongs in `theme()`.

## 2. `element_text()`

Inside `theme()`, text elements (titles, subtitles, axis labels, tick marks, legend titles) can't take raw strings or plain numbers — ggplot2 uses constructor functions to define their appearance. `element_text()` handles typography.

Related constructors:

* `element_text()`: typography and font styling
* `element_rect()`: borders, fills, and backgrounds
* `element_line()`: grid lines and axis tick marks
* `element_blank()`: removes the element completely

Key arguments to `element_text()`:

| Argument | Description | Values / Examples |
| :--- | :--- | :--- |
| `face` | Font style/weight | `"bold"`, `"italic"`, `"plain"` |
| `size` | Text size in points | Numeric (e.g., `12`, `14`) |
| `color` | Font color | Hex codes (`"#2b2b2b"`) or names (`"gray30"`) |
| `angle` | Text rotation | Degrees (`0` to `360`, e.g., `45` for crowded x-axes) |
| `hjust` / `vjust` | Horizontal / vertical alignment | `0` (left/bottom), `0.5` (center), `1` (right/top) |
| `family` | Font family/typeface | `"sans"`, `"serif"`, `"mono"`, or custom fonts |

```r

theme(
  plot.title   = element_text(face = "bold", size = 16, hjust = 0),
  axis.text.x  = element_text(angle = 45, hjust = 1, size = 10)
)
```
An alternative to this is the somewhat more modern:

```r
# Automatically handles angle, hjust, and vjust for you
scale_x_discrete(guide = guide_axis(angle = 45))

# Or avoid tilting entirely by staggering labels into two rows:
scale_x_discrete(guide = guide_axis(n.dodge = 2))

```

Dodging `(n.dodge = 2)` is often preferred in publication graphics over angled text because horizontal text is significantly easier to read.

Note the use of `guide_axis()` here, which is a specialized guide for discrete axes.  It is a more modern alternative to `element_text()` for controlling axis text.

## 3. `guides()`

While `theme()` manages non-data ink, `guides()` controls how legends and colorbars behave, wrap, and render.

The distinction:

* `theme(legend.position = "bottom")` controls where the legend container sits on the canvas.
* `guides(color = guide_legend(nrow = 2))` controls how the keys inside that legend are laid out.
* `guides(fill = "none")` removes a specific legend entirely without dropping the aesthetic mapping.

Common use cases:

* Wrapping long discrete legends into multiple rows/columns with `guide_legend(nrow = 2)`.
* Fixing point visibility in the legend (`override.aes`): if points are drawn with low opacity (`alpha = 0.3`) or small size (`size = 1`), they can be hard to see in the legend key. `override.aes` adjusts the legend keys without changing the plot data.
* Shaping continuous colorbars with `guide_colorbar(barwidth = unit(12, "lines"))`.

Reference:

| Function | Scope | Question it answers | Example |
| :--- | :--- | :--- | :--- |
| `theme()` | Canvas / frame | Where is this non-data element placed or styled? | Moving the legend box, dropping grid lines |
| `element_text()` | Typography | How should this specific label look? | Rotating tick labels, bolding titles |
| `guides()` | Legend keys | How should the legend contents be arranged? | Stacking legend keys into 2 rows, boosting legend alpha |
