How can you make multi-line axis labels with TeX not left-justified in R2026a?
Show older comments
I just started using R2026a and encountered a problem with axis labels. In R2025b on a different computer, I don't have this problem. Multi-line labels that have TeX in them render left justified, .e.g.
xlabel( sprintf( 'normal\n\\bfbold' ) )
whereas those with no TeX render centered as expected
ylabel( sprintf( 'normal\nbold' ) )

Setting the 'HorizontalAlignment' property of the label to 'center' after the fact, as suggested by a web search does not fix the problem. I get the same behavior creating a text object with text() as opposed to xlabel(), and can't think of a workaround other than creating a separate text object for each line, which would make be abandon R2026a for the time being. Has anyone solved this?
Answers (3)
xlabel({'normal','\bfbold'},'interpreter','tex')
Correct syntax for the TeX interpreter and it'll work as expected.
2 Comments
Spero
on 24 Apr 2026
Mmmm....indeed, on closer looking, that does appear to be so.
hXL=xlabel({'normal','\bfbold'},'interpreter','tex'); % the cellstr version
hXL
Just confirmed the above does show up with both text lines being centered in R2022b.
I'd say this counts as and should be submitted as official support request/bug.
xlabel({'normal'; '\textbf{bold}'}, ...
'Interpreter','latex')
4 Comments
dpb
on 24 Apr 2026
Yeah, I had checked the LaTeX interpreter, too...but TeX appears to have been broke...
Spero
on 24 Apr 2026
"...see if there's a workaround for the TeX interpreter"
As noted above, for that I think you'll have to submit this to Mathworks as an official support request/bug at <Product Support Page>. The 'HorizontalAlignment' is returned as 'centered' so there's nothing else to be done at the user level with the object as rendered other than some manual fixup like adding blanks as needed or the drawing of individual text lines it would appear.
"...it worked up through and including R2025b."
That's interesting/confusing as the forum here uses R2025a and shows the same symptoms. That might imply it's OS/platform dependent? I've not yet moved to the new UI so can't compare here.
the whole point of this post was to see if there's a workaround for the TeX interpreter.
Assuming you've reported this as a bug and (presumably) a patch is on the way, what value is there in restricting the allowable space of workarounds to the TeX interpreter? Since LaTeX is a superset of TeX, it should be able to do all the same stuff.
Here's an attempt using the idea of separate text boxes that you mentioned. It wasn't too bad, although, it doesn't have the ability to dynamically readjust to things like changes in the figure size, as a normal xlabel would. However, a nice upside of this is that different lines can have different interpreters.
T = multiXLabel(["normal","\bfbold","$y=x+1$"], 'Interpreter','tex');
T(3).Interpreter='latex';
function varargout = multiXLabel(varargin)
% MULTIXLABEL(STR)
% creates a multiline x-axis label on the current axes using the strings
% in STR. STR may be a string array, character vector, cell array of
% character vectors, or any input convertible to string.
%
% MULTIXLABEL(AX,STR)
% adds the multiline label to the specified axes AX.
%
% MULTIXLABEL(...,Name,Value)
% passes additional name-value arguments directly to XLABEL, allowing
% standard text formatting options such as:
%
% 'Interpreter'
% 'FontSize'
% 'FontWeight'
% 'FontAngle'
% 'Color'
% 'Rotation'
%
% T = MULTIXLABEL(...)
% returns a vector of text object handles corresponding to each line of
% the multi-line label.
if isa(varargin{1},'matlab.graphics.axis.Axes')
[ax,str]=deal(varargin{1:2}); varargin(1:2)=[];
else
ax=gca;
str=varargin{1}; varargin(1)=[];
end
str=string(str);
t = xlabel(ax,'',varargin{:});
oldAxUnits = ax.Units;
ax.Units = 'normalized';
oldLabelUnits = t.Units;
t.Units = 'normalized';
t.Visible = 'off';
N = numel(str);
T = gobjects(N,1);
lineSpacing = 1.15;
x0 = 0.5;
y0 = -0.08;
for i = 1:N
T(i) = text(ax,x0,y0,str(i), ...
'Units','normalized', ...
'Interpreter',t.Interpreter, ...
'HorizontalAlignment','center', ...
'VerticalAlignment','top', ...
'FontName',t.FontName, ...
'FontSize',t.FontSize, ...
'FontWeight',t.FontWeight, ...
'Clipping','off');
drawnow
ext = T(i).Extent;
if i < N
y0 = y0 - lineSpacing*ext(4);
end
end
drawnow
% Find lowest point of all replacement labels, in axes-normalized units
ymin = min(arrayfun(@(h) h.Extent(2), T));
% Amount below axes needed, plus small padding
neededBelow = max(0, -ymin);
% Current bottom margin below axes
currentBelow = ax.Position(2);
% Only add the extra room actually needed
extra = max(0, neededBelow - currentBelow);
if extra > 0
ax.Position(2) = ax.Position(2) + extra;
ax.Position(4) = ax.Position(4) - extra;
end
ax.Units = oldAxUnits;
t.Units = oldLabelUnits;
if nargout, varargout={T};end
end
4 Comments
Spero
on 24 Apr 2026
dpb
on 24 Apr 2026
"...A nice upside of this is that different lines can have different interpreters."
I wonder couldn't use a cell array of just the desired interpreter for cleaner UI? But, clever, agreed.
@dpb that runs into the same problem as,
plot(X1,Y1,X2,Y2,...Name,Value)
You often do want some way to pass different Name Value pairs to the separate line plots, but TMW doesn't bother because it becomes thorny to parse Line properties that are already cell-valued.
dpb
on 24 Apr 2026
@Matt J, yeah, to be fully generic replacement would be a pain; but for a single-use workaround with only the one choice, maybe.
I looked at the idea of modifying the string lengths to approximate by padding, but the control characters aren't parsed from the strings so one would have to build in the TeX comand list to back out the actual displayed text.
All in all, seems like a nasty regression; wonder how it came to be. Undoubtedly something to do with the underlying complete rewrite. I suppose it will all turn out ok eventually, but it's certainly a bumpy ride on the way.
Categories
Find more on Axis Labels in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!


