# How the Rich Styled Wrapper Applies Consistent Styling to Renderables

> Discover how the Styled wrapper ensures consistent styling in Textualize Rich. It intercepts renderables, resolves styles, and applies them uniformly to ensure a cohesive look.

- Repository: [Textualize/rich](https://github.com/Textualize/rich)
- Tags: internals
- Published: 2026-03-06

---

**The `Styled` wrapper enforces consistent styling by intercepting the renderable protocol in `__rich_console__`, resolving the target style against the console, rendering the inner object into segments, and uniformly applying the resolved style to every segment via `Segment.apply_style`.**

The `Styled` class in the Textualize/rich repository provides a powerful mechanism for applying uniform visual styles to any renderable object. Whether you need to add a blue background to a complex table or force bold red text across an entire panel, the **Rich Styled wrapper** guarantees that your specified style overrides or augments the renderable's native formatting consistently.

## How the Styled Wrapper Intercepts Rendering

To understand how consistent styling is enforced, examine the `Styled` class implementation in [`rich/styled.py`](https://github.com/Textualize/rich/blob/main/rich/styled.py). The wrapper implements the **`__rich_console__`** method, which the console calls when preparing output. This method executes a precise three-step pipeline to ensure that every piece of the wrapped content shares the same visual appearance.

### Step 1: Resolve the Target Style

First, the wrapper converts the user-provided style argument into a concrete **Style** object. It delegates this resolution to the console's style registry:

```python
style = console.get_style(self.style)  # rich/console.py

```

This call handles style strings, pre-built `Style` objects, or any valid `StyleType`, returning a normalized style ready for application across all segments.

### Step 2: Render the Wrapped Object

Next, `Styled` delegates rendering of the inner object to obtain its raw segment representation:

```python
rendered_segments = console.render(self.renderable, options)  # rich/console.py

```

This returns an iterable of **Segment** objects containing the text and any pre-existing styles from the original renderable's internal logic.

### Step 3: Apply Style Uniformly

Finally, the wrapper applies the resolved style to every segment. It calls **`Segment.apply_style`** from [`rich/segment.py`](https://github.com/Textualize/rich/blob/main/rich/segment.py) to merge the new style with any existing formatting:

```python
segments = Segment.apply_style(rendered_segments, style)  # rich/segment.py

return segments

```

This method walks every segment and merges the supplied style, preserving original formatting that does not clash while ensuring the new style attributes apply consistently across the entire output.

## Preserving Layout Measurements

The `Styled` wrapper also implements **`__rich_measure__`** to ensure layout calculations remain accurate. Rather than calculating its own dimensions, it forwards the measurement request directly to the wrapped object:

```python
def __rich_measure__(self, console, options):
    return Measurement.get(console, options, self.renderable)  # rich/measure.py

```

This delegation ensures that padding, margins, and size constraints computed by the console reflect the underlying renderable's true dimensions, not the wrapper itself.

## Using the Styled Wrapper in Practice

You can apply the **Rich Styled wrapper** to any renderable, including panels, tables, and text objects. Here are practical implementations demonstrating consistent styling:

```python
from rich import print
from rich.panel import Panel
from rich.styled import Styled
from rich.table import Table

# Apply a blue background to an entire panel

blue_panel = Styled(Panel("Hello, world!"), "on blue")
print(blue_panel)

# Apply bold red text to a table, overriding the table's own cell styles

table = Table()
table.add_column("Name")
table.add_row("[green]Alice[/]")
table.add_row("[yellow]Bob[/]")
styled_table = Styled(table, "bold red")
print(styled_table)

# Nesting works – the inner Styled is rendered first, then the outer one

nested = Styled(Styled(Panel("Nested"), "on magenta"), "underline")
print(nested)

```

## Summary

- The **`Styled`** class wraps any renderable to apply consistent styling across the entire output, regardless of the renderable's own internal styling logic.
- **Style resolution** occurs via `console.get_style()` in [`rich/console.py`](https://github.com/Textualize/rich/blob/main/rich/console.py), normalizing user input into concrete `Style` objects.
- **Uniform application** happens through `Segment.apply_style()` in [`rich/segment.py`](https://github.com/Textualize/rich/blob/main/rich/segment.py), merging the new style with existing segment formatting.
- **Layout integrity** is maintained by delegating measurement to the inner renderable via `Measurement.get()` in [`rich/measure.py`](https://github.com/Textualize/rich/blob/main/rich/measure.py).
- **Nesting is supported**, allowing multiple `Styled` layers to combine progressively.

## Frequently Asked Questions

### Can Styled wrappers be nested to combine multiple styles?

Yes, you can nest `Styled` objects to layer styles progressively. The inner wrapper renders first with its specific style, then the outer wrapper applies its style to the resulting segments. This allows you to combine attributes like background colors from one wrapper with text decorations from another, as both wrappers simply return transformed segment iterables that the next layer can consume.

### How does the Styled wrapper handle renderables that already have their own styles?

The `Segment.apply_style()` method merges the new style with existing segment styles rather than replacing them completely. When you wrap a table containing green and yellow cells with `Styled(..., "bold red")`, the text becomes bold and red while preserving structural formatting, though color attributes may be overridden depending on the specific merge rules implemented in [`rich/segment.py`](https://github.com/Textualize/rich/blob/main/rich/segment.py).

### Does wrapping an object with Styled change its dimensions?

No, the `Styled` wrapper delegates all measurement to the underlying renderable through `Measurement.get()` as implemented in [`rich/measure.py`](https://github.com/Textualize/rich/blob/main/rich/measure.py). The console calculates padding, alignment, and container sizes based on the wrapped object's true dimensions, ensuring the visual layout remains identical to the unwrapped version.

### What types of objects can be wrapped with Styled?

Any object implementing the Rich renderable protocol can be wrapped, including `Panel`, `Table`, `Text`, `Syntax`, and even other `Styled` instances. As long as the object provides `__rich_console__` and optionally `__rich_measure__` methods, the wrapper can intercept and transform its output according to the pipeline defined in [`rich/styled.py`](https://github.com/Textualize/rich/blob/main/rich/styled.py).