Skip to contents

Overview

ggguides provides styling functions to customize legend appearance without diving into ggplot2’s theme element hierarchy. The main functions are:

Font Styling

Font Size

Adjust the overall text size (applies to both title and labels):

p <- ggplot(mtcars, aes(mpg, wt, color = factor(cyl))) +
  geom_point(size = 3) +
  labs(color = "Cylinders")

p + ggtitle("Default size")
p + legend_style(size = 14) + ggtitle("size = 14")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Default size
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 size = 14

Font Family

Change the font family for legend text:

p + legend_style(family = "serif") + ggtitle("serif")
p + legend_style(family = "mono") + ggtitle("mono")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 serif
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 mono

Title Emphasis

Make the title stand out with separate size and face settings:

p + legend_style(
  size = 12,
  title_size = 14,
  title_face = "bold"
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Text Rotation

For legends with long category names, rotate the labels to save space:

Basic Rotation

p_long <- ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point()

p_long + legend_style(angle = 45)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv

Vertical Labels

Use 90 degrees for fully vertical text. Key height is automatically adjusted to prevent label overlap:

p_long + legend_style(angle = 90)
#> legend_auto_fit: Legend (16.3cm) exceeds 95% of panel (11.4cm). Wrapping to 4 rows.
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv

Title Rotation

Rotate the legend title independently:

p_long + legend_style(title_angle = 90, title_hjust = 0.5) + ggtitle("Rotated title only")
p_long + legend_style(angle = 45, title_angle = 90) + ggtitle("Both rotated")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv Rotated title only
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv Both rotated

Background and Border

Add visual containers around the legend:

p + legend_style(
  background = "#FFF3E0"
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8
p + legend_style(
  background = "#FFF3E0",
  background_color = "#FF9800"
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Key Size

Adjust the size of legend keys (color swatches):

p + legend_style(
  key_width = 1.5,
  key_height = 1.5
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Margin

Control spacing around the legend:

p + legend_style(
  background = "#FFF3E0",
  margin = 0.5
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Full Styling Example

Combine all styling options:

p + legend_style(
  size = 11,
  title_size = 13,
  title_face = "bold",
  family = "sans",
  key_width = 1.2,
  background = "#FFF3E0",
  background_color = "#FF9800",
  margin = 0.3
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Wrapping Legend Entries

For legends with many entries, legend_wrap() creates multi-column or multi-row layouts.

By Columns

ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point() +
  legend_wrap(ncol = 2)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv

By Rows

ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point() +
  legend_wrap(nrow = 2)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv

With Bottom Position

Wrapping works well with horizontal legends:

ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point() +
  legend_wrap(nrow = 2) +
  legend_bottom()
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv

Customizing Legend Keys

When plot aesthetics like small point sizes or low alpha values make legend keys hard to read, legend_keys() overrides the key appearance without affecting the plot.

Enlarging Small Points

p_small <- ggplot(mtcars, aes(mpg, wt, color = factor(cyl))) +
  geom_point(size = 1) +
  labs(color = "Cylinders")

p_small + ggtitle("Small points in legend")
p_small + legend_keys(size = 4) + ggtitle("Enlarged legend keys")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Small points in legend
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Enlarged legend keys

Removing Transparency

p_alpha <- ggplot(mtcars, aes(mpg, wt, color = factor(cyl))) +
  geom_point(alpha = 0.3, size = 3) +
  labs(color = "Cylinders")

p_alpha + ggtitle("Transparent legend keys")
p_alpha + legend_keys(alpha = 1) + ggtitle("Opaque legend keys")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Transparent legend keys
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Opaque legend keys

Combining Overrides

ggplot(mtcars, aes(mpg, wt, color = factor(cyl))) +
  geom_point(alpha = 0.3, size = 1) +
  legend_keys(size = 4, alpha = 1)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> factor(cyl) fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Targeting Specific Aesthetics

By default, legend_keys() applies to both colour and fill legends. Target specific aesthetics with the aesthetic parameter:

ggplot(mtcars, aes(factor(cyl), mpg, fill = factor(cyl))) +
  geom_boxplot(alpha = 0.5) +
  legend_keys(alpha = 1, aesthetic = "fill")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 10 15 20 25 30 35 4 6 8 factor(cyl) mpg fill: #F5F6F8;' /> fill: #F5F6F8;' /> factor(cyl) fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8

Changing Symbol Shapes

Use named shapes for clarity instead of numeric codes:

p + legend_keys(shape = "square") + ggtitle("Square")
p + legend_keys(shape = "diamond") + ggtitle("Diamond")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Square
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Diamond

Available shape names include: "circle", "square", "diamond", "triangle", "plus", "cross", "asterisk".

Filled Shapes with Outlines

Shapes 21-25 (or names ending in _filled) support both outline and fill colors, making legends more visible against any background:

# White fill with colored outline - works with color mapping only
p + legend_keys(shape = "circle_filled", fill = "white", stroke = 1.5) +
  ggtitle("White fill, colored outline")

# Colored fill with black outline - requires mapping BOTH color and fill
ggplot(mtcars, aes(mpg, wt, color = factor(cyl), fill = factor(cyl))) +
  geom_point(size = 3, shape = 21, stroke = 1) +
  legend_keys(colour = "black", stroke = 1) +
  ggtitle("Colored fill, black outline")
#> Warning: Duplicated `override.aes` is ignored.
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 White fill, colored outline
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> factor(cyl) fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Colored fill, black outline

Note: For colored fills with a custom outline, you must map both color and fill in the plot aesthetics. This is a ggplot2 limitation—override.aes can only set static values, it cannot make fill inherit from color.

Shape types:

Type Shapes Fill from Outline from
Outline only "circle_open", "square_open", "diamond_open" N/A colour
Solid filled "circle", "square", "diamond" colour N/A
Fill + outline "circle_filled", "square_filled", "diamond_filled" fill colour

Reordering Legend Entries

legend_order() changes the order of legend entries without modifying factor levels in your data.

Explicit Order

Specify the exact order you want:

p + legend_order(c("8", "6", "4"))
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 8 6 4

Using Functions

Apply functions like rev or sort to the current order:

p + legend_order(rev) + ggtitle("Reversed")
p + legend_order(sort) + ggtitle("Sorted")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 8 6 4 Reversed
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 4 6 8 Sorted

Other Aesthetics

Reorder legends for fill, shape, or other aesthetics:

ggplot(mtcars, aes(factor(cyl), fill = factor(cyl))) +
  geom_bar() +
  legend_order(c("8", "4", "6"), aesthetic = "fill")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 0 5 10 4 6 8 factor(cyl) count fill: #F5F6F8;' /> fill: #F5F6F8;' /> factor(cyl) fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 8 4 6

Reversing Legend Order

For simple reversal, legend_reverse() is a convenient shorthand:

fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 10 15 20 25 30 35 mpg wt fill: #F5F6F8;' /> fill: #F5F6F8;' /> Cylinders fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 8 6 4

Combining Style Functions

All ggguides functions compose with +:

ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point() +
  legend_left() +
  legend_style(
    size = 11,
    title_face = "bold",
    background = "#FFF3E0"
  )
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv
ggplot(mpg, aes(displ, hwy, color = class)) +
  geom_point() +
  legend_wrap(ncol = 2) +
  legend_bottom() +
  legend_style(size = 10, title_face = "bold")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 20 30 40 2 3 4 5 6 7 displ hwy fill: #F5F6F8;' /> fill: #F5F6F8;' /> class fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2seater compact midsize minivan pickup subcompact suv

Styling Continuous Color Bars

For continuous scales, colorbar_style() customizes the color bar appearance.

Basic Usage

p_cont <- ggplot(faithfuld, aes(waiting, eruptions, fill = density)) +
  geom_tile()

p_cont
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03

Size Adjustments

Create taller, thinner bars:

p_cont + colorbar_style(width = 0.5, height = 10, aesthetic = "fill")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03

Horizontal Orientation

p_cont + colorbar_style(width = 10, height = 0.5, direction = "horizontal", aesthetic = "fill") +
  legend_bottom()
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03

### Adding a Frame

p_cont + colorbar_style(frame = TRUE, aesthetic = "fill") + ggtitle("Black frame")
p_cont + colorbar_style(frame = "#FF9800", aesthetic = "fill") + ggtitle("Orange frame")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03 Black frame
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03 Orange frame

Removing Ticks

p_cont + colorbar_style(ticks = FALSE, frame = "#FF9800", aesthetic = "fill")
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03

Combined Customization

p_cont + colorbar_style(
  width = 0.5,
  height = 8,
  frame = "#E65100",
  ticks_length = 0.3,
  aesthetic = "fill"
)
fill: #F5F6F8;' /> fill: #F5F6F8;' /> 2 3 4 5 40 50 60 70 80 90 waiting eruptions fill: #F5F6F8;' /> fill: #F5F6F8;' /> density 0.01 0.02 0.03

Summary

Function Purpose Key Parameters
legend_style() Comprehensive styling size, title_size, title_face, family, angle, background, margin
legend_keys() Override key appearance size, alpha, shape, fill, colour, stroke, aesthetic
legend_order() Reorder entries order (vector or function), aesthetic
legend_wrap() Multi-column layout ncol, nrow
legend_reverse() Reverse entry order None
colorbar_style() Continuous color bar width, height, frame, ticks, direction

Learn more: