How to Add ANSI Colors to Table Cells Using Outfancy

Outfancy preserves ANSI escape sequences in cell values and only strips them internally when calculating column widths via widgets.printed_length, allowing you to embed color codes directly from outfancy.colors or custom ANSI strings.

Outfancy is a lightweight Python library for rendering formatted tables in the terminal. Because the library renders cells as literal strings without additional processing, you can add ANSI colors to table cells by embedding escape sequences directly in your data strings.

How Color Handling Works in the Rendering Pipeline

Outfancy does not provide a dedicated styling API. Instead, it treats any ANSI escape sequences in your data as literal text. The library strips these codes only when necessary for layout calculations, ensuring your colors appear in the final output while maintaining proper column alignment.

In outfancy/widgets.py, the remove_colors function (lines 15-27) uses a regular expression to strip \x1b[... escape sequences. This function is called exclusively by printed_length (lines 99-103), which calculates the visual width of cell content for alignment purposes. Because remove_colors operates only during width measurement—not during the actual string concatenation—the ANSI codes remain intact in the final table output produced by outfancy/table.py.

The render method in outfancy/table.py builds the table by joining these pre-colored strings, meaning whatever color codes you embed are preserved verbatim in the terminal output.

Using the Built-in Color Palette

The outfancy/colors.py file (lines 3-31) defines a ready-made palette of ANSI constants. These follow a naming convention of {style}_{color} where style can be normal, bold, or strong, and color includes standard terminal colors like red, green, blue, and violet.

Available constants include:

  • normal_red, normal_green, normal_blue — Standard foreground colors
  • bold_normal_blue, bold_strong_green — Bold and high-intensity variants
  • normal_reset, bold_normal_reset, bold_strong_reset — Style reset codes

Import the palette and wrap your cell values with the appropriate opening and reset codes:

from outfancy.table import Table
from outfancy import colors

# Wrap cell values with color codes

data = [
    (f"{colors.normal_red}Critical{colors.normal_reset}", "Error", "99"),
    (f"{colors.normal_green}Stable{colors.normal_reset}", "OK", "42"),
    (f"{colors.bold_strong_yellow}Warning{colors.bold_strong_reset}", "Check", "10")
]

tbl = Table()
print(tbl.render(data))

Coloring Table Headers

Headers defined via the label_list parameter accept colored strings through the same mechanism. Because labels pass through the same rendering pipeline as data cells, you can apply ANSI codes to column titles to create visually distinct header rows:

labels = [
    f"{colors.bold_normal_violet}Status{colors.bold_normal_reset}",
    f"{colors.bold_normal_violet}Message{colors.bold_normal_reset}",
    f"{colors.bold_normal_violet}Code{colors.bold_normal_reset}"
]

print(tbl.render(data, label_list=labels))

Working with Custom ANSI Codes

If the built-in palette lacks the specific color you need, you can embed raw ANSI escape sequences directly. This is useful for 256-color or RGB terminal colors:


# 256-color orange

custom_orange = "\x1b[38;5;208m"
reset = "\x1b[0m"

data = [
    (f"{custom_orange}Custom{reset}", "Standard", "Data")
]

When using custom codes, always include a reset sequence (such as \x1b[0m or colors.normal_reset) at the end of each colored segment to prevent the styling from bleeding into subsequent cells or text.

Summary

  • Outfancy renders cell content literally, preserving any ANSI escape sequences you embed in your data strings.
  • The remove_colors function in outfancy/widgets.py (lines 15-27) strips codes only during width calculation via printed_length, ensuring columns align correctly despite invisible color codes.
  • Import pre-defined color constants from outfancy/colors.py or use custom \x1b[ sequences for full color control.
  • Apply reset codes after each colored segment to isolate styling to specific cells.
  • Headers support the same coloring technique via the label_list parameter.

Frequently Asked Questions

Does Outfancy provide a dedicated API for styling individual cells?

No. According to the source code in outfancy/table.py, the library does not implement cell-level styling methods. You add colors by embedding ANSI escape sequences directly into the string values you pass to Table.render.

Will ANSI color codes break table alignment?

No. The printed_length function in outfancy/widgets.py (lines 99-103) automatically removes color codes when calculating the visual width of each cell. This ensures the column widths are computed based on the actual character count, not the length of the escape sequences, keeping your table properly aligned.

Can I color the table headers separately from the data rows?

Yes. The label_list parameter in Table.render accepts strings, so you can wrap your header labels with the same ANSI color constants used for cell data. These labels undergo the same rendering process as body cells.

How do I reset colors after styling a specific cell?

Append a reset code immediately after the colored text. Use colors.normal_reset for standard colors, colors.bold_normal_reset for bold styles, or colors.bold_strong_reset for high-intensity bold colors. Alternatively, use the universal \x1b[0m reset code to return to default terminal styling.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →