You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[ENH]: Optional axes-aware text wrapping for wrap=True #31655
When creating multi-axes figures with subplots (e.g. dashboards,
reports, side-by-side comparisons), using ax.text() with wrap=True
causes text to wrap based on the figure boundary instead of the axes
boundary. This means text overflows outside its axes into adjacent
axes or outside the figure entirely, making the plot look broken.
Example: A 2-column subplot figure where a long annotation in the
left axes spills into the right axes area.
Proposed solution
Add an option for wrap=True to respect the axes boundary when text
is placed inside an axes, so annotations stay visually contained
within their axes.
This could be implemented by checking whether the text object belongs
to an axes (self.axes is not None) in the _get_wrap_line_width()
method of text.py, and using the axes boundary instead of the figure
boundary when calculating the available wrap width.
Hi @codegnan-dm, I see you already have PR #31633 linked for this enhancement. This looks like a super useful feature! Let me know if you need any help testing it out on different subplot configurations or if there is anything I can do to help get it reviewed.
This means text overflows outside its axes into adjacent axes or outside the figure entirely
If you have an example where you set wrap=True and the text still went outside the figure, please raise that as a bug report.
If the problem is only that text goes into the next axes, can you get what you want with subfigures?
importmatplotlib.pyplotaspltfig=plt.figure(figsize=(6, 4))
sfig1, sfig2=fig.subfigures(ncols=2)
ax1=sfig1.subplots()
ax2=sfig2.subplots()
ax1.set_title("Left Axes")
ax1.text(0.05, 0.5,
"This is a very long string that should wrap within the axes boundary and not overflow outside it",
wrap=True, transform=ax1.transAxes, va='center')
ax2.set_title("Right Axes")
ax2.text(0.05, 0.5,
"This is a very long string that should wrap within the axes boundary and not overflow outside it",
wrap=True, transform=ax2.transAxes, va='center')
plt.show()
@rcomer Thank you for the subfigures suggestion — I tested it and
it does work correctly. The text wraps within each subfigure boundary
as expected.
However, I think the axes-aware wrapping in PR #31633 still adds value
for the following reasons:
Discoverability — users who use ax.text() with wrap=True expect
wrapping to "just work" within their axes. Requiring subfigures as
a workaround is not obvious and is hard to find in documentation.
Simplicity — plt.subplots() is the most common way to create
multi-axes figures. Requiring users to restructure their code to
use fig.subfigures() just to get correct text wrapping adds
unnecessary complexity.
Consistency — if wrap=True is set on text inside an axes, it is
reasonable to expect wrapping to respect the axes boundary by default.
That said, I completely understand if the maintainers feel the
subfigures workaround is sufficient and the PR is not needed. Happy
to close the PR if that is the preferred direction.
@timhoffm Thank you for the support! That is exactly the problem
I encountered — the current behavior almost always produces visually
broken output when using wrap=True inside axes.
PR #31633 implements this fix by checking whether the text belongs
to an axes in _get_wrap_line_width() and using the axes boundary
instead of the figure boundary when calculating wrap width. The fix
preserves full backward compatibility — figure-level text like
fig.suptitle() still falls back to the figure boundary.
Before/after screenshots are attached to the PR showing the
improvement. Happy to make any adjustments based on your feedback!
Interestingly, our current implementation was originally based on a StackOverflow answer that did wrap to the axes #3418. From a quick scan of the PR I don't see an explanation for why it changed to wrapping to the figure #4342.
I note that annotations are often placed outside an axes, even if they use an axes method (example). In fact I guess that would be more common if you have a lot of text, because you don't want the text to obscure the data you have plotted. So I think this would need more careful design than just checking whether the text object has an axes attribute.
This means we actually need control via a parameter wrap_boundary with values "axes" / "figure".
Default for Text would be "figure", and Axes.text() would override the default to "axes". Possibly some other text-related plotting functions like bar_label should too.
@rcomer Yes let's leave bar_label aside that's more involved.
@story645 good idea. We don't need a new parameter. Enriching the semantics of wrap from bool to different values makes sense. For backward-compatibility and simplicity, wrap=True should be synonym to wrap="figure".
Thank you all for the detailed design discussion! I understand the
consensus is to enrich wrap to accept "axes" / "figure" string values
in addition to True/False, with wrap=True remaining as figure boundary
for backward compatibility. I will update PR #31633 accordingly.
I have opened PR #31716 which implements the agreed design — extending wrap to accept 'axes' and 'figure' string values, with wrap=True remaining as figure boundary for backward compatibility.
Activity
anushkadas-coder commentedon May 13, 2026
Hi @codegnan-dm, I see you already have PR #31633 linked for this enhancement. This looks like a super useful feature! Let me know if you need any help testing it out on different subplot configurations or if there is anything I can do to help get it reviewed.
deepali-cg commentedon May 13, 2026
Hi @anushkadas-coder, thank you so much! That's really kind of you.
Yes, it would be really helpful if you could test it on different
subplot configurations and share your results as a comment on PR #31633.
Any testing or feedback you can share on the PR would help strengthen
the case for the maintainers to review and merge it. Thanks again!
rcomer commentedon May 15, 2026
If you have an example where you set
wrap=Trueand the text still went outside the figure, please raise that as a bug report.If the problem is only that text goes into the next axes, can you get what you want with subfigures?
deepali-cg commentedon May 19, 2026
@rcomer Thank you for the subfigures suggestion — I tested it and
it does work correctly. The text wraps within each subfigure boundary
as expected.
However, I think the axes-aware wrapping in PR #31633 still adds value
for the following reasons:
Discoverability — users who use ax.text() with wrap=True expect
wrapping to "just work" within their axes. Requiring subfigures as
a workaround is not obvious and is hard to find in documentation.
Simplicity — plt.subplots() is the most common way to create
multi-axes figures. Requiring users to restructure their code to
use fig.subfigures() just to get correct text wrapping adds
unnecessary complexity.
Consistency — if wrap=True is set on text inside an axes, it is
reasonable to expect wrapping to respect the axes boundary by default.
That said, I completely understand if the maintainers feel the
subfigures workaround is sufficient and the PR is not needed. Happy
to close the PR if that is the preferred direction.
timhoffm commentedon May 19, 2026
I agree that wrapping text in an Axes is a desirable feature.
If text in an Axes is wrapped, it should by default be wrapped within the Axes box. Crossing the spine is almost always visually ugly (see also the current example: https://matplotlib.org/stable/gallery/text_labels_and_annotations/autowrap.html).
deepali-cg commentedon May 19, 2026
@timhoffm Thank you for the support! That is exactly the problem
I encountered — the current behavior almost always produces visually
broken output when using wrap=True inside axes.
PR #31633 implements this fix by checking whether the text belongs
to an axes in _get_wrap_line_width() and using the axes boundary
instead of the figure boundary when calculating wrap width. The fix
preserves full backward compatibility — figure-level text like
fig.suptitle() still falls back to the figure boundary.
Before/after screenshots are attached to the PR showing the
improvement. Happy to make any adjustments based on your feedback!
rcomer commentedon May 19, 2026
Interestingly, our current implementation was originally based on a StackOverflow answer that did wrap to the axes #3418. From a quick scan of the PR I don't see an explanation for why it changed to wrapping to the figure #4342.
I note that annotations are often placed outside an axes, even if they use an axes method (example). In fact I guess that would be more common if you have a lot of text, because you don't want the text to obscure the data you have plotted. So I think this would need more careful design than just checking whether the text object has an
axesattribute.rcomer commentedon May 19, 2026
OTOH axes titles are an example where, if you have subplots, you probably want to wrap to the width of the axes even though the text is outside it.
timhoffm commentedon May 19, 2026
This means we actually need control via a parameter
wrap_boundarywith values "axes" / "figure".Default for Text would be "figure", and
Axes.text()would override the default to "axes". Possibly some other text-related plotting functions likebar_labelshould too.rcomer commentedon May 19, 2026
If you are passing long strings in
bar_label, wouldn't you want to wrap to the bars?story645 commentedon May 19, 2026
What about allowing
wrapto take "axes" and "figure" in addition to True/False?timhoffm commentedon May 19, 2026
@rcomer Yes let's leave
bar_labelaside that's more involved.@story645 good idea. We don't need a new parameter. Enriching the semantics of
wrapfrom bool to different values makes sense. For backward-compatibility and simplicity,wrap=Trueshould be synonym towrap="figure".deepali-cg commentedon May 20, 2026
Thank you all for the detailed design discussion! I understand the
consensus is to enrich wrap to accept "axes" / "figure" string values
in addition to True/False, with wrap=True remaining as figure boundary
for backward compatibility. I will update PR #31633 accordingly.
deepali-cg commentedon May 20, 2026
I have opened PR #31716 which implements the agreed design — extending wrap to accept 'axes' and 'figure' string values, with wrap=True remaining as figure boundary for backward compatibility.