Question
I am creating a figure containing about 20 plotted data series. I want to place the legend outside the plot area, on the right side, without reducing the size of the axes.
Can I position the legend outside the axes and reduce the font size of the legend text so that the legend requires less space?
Short Answer
You will learn how Matplotlib positions legends, how to anchor a legend outside an axes, and how to make a large legend more compact with options such as fontsize, ncol, and spacing settings. You will also learn how to save an external legend without clipping it or shrinking the plotted area.
Concept
A Matplotlib legend is an artist that describes plotted objects with labels, usually lines, markers, or bars. By default, calling ax.legend() places it inside the axes.
To move a legend outside the plotted rectangle, use two arguments together:
loc: chooses the point on the legend box to use as an anchor.bbox_to_anchor: supplies the destination coordinates for that anchor point.
For example, loc="upper left" and bbox_to_anchor=(1.02, 1) mean: place the legend's upper-left corner just to the right of the axes' upper-right area.
A legend outside the axes still needs space on the figure canvas. You can choose between two common approaches:
- Keep the axes position unchanged and save with
bbox_inches="tight". The exported image expands its bounding box to include the external legend. - Reserve space in the figure layout. This prevents overlap or clipping in an interactive window, but it usually reduces the available axes area unless you make the overall figure wider.
For many legend entries, decreasing fontsize is useful, but it can make labels hard to read. A multi-column legend and smaller spacing often improve compactness more effectively.
Mental Model
Think of the axes as a framed photograph and the legend as a caption card.
- By default, Matplotlib puts the caption card on top of the photograph.
locchooses which corner of the card you hold.bbox_to_anchortells you where to place that held corner.
If you place the card beyond the photograph's frame, the overall page must either become wider or be cropped carefully when it is exported. Reducing fontsize makes the card smaller, but it does not create unlimited room.
Syntax and Examples
Use bbox_to_anchor with loc to place a legend on the right side of an axes:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(8, 4))
ax.plot([1, 2, 3], [2, 4, 3], label="Sales")
ax.plot([1, 2, 3], [1, 3, 5], label="Profit")
ax.legend(
loc="upper left",
bbox_to_anchor=(1.02, 1),
fontsize=8
)
ax.set_xlabel("Month")
ax.set_ylabel("Amount")
plt.show()
bbox_to_anchor=(1.02, 1) uses axes-relative coordinates by default:
0, 0is the lower-left of the axes.1, 1is the upper-right of the axes.1.02, 1is slightly to the right of the upper-right corner.
For a legend with many labels, use columns and compact spacing:
Step by Step Execution
Consider this code:
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(7, 4))
line_a, = ax.plot([0, 1, 2], [1, 2, 1], label="Experiment A")
line_b, = ax.plot([0, 1, 2], [2, 1, 2], label="Experiment B")
legend = ax.legend(
loc="center left",
bbox_to_anchor=(1.02, 0.5),
fontsize=8
)
fig.savefig("results.png", bbox_inches="tight", dpi=150)
Execution trace:
plt.subplots()creates a figure and one axes.- Each
ax.plot()call creates a line. Thelabelvalues are stored for the legend. ax.legend()builds legend entries from the labeled lines.loc="center left"selects the center of the legend's left edge as its anchor point.bbox_to_anchor=(1.02, 0.5)places that point just right of the axes and halfway up its height.
Real World Use Cases
External legends are useful when the plotted data should remain unobstructed:
- Monitoring dashboards: several time-series lines need a readable plot area and a list of service names beside it.
- Scientific charts: experiment names can be long, so an internal legend would cover data points.
- Financial reports: multiple funds or market indicators need labels without hiding price trends.
- Data exports: a script generates PNG or PDF reports where the legend must be included reliably.
- Dense comparison charts: 10–20 categories may need a multi-column legend below or beside the plot.
Real Codebase Usage
In production plotting code, developers commonly keep the legend configuration in one place so all generated charts look consistent.
LEGEND_OPTIONS = {
"loc": "upper left",
"bbox_to_anchor": (1.02, 1),
"fontsize": 8,
"frameon": False,
"labelspacing": 0.3,
}
ax.legend(**LEGEND_OPTIONS)
Useful real-project patterns include:
- Only label needed artists: give
labelonly to lines that should appear in the legend. This prevents duplicate or noisy entries. - Use figure-level legends for multiple axes:
fig.legend(...)can create one shared legend for a multi-panel figure. - Export safely: use
fig.savefig(path, bbox_inches="tight")for reports that contain annotations or legends outside axes. - Make output dimensions intentional: if an external legend must be visible in an application window, increase
figsizerather than allowing the axes to become too small. - Use readable labels: shortening verbose names can be better than making the font extremely small.
Common Mistakes
Expecting an external legend to need no space
An external legend is outside the axes, but it is still part of the figure. If the figure is not wide enough, it may be clipped or overlap another element.
# May be clipped in a saved image without bbox_inches="tight"
ax.legend(loc="upper left", bbox_to_anchor=(1.02, 1))
fig.savefig("plot.png")
Prefer:
fig.savefig("plot.png", bbox_inches="tight")
Using bbox_to_anchor without understanding loc
This does not mean “put the entire legend at this coordinate.” It means “put the point selected by loc at this coordinate.”
# The legend's lower-right corner is anchored at the axes upper-right corner.
ax.legend(loc="lower right", bbox_to_anchor=(1, 1))
Choose loc="upper left" for a legend placed to the right of an axes.
Making the font too small
ax.legend(fontsize=3)
Comparisons
| Technique | Best use | Effect on axes size | Important note |
|---|---|---|---|
ax.legend(loc="best") | Small legend inside one plot | None | May cover plotted data. |
ax.legend(..., bbox_to_anchor=...) | Put a legend beside one axes | None by itself | Export with bbox_inches="tight" if needed. |
fig.legend(...) | One legend shared by several axes | Depends on layout | Useful for multi-panel figures. |
fontsize=8 | Reduce legend text size | None | Keep text readable. |
ncol=2 or more |
Cheat Sheet
# Legend outside the right edge of one axes
ax.legend(
loc="upper left",
bbox_to_anchor=(1.02, 1),
fontsize=8
)
# Centered vertically on the right
ax.legend(
loc="center left",
bbox_to_anchor=(1.02, 0.5)
)
# Compact legend for many entries
ax.legend(
loc="upper left",
bbox_to_anchor=(1.02, 1),
fontsize=7,
ncol=2,
labelspacing=0.3,
handlelength=1.2,
frameon=False
)
# Save an external legend without cropping it
fig.savefig("chart.png", bbox_inches="tight", dpi=150)
Rules to remember:
locchooses the legend point to anchor.bbox_to_anchorchooses where that point goes.- Coordinates are relative to the axes by default.
- An external legend needs canvas space when displayed or exported.
- Use columns and spacing options before making text too small.
FAQ
How do I move a Matplotlib legend outside the plot on the right?
Use loc="upper left" with bbox_to_anchor=(1.02, 1) in ax.legend().
Does bbox_to_anchor change the size of the axes?
No. It changes the legend position. However, the figure may need additional canvas space to display or save the legend without clipping.
How do I reduce the legend font size in Matplotlib?
Pass a number to fontsize, such as ax.legend(fontsize=8).
Why is my legend missing from the saved PNG?
It is probably outside the normal figure boundary. Save with fig.savefig("plot.png", bbox_inches="tight").
How can I fit 20 legend labels into less space?
Try ncol=2 or more, shorten labels, reduce labelspacing, and use a modestly smaller fontsize.
Should I use ax.legend() or fig.legend()?
Use ax.legend() for one axes. Use fig.legend() when one legend should describe data across multiple axes.
Mini Project
Description
Create a reusable chart that compares several measurement series and places a compact legend to the right. The chart should preserve an unobstructed plotting area and export correctly as an image.
Goal
Generate and save a line chart with a readable external legend that is not clipped.
Requirements
Plot at least four labeled data series on one axes. Place the legend outside the right side of the axes. Use a smaller but readable legend font size. Use at least two legend columns. Save the image while including the external legend.
Keep learning
Related questions
@staticmethod vs @classmethod in Python Explained
Learn the difference between @staticmethod and @classmethod in Python with clear examples, use cases, mistakes, and a mini project.
Add Rows to a Pandas DataFrame in Python
Learn how to add rows to a Pandas DataFrame, why repeated row appends are slow, and when to use loc, concat, or record lists.
Call a Function by Name in a Python Module
Learn how to call a function by name in a Python module using strings, getattr, and safe patterns for dynamic function dispatch.