# How to Apply ANSI Terminal Colors and Styles Using fmtlib

> Learn to apply ANSI terminal colors and styles with fmtlib. Use fg, bg, and emphasis enums with the | operator for stunning text formatting in your C++ applications.

- Repository: [Hello World Foundation/fmt](https://github.com/fmtlib/fmt)
- Tags: how-to-guide
- Published: 2026-09-11

---

**The {fmt} library provides a type-safe, composable API in [`include/fmt/color.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/color.h) for emitting ANSI escape sequences, using `fg()`, `bg()`, and `emphasis` enums combined via the `|` operator to control terminal colors and text styles.**

The **fmtlib/fmt** repository offers a comprehensive solution for applying ANSI terminal colors and styles using fmtlib through its dedicated color formatting API. The implementation resides primarily in [`include/fmt/color.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/color.h), which extends the core formatting engine defined in [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h) to support 24-bit RGB values, 8-bit terminal colors, and text emphasis attributes. All color operations are constexpr-compatible and integrate directly with the library’s existing `print` and `format` functions.

## Core Color Types and Enums

The color system is built on strongly-typed enums that prevent runtime errors and provide compile-time validation of color values.

### RGB and Terminal Color Palettes

The library defines two distinct color enumerations in [`include/fmt/color.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/color.h). The **`enum class color`** defines a 24-bit RGB palette where each enumerator stores a 0xRRGGBB hex value (e.g., `fmt::color::steel_blue`, `fmt::color::red`). For basic terminal compatibility, the **`enum class terminal_color`** provides 8-bit ANSI standard colors ranging from black to bright_white.

### Text Emphasis Attributes

Text styling beyond color is handled by the **`enum class emphasis`**, a bit-mask enumeration defined at lines 79-86. This supports bold, faint, italic, underline, blink, reverse, conceal, and strikethrough attributes. These flags can be combined using bitwise operations to apply multiple emphasis styles simultaneously.

### Internal Representation

The library uses a compact internal structure to store color data efficiently. The **`struct rgb`** decodes 24-bit color values into separate R, G, B components, while **`detail::color_type`** acts as a bit-packed discriminated union that can represent an unset value, an RGB color, or a terminal color index. This internal representation enables the type-safe composition mechanisms exposed by the public API.

## Composing Styles with text_style

The **`text_style`** class serves as the primary container for formatting attributes, storing foreground color, background color, and emphasis flags in a single 64-bit integer where specific bit ranges encode each component.

### Style Composition Operators

`text_style` provides an **`operator|=`** method (defined at lines 135-182) that safely merges style components. You can combine foreground colors, background colors, and emphasis attributes using the `|` operator. The implementation actively rejects illegal mixtures—attempting to combine a 24-bit RGB color with an 8-bit terminal color in incompatible ways will fail at compile time or runtime depending on the context.

### Factory Functions

The header exposes two factory functions for creating `text_style` objects:
- **`fg(detail::color_type)`**: Sets the foreground color from either a `fmt::color` or `fmt::terminal_color`
- **`bg(detail::color_type)`**: Sets the background color using the same color types

These functions return `text_style` instances that can be further modified or passed directly to output functions.

## ANSI Escape Sequence Generation

When processing styled output, the library generates concrete ANSI escape codes through internal helper functions. The **`detail::make_foreground_color`**, **`detail::make_background_color`**, and **`detail::make_emphasis`** functions (located around lines 248-268) construct the appropriate escape sequences.

For RGB colors, the library emits the extended color code format `\x1b[38;2;<r>;<g>;<b>m` for foreground and `\x1b[48;2;<r>;<g>;<b>m` for background. Standard emphasis attributes generate codes like `\x1b[1m` for bold or `\x1b[4m` for underline. These sequences are automatically prepended to formatted output and terminated with the reset code `\x1b[0m` to prevent style bleeding.

## Output Functions and Styled Arguments

The color API integrates seamlessly with {fmt}'s formatting pipeline through overloaded output functions and specialized formatters.

### Global Print Overloads

The library provides overloads of **`print`** and **`println`** that accept a `text_style` as the first argument. These functions (defined around lines 278-340) prepend the generated ANSI escape codes, invoke the core formatting engine from [`include/fmt/format.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/format.h), then append the reset sequence. Similarly, **`vformat_to`** accepts a `text_style` parameter for writing to arbitrary output buffers.

### Per-Argument Styling

For applying different styles to individual values within a single format string, the library provides the **`styled()`** wrapper function. This creates a `detail::styled_arg<T>` object that the **`formatter<detail::styled_arg<T>>`** specialization (lines 522-552) processes by injecting escape codes immediately around the formatted value. This allows mixing styled and unstyled content within one format call without manual string concatenation.

## Complete Usage Examples

The following examples demonstrate practical applications of the color API using C++17 or later:

```cpp
#include <fmt/color.h>

int main() {
    // Simple colored output using RGB palette
    fmt::print(fg(fmt::color::steel_blue), "Steel blue text\n");

    // Combine foreground, background and emphasis attributes
    fmt::println(
        fmt::emphasis::bold | fmt::fg(fmt::color::red) | fmt::bg(fmt::color::yellow),
        "Bold red on yellow");

    // Per-argument styling inside a single format string
    fmt::print(
        "Normal {} {} {}\n",
        fmt::styled("red",   fmt::fg(fmt::color::red)),
        fmt::styled("green", fmt::fg(fmt::color::green) | fmt::emphasis::underline),
        fmt::styled("blue",  fmt::bg(fmt::color::blue)));

    // Using terminal colors (bright variants)
    fmt::println(fmt::emphasis::italic | fmt::fg(fmt::terminal_color::bright_magenta),
                 "Italic bright magenta");
}

```

Each example compiles with the header-only configuration of {fmt} or when linking against the compiled library. The `fg()` and `bg()` functions accept both RGB `color` values and indexed `terminal_color` values, while the `|` operator safely composes multiple style attributes into a single `text_style` object.

## Summary

- **[`include/fmt/color.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/color.h)** contains the complete ANSI color API, including `enum class color`, `enum class terminal_color`, and `enum class emphasis`.
- The **`text_style`** class composes foreground/background colors and emphasis flags using the `|` operator, storing data efficiently in a 64-bit packed format.
- Factory functions **`fg()`** and **`bg()`** create style objects, while **`styled()`** enables per-argument formatting within format strings.
- Output functions **`print`**, **`println`**, and **`vformat_to`** accept `text_style` arguments and automatically manage ANSI escape sequences including reset codes.
- The implementation prevents invalid color combinations at the type level, distinguishing between 24-bit RGB values and 8-bit terminal colors.

## Frequently Asked Questions

### Do I need to compile and link a separate library for color support?

No. All color functionality resides in [`include/fmt/color.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/color.h) and works with the header-only configuration of {fmt}. If you prefer using the compiled library, the same headers work with `libfmt` without additional dependencies.

### Can I mix RGB colors with terminal colors in the same style?

No. The `text_style` class implementation in [`include/fmt/color.h`](https://github.com/fmtlib/fmt/blob/main/include/fmt/color.h) enforces type safety by rejecting illegal mixtures through its `operator|=` logic. You must use either 24-bit RGB colors (`fmt::color`) or 8-bit terminal colors (`fmt::terminal_color`) consistently within a single foreground or background specification.

### How do I apply different styles to individual arguments in one format string?

Use the **`fmt::styled()`** wrapper function. It creates a `detail::styled_arg<T>` that the formatter processes individually, allowing you to write `fmt::print("{}", fmt::styled("text", fmt::fg(fmt::color::red)))` alongside other arguments with different or no styling.

### Are these color operations available at compile time?

Yes. The color enums, `text_style` composition operations, and `rgb` struct are all marked `constexpr` where possible. However, actual output to terminals via `fmt::print` naturally requires runtime execution.