2025, Oct 29 03:00
How to Keep Matplotlib Superscripts and Subscripts in Computer Modern: Consistent Label Fonts
Learn how to fix Matplotlib font mismatch in superscripts and subscripts. Use Computer Modern in labels with mathtext and rcParams for consistent plots.
Keeping figures visually consistent with a report matters, especially when fonts mismatch inside a single label. A frequent nuisance in Matplotlib is that superscripts and subscripts in labels render in a different face than the surrounding text, even when a specific font family is set. If you rely on Computer Modern (the default font used by pdfLaTeX) and you see the superscript 2 in “W/cm²” look off, the fix is straightforward.
Problem setup
The goal is to use Computer Modern throughout the figure: titles, axis labels, and units. The configuration below selects a serif family and the cmr10 face, and enables math text handling:
import matplotlib.pyplot as gp
import matplotlib as mp
mp.rcParams['font.family'] = "serif"
mp.rcParams['font.serif'] = "cmr10"
mp.rcParams['axes.formatter.use_mathtext'] = True
canvas, axes = gp.subplots()
axes.set_title('Results', fontsize=18)
axes.set_ylabel(r'Heat Flux (W/cm$^2$)', fontsize=18)
axes.set_xlabel('Wall Superheat (K)', fontsize=18)
axes.legend()
The label displays, but the superscript 2 does not use the same face as the rest of the text. The same visual mismatch appears with subscripts.
What’s going on
The font changes at the moment you enter math text. In the example above, the segment inside dollar signs is handled differently from the surrounding string, so the superscript 2 is typeset with a math font that doesn’t match the chosen serif face. The result is a subtle but noticeable inconsistency between the unit text and the exponent.
Solution
Force the math segment to use the regular text font. The simplest way is to wrap the unit string with \mathregular while keeping the superscript inside:
import matplotlib.pyplot as gp
import matplotlib as mp
mp.rcParams['font.family'] = "serif"
mp.rcParams['font.serif'] = "cmr10"
mp.rcParams['axes.formatter.use_mathtext'] = True
fig_obj, axis_ref = gp.subplots()
axis_ref.set_title('Results', fontsize=18)
axis_ref.set_ylabel('Heat Flux ($\mathregular{W/cm^{2}}$)', fontsize=18)
axis_ref.set_xlabel('Wall Superheat (K)', fontsize=18)
This renders the superscript 2 with the same Computer Modern face as the rest of the label.
Another way to make the math portion follow your chosen font is to adjust the math text configuration. In addition to the current settings, set:
mp.rcParams['mathtext.fontset'] = "custom"
mp.rcParams['mathtext.rm'] = "serif"
In scenarios where math text is not required, you can also avoid math altogether by using a Unicode superscript in the label string:
axis_ref.set_ylabel('Heat Flux (W/cm\u00b2)', fontsize=18)
Why this matters
Font inconsistency breaks the rhythm of a figure and makes otherwise polished plots feel uneven. When figures go into papers, theses, or reports that rely on Computer Modern, mismatched superscripts draw attention away from the data. Ensuring the exponent and the surrounding text share the same face keeps visuals coherent and professional.
Takeaways
Be mindful of when your label strings switch into math handling. If you need superscripts or subscripts but want the look to match your text font, wrap the relevant part with \mathregular, or tune the math text settings so math follows your serif choice. If you don’t need math parsing, a Unicode superscript is a clean and simple alternative. Consistency here pays off in readability and presentation quality.
The article is based on a question from StackOverflow by simply_a_student and an answer by simply_a_student.