@@ -137,7 +137,8 @@ def do_constrained_layout(fig, h_pad, w_pad,
137137layoutgrids [fig ].update_variables ()
138138if check_no_collapsed_axes (layoutgrids ,fig ):
139139reposition_axes (layoutgrids ,fig ,renderer ,h_pad = h_pad ,
140- w_pad = w_pad ,hspace = hspace ,wspace = wspace )
140+ w_pad = w_pad ,hspace = hspace ,wspace = wspace ,
141+ compress = True )
141142else :
142143_api .warn_external (warn_collapsed )
143144
@@ -651,7 +652,7 @@ def get_pos_and_bbox(ax, renderer):
651652
652653
653654def reposition_axes (layoutgrids ,fig ,renderer ,* ,
654- w_pad = 0 ,h_pad = 0 ,hspace = 0 ,wspace = 0 ):
655+ w_pad = 0 ,h_pad = 0 ,hspace = 0 ,wspace = 0 , compress = False ):
655656"""
656657 Reposition all the Axes based on the new inner bounding box.
657658 """
@@ -662,7 +663,7 @@ def reposition_axes(layoutgrids, fig, renderer, *,
662663bbox = bbox .transformed (trans_fig_to_subfig ))
663664reposition_axes (layoutgrids ,sfig ,renderer ,
664665w_pad = w_pad ,h_pad = h_pad ,
665- wspace = wspace ,hspace = hspace )
666+ wspace = wspace ,hspace = hspace , compress = compress )
666667
667668for ax in fig ._localaxes :
668669if ax .get_subplotspec ()is None or not ax .get_in_layout ():
@@ -689,10 +690,10 @@ def reposition_axes(layoutgrids, fig, renderer, *,
689690for nn ,cbax in enumerate (ax ._colorbars [::- 1 ]):
690691if ax == cbax ._colorbar_info ['parents' ][0 ]:
691692reposition_colorbar (layoutgrids ,cbax ,renderer ,
692- offset = offset )
693+ offset = offset , compress = compress )
693694
694695
695- def reposition_colorbar (layoutgrids ,cbax ,renderer ,* ,offset = None ):
696+ def reposition_colorbar (layoutgrids ,cbax ,renderer ,* ,offset = None , compress = False ):
696697"""
697698 Place the colorbar in its new place.
698699
@@ -706,6 +707,8 @@ def reposition_colorbar(layoutgrids, cbax, renderer, *, offset=None):
706707 offset : array-like
707708 Offset the colorbar needs to be pushed to in order to
708709 account for multiple colorbars.
710+ compress : bool
711+ Whether we're in compressed layout mode.
709712 """
710713
711714parents = cbax ._colorbar_info ['parents' ]
@@ -724,6 +727,31 @@ def reposition_colorbar(layoutgrids, cbax, renderer, *, offset=None):
724727aspect = cbax ._colorbar_info ['aspect' ]
725728shrink = cbax ._colorbar_info ['shrink' ]
726729
730+ # For colorbars with a single parent in compressed layout,
731+ # use the actual visual size of the parent axis after apply_aspect()
732+ # has been called. This ensures colorbars align with their parent axes.
733+ # This fix is specific to single-parent colorbars where alignment is critical.
734+ if compress and len (parents )== 1 :
735+ from matplotlib .transforms import Bbox
736+ # Get the actual parent position after apply_aspect()
737+ parent_ax = parents [0 ]
738+ actual_pos = parent_ax .get_position (original = False )
739+ # Transform to figure coordinates
740+ actual_pos_fig = actual_pos .transformed (fig .transSubfigure - fig .transFigure )
741+
742+ if location in ('left' ,'right' ):
743+ # For vertical colorbars, use the actual parent bbox height
744+ # for colorbar sizing
745+ # Keep the pb x-coordinates but use actual y-coordinates
746+ pb = Bbox .from_extents (pb .x0 ,actual_pos_fig .y0 ,
747+ pb .x1 ,actual_pos_fig .y1 )
748+ elif location in ('top' ,'bottom' ):
749+ # For horizontal colorbars, use the actual parent bbox width
750+ # for colorbar sizing
751+ # Keep the pb y-coordinates but use actual x-coordinates
752+ pb = Bbox .from_extents (actual_pos_fig .x0 ,pb .y0 ,
753+ actual_pos_fig .x1 ,pb .y1 )
754+
727755cbpos ,cbbbox = get_pos_and_bbox (cbax ,renderer )
728756
729757# Colorbar gets put at extreme edge of outer bbox of the subplotspec