Skip to content

[ENH]: Built-in support for multi-color and multi-style text. #30890

Open

Description

@ra8in

Problem

Creating multi-colored or multi-styled text in Matplotlib requires manual positioning of each text segment with complex spacing calculations.
Users currently need to calculate x-positions manually for each colored segment, which is tedious and error-prone, especially when text properties change.

Proposed solution

Add a richtext() function (or ax.richtext() method) that handles multi-color/multi-style text automatically:

Current approach (manual and tedious):

fig, ax = plt.subplots()
ax.text(0.1, 0.5, "Hello", color='red', fontsize=20)
ax.text(0.35, 0.5, " ", fontsize=20)  # Manual spacing calculation!
ax.text(0.4, 0.5, "World", color='blue', fontsize=20)  # More manual work!

Proposed approach (simple and automatic):

fig, ax = plt.subplots()
ax.richtext(0.5, 0.5,
            strings=["Hello", " ", "World"],
            colors=["red", None, "blue"],
            fontsize=20, ha='center', va='center')

Key Features:

  • Accepts lists of text segments with corresponding colors/styles
  • Automatically calculates spacing and positioning
  • Supports word wrapping with box_width parameter
  • Flexible property specification (single values, lists, or dicts)
  • Compatible with all standard matplotlib text parameters

Example Use Cases:

  1. Data visualization: Highlight specific values in different colors
  2. Scientific plots: Format chemical formulas, mathematical notation
  3. Publication-quality figures: Mixed text styling in titles/labels

Implementation:
I've created a working proof-of-concept package: mpl-richtext (also on PyPI)

The implementation:

  • Uses matplotlib's renderer for accurate text measurements
  • Creates positioned Text objects automatically
  • ~400 lines of code
  • Handles alignment, wrapping, and various text properties

Example output:

Example

Questions for maintainers:

  1. Is this functionality suitable for matplotlib core?
  2. Should it be a standalone function, an Axes method, or a custom Artist?
  3. Any concerns about the implementation approach?

I'm willing to contribute this to matplotlib and adapt it based on maintainer feedback. Open to API redesign or implementation changes as needed.

Activity

  1. story645 commented on Dec 22, 2025

    @story645
    Member

    Hi, your library looks really cool and you should absolutely add it to https://matplotlib.org/thirdpartypackages/

    As for this in core? If we were to build in better support, it would likely be built on top of current work to improve font handling (Font and text overhaul (view)).

    Users currently need to calculate x-positions manually for each colored segment, which is tedious and error-prone, especially when text properties change.

    When does using annotate fail?

  2. timhoffm commented on Dec 24, 2025

    @timhoffm
    Member

    IMHO rich text support would be a nice addition to core matplotlib. However, we'd need to approach this differently, both from architecture and API:

    Cobbling together individual Text objects will not be good enough. Almost every update operation like changing text or fontsize is not reasonably possible as there is a strong interdependency of properties and positions of the Text objects. Instead, we'd need some new Artist, e.g. TextArea. This would hold all text parts with their individual properties and draw them all through one draw() method.

    Also, I think, lists of text chunks with their individual properties are not a good high-level interface. Instead we'd most likely want some kind of simple markup language.

  3. story645 commented on Dec 24, 2025

    @story645
    Member

    Instead, we'd need some new Artist, e.g. TextArea. This would hold all text parts with their individual properties and draw them all through one draw() method.

    Would that be an extension of TextArea?

    Also there's a start of a discussion on how this fits with the new font stuff in #29695

  4. timhoffm commented on Dec 24, 2025

    @timhoffm
    Member

    😳 I didn’t know we had a TextArea already. Needs investigation. My primary thought was that we could start with a new independent Artist without backward-compatibility concerns.

    In the end we likely want to port part of the functionality back to Text, so that e.g. labels and titles can be styled with markup. But I reckoned that it would be helpful to learn how to do this with a new Artist, that is designed from scratch and is a bit more general in that it would support e.g. word wrapping.

  5. story645 commented on Dec 24, 2025

    @story645
    Member

    I didn’t know we had a TextArea already.

    I only know about this 'cause I have to finish #29374

    I like this issues naming suggestion of RichText.

    In the end we likely want to port part of the functionality back to Text, so that e.g. labels and titles can be styled with markup

    Possibly we could do some sort of dispatching on the various text setting methods - if spec then RichText else Text - which would make it easier to maintain scope.

  6. QuLogic commented on Dec 25, 2025

    @QuLogic
    Member

    See also flexitext and highlight_text.

    One benefit of handling a whole rich text string in core is that something like libraqm can do the layout for the whole string together with all options (which is how we do font fallback.) However, I do think that would need to additions to the backend API to really translate all the information nicely.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions