Quick answer: Synthetic bold/italic changes glyph widths. Always re-measure with font.size(text) after toggling the style, or load a dedicated bold font file.

A UI lays out text using cached widths, then calls font.set_bold(True) for emphasis. The bold text overflows its box — the cached widths are for the regular weight.

Synthetic Styling Changes Metrics

set_bold and set_italic on a pygame Font apply a synthetic transform — faux bold smears each glyph slightly wider. Any width you measured before the toggle is now wrong.

Re-Measure After Toggling

font.set_bold(True)
w, h = font.size(text)   # measure in the CURRENT style
surface = font.render(text, True, color)

Measure, then render, with the style already set. Don’t reuse a width from before the toggle.

Prefer a Real Bold Font

Synthetic bold is approximate and looks worse than a hand-designed bold weight. Load the actual bold file as a separate Font object:

regular = pygame.font.Font("Inter-Regular.ttf", 24)
bold    = pygame.font.Font("Inter-Bold.ttf", 24)

Each has its own stable metrics — no toggling, no re-measuring surprises.

Cache Per Style

If you cache rendered text, key the cache on (text, style) — not just text. A regular and bold render of the same string are different surfaces.

Verifying

Bold emphasis text fits its box. Mixed regular/bold runs lay out correctly. Switching styles re-measures and never overflows.

“Style toggles change metrics. Re-measure after, or just load real weight files.”

For any polished UI, ship the actual font weights — synthetic bold/italic always looks a little off next to the real thing.