matplotlib
legend
axis
figure
plot customization

Moving matplotlib legend outside of the axis makes it cutoff by the figure box

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When you move a Matplotlib legend outside the axes, the legend may be clipped because the figure does not automatically reserve space for it. The legend is no longer inside the normal axes area, but the figure size and subplot margins still reflect the original layout.

The fix is usually one of three things: give the figure more margin, use a layout helper, or save the figure with a tight bounding box. Which one you need depends on whether the issue is on screen, in the saved file, or both.

Place The Legend Outside Deliberately

The standard pattern uses bbox_to_anchor and loc:

python
1import matplotlib.pyplot as plt
2
3x = [1, 2, 3]
4y1 = [1, 4, 9]
5y2 = [1, 2, 3]
6
7fig, ax = plt.subplots(figsize=(6, 4))
8ax.plot(x, y1, label="Quadratic")
9ax.plot(x, y2, label="Linear")
10
11ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
12plt.show()

This moves the legend to the right of the axes. The clipping problem appears because the default subplot area usually still fills most of the figure width.

Reserve Space With subplots_adjust

One direct solution is to shrink the axes so the figure leaves room for the legend.

python
1import matplotlib.pyplot as plt
2
3fig, ax = plt.subplots(figsize=(6, 4))
4ax.plot(x, y1, label="Quadratic")
5ax.plot(x, y2, label="Linear")
6
7ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
8fig.subplots_adjust(right=0.75)
9plt.show()

By reducing the usable width of the subplot area, you create empty figure space on the right where the legend can live without being clipped.

Try Layout Helpers

Matplotlib layout helpers can sometimes handle spacing for you. tight_layout() is often the first thing to try:

python
1fig, ax = plt.subplots(figsize=(6, 4))
2ax.plot(x, y1, label="Quadratic")
3ax.plot(x, y2, label="Linear")
4
5ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
6plt.tight_layout()
7plt.show()

This often improves things, but it is not perfect for every external-legend case. constrained_layout=True at figure creation can also help:

python
1fig, ax = plt.subplots(figsize=(6, 4), constrained_layout=True)
2ax.plot(x, y1, label="Quadratic")
3ax.plot(x, y2, label="Linear")
4ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
5plt.show()

Layout helpers are convenient, but manual margin control is still sometimes the most predictable approach.

Saving Figures Requires Extra Care

A figure that looks acceptable on screen can still save incorrectly if the output bounding box crops the external legend. When saving, bbox_inches="tight" is often the missing step:

python
1fig, ax = plt.subplots(figsize=(6, 4))
2ax.plot(x, y1, label="Quadratic")
3ax.plot(x, y2, label="Linear")
4ax.legend(loc="center left", bbox_to_anchor=(1.02, 0.5))
5
6fig.savefig("plot.png", bbox_inches="tight", dpi=150)

This tells Matplotlib to include everything that was drawn, including the legend outside the axes.

Consider Figure-Level Legends

If the legend conceptually belongs to the whole figure rather than one subplot, fig.legend(...) can be cleaner than ax.legend(...).

python
1fig, ax = plt.subplots(figsize=(6, 4))
2line1, = ax.plot(x, y1, label="Quadratic")
3line2, = ax.plot(x, y2, label="Linear")
4
5fig.legend([line1, line2], ["Quadratic", "Linear"], loc="center right")
6fig.subplots_adjust(right=0.8)
7plt.show()

This is especially helpful in multi-axes figures where one shared legend is better than one legend per subplot.

Common Pitfalls

One common mistake is assuming bbox_to_anchor automatically resizes the figure. It does not. Another is relying only on what the interactive window shows and then being surprised when savefig clips the legend in the exported image. Developers also sometimes mix tight_layout, constrained_layout, and manual adjustments without understanding which one currently controls spacing. Finally, if the legend is very wide, you may simply need a larger figure rather than endlessly tweaking margins.

Summary

  • External legends are clipped because the figure does not automatically reserve space for them.
  • Use bbox_to_anchor to position the legend and subplots_adjust to make room.
  • 'tight_layout() or constrained_layout=True can help, but not in every case.'
  • Use bbox_inches="tight" when saving figures that include external legends.
  • If the legend represents the whole figure, consider fig.legend(...) instead of ax.legend(...).

Course illustration
Course illustration

All Rights Reserved.