Description
Bug summary
When legend is placed outside of the axes bounds (using bbox_to_anchor), particularly by a relatively wide margin, and layout is set to "constrained", one would expect the axes to be scaled such that both the axes and legend fit inside the figure size, as shown below:

However, the initially generated plot does not scale the axes enough to include the legend within the figure, as shown below:

However, when the _constrained_layout
function is iterated upon (by repeated plt.savefig()
, the figure converges to the expected result. The attached example illustrates this convergence. For the purposes of generated the attached output images, the example script was executed with the internal number of _constrained_layout
set to 1 (instead of 2), on this line of the _constrained_layout
function:
This was done to show what happens with each iteration of _constrained_layout
. An animated GIF of the sequence of images produced is shown below:
Code for reproduction
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 500)
y1 = np.sin(x)
fig, ax = plt.subplots(figsize=(10, 6), layout="constrained")
ax.plot(x, y1, label='sin(x) long title')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.legend( loc="upper right", bbox_to_anchor=(1.5, -0.8))
for i in range(21):
fig.savefig(f'constrained_test_{i}.png')
Actual outcome

Expected outcome

Additional information
No response
Operating system
No response
Matplotlib Version
3.11.0.dev52743+g30f4ece.d20250712 (Current main, with above noted modification)
Matplotlib Backend
No response
Python version
No response
Jupyter version
No response
Installation
git checkout