This page documents Rich's width measurement system (rich/measure.py, rich/constrain.py) and the ratio-based space distribution utilities (rich/_ratio.py) used when computing column and panel sizes. The Layout class itself (splitting, splitters, the Region type) is documented in Trees and Layout. For the rendering pipeline that consumes these measurements, see Rendering Pipeline.
Before Rich renders a renderable to the terminal, it often needs to know how wide that renderable wants to be. The measurement system answers two questions:
These two values drive decisions in tables (column sizing), Columns (how many columns fit per row), Align (centering math), and Layout (how to divide a region between children).
Measurement NamedTupleFile: rich/measure.py11-122
Measurement is a two-field NamedTuple defined at the module level:
Measurement(minimum: int, maximum: int)
| Field | Type | Meaning |
|---|---|---|
minimum | int | Smallest usable width in terminal cells |
maximum | int | Preferred width if space is unconstrained |
| Method | Signature | Description |
|---|---|---|
span | @property → int | maximum - minimum |
normalize() | → Measurement | Clamps so that 0 ≤ minimum ≤ maximum |
with_maximum(width) | → Measurement | Returns a copy where both fields are ≤ width |
with_minimum(width) | → Measurement | Returns a copy where both fields are ≥ max(0, width) |
clamp(min_width, max_width) | → Measurement | Composes with_minimum and with_maximum; either argument may be None |
normalize is always called by Measurement.get before returning to callers, so internal __rich_measure__ implementations do not need to worry about producing invalid ranges.
Measurement.get() – the primary entry pointMeasurement.get(console, options, renderable) → Measurement
This classmethod is the standard way to measure any renderable. Its logic:
Measurement(0, 0) immediately if options.max_width < 1.Text objects via console.render_str.rich_cast to resolve __rich__ objects.__rich_measure__, calls it and applies normalize().with_maximum(max_width).__rich_console__ (no __rich_measure__), returns Measurement(0, max_width) — i.e., it can use any width up to the console limit.errors.NotRenderableError if the object is not renderable at all.Sources: rich/measure.py78-122
__rich_measure__ ProtocolAny class can opt into precise width reporting by implementing:
Without this method, Rich conservatively assumes the object can fill any available width (Measurement(0, max_width)). With it, layout containers can make tighter decisions.
Examples of __rich_measure__ in the codebase:
| Class | File | Behaviour |
|---|---|---|
Align | rich/align.py235-239 | Delegates to Measurement.get on the wrapped renderable |
VerticalCenter | rich/align.py292-296 | Same delegation pattern |
Constrain | rich/constrain.py31-37 | Calls Measurement.get after clamping options to self.width |
Table | rich/table.py | Returns fixed measurement when width is set; computes column bounds otherwise |
The following diagram shows the call chain when a container (e.g., Columns) measures its children:
Diagram: Measurement.get Resolution Chain
Sources: rich/measure.py78-122 rich/align.py235-239 rich/constrain.py31-37
measure_renderables()measure_renderables(console, options, renderables) → Measurement
Measures a sequence of renderables and returns a combined Measurement:
minimum = the largest minimum across all renderables (the widest minimum requirement).maximum = the largest maximum across all renderables (the widest preferred width).Used by Columns to determine how wide each column in a row needs to be.
Returns Measurement(0, 0) for an empty sequence.
Sources: rich/measure.py125-151
ConstrainConstrain is a renderable wrapper that limits the width of another renderable. It is used internally by Align and Columns.
__rich_console__: renders the inner object with options.max_width set to min(self.width, options.max_width).__rich_measure__: calls Measurement.get after narrowing options to self.width, so the constrained measurement propagates correctly up to any parent container.If width is None, Constrain passes through transparently.
Sources: rich/constrain.py10-37
These three functions in rich/_ratio.py convert abstract ratio/size constraints into concrete integer column or row widths. They are consumed by Table column sizing, Columns layout, and the Layout splitters.
Diagram: Ratio Utilities and Their Callers
Sources: rich/_ratio.py14-141 rich/layout.py101-138
ratio_resolveratio_resolve(total: int, edges: Sequence[Edge]) -> List[int]
Divides total space among edges, where each Edge has:
| Attribute | Meaning |
|---|---|
size | Fixed size in characters; None means "flexible" |
ratio | Weight for flexible allocation |
minimum_size | Minimum characters this edge must receive |
Algorithm:
size-fixed edges as resolved.ratio.minimum_size, lock it to minimum_size and repeat.fractions.Fraction for precision).If the sum of minimum_size values exceeds total, the returned sizes will exceed total — the caller is expected to clip content.
Used by both RowSplitter.divide and ColumnSplitter.divide in rich/layout.py rich/layout.py101-138
ratio_reduceratio_reduce(total: int, ratios: List[int], maximums: List[int], values: List[int]) -> List[int]
Reduces a list of values by distributing a total reduction proportionally across slots. Slots with a maximum of 0 are excluded from reduction. Used by Table to shrink column widths when the available space is less than the sum of preferred widths.
ratio_distributeratio_distribute(total: int, ratios: List[int], minimums: Optional[List[int]] = None) -> List[int]
Distributes total into slots according to ratios, with optional per-slot minimums. The result is guaranteed to sum exactly to total. Uses math.ceil to handle fractional allocation, crediting the remainder to subsequent slots. Used by Table to expand column widths when distributing surplus space.
Layout rich/layout.py142-416 uses ratio_resolve indirectly through its Splitter subclasses.
Diagram: Layout Splitting Flow
The Layout class treats each child as an Edge-like object: it exposes size, ratio, and minimum_size attributes, satisfying the Edge protocol expected by ratio_resolve.
Layout Attribute | Edge Protocol Attribute | Role |
|---|---|---|
size | size | Fixed pixel count (rows or columns) |
ratio | ratio | Proportional weight (default 1) |
minimum_size | minimum_size | Floor on allocated space (default 1) |
RowSplitter resolves widths; ColumnSplitter resolves heights. Both use the same ratio_resolve function on the same attribute set.
Sources: rich/layout.py101-138 rich/_ratio.py14-72 rich/layout.py345-393
Columns Width AlgorithmColumns.__rich_console__ rich/columns.py62-171 shows a typical use of Measurement.get:
maximum width via Measurement.get.column_count columns; check if sum(column_widths) + padding fits within options.max_width.column_count and retry.Table.grid with the computed column widths.The equal=True option replaces all individual widths with the global maximum before the column-fitting loop.
Sources: rich/columns.py62-171
| Symbol | Location | Role |
|---|---|---|
Measurement | rich/measure.py11 | NamedTuple holding (minimum, maximum) width bounds |
Measurement.get | rich/measure.py78 | Resolves measurement for any renderable |
measure_renderables | rich/measure.py125 | Aggregates measurements across a sequence |
Constrain | rich/constrain.py10 | Renderable wrapper that enforces a width cap |
ratio_resolve | rich/_ratio.py14 | Divides space by size/ratio/minimum constraints |
ratio_reduce | rich/_ratio.py75 | Proportionally reduces values to fit a total |
ratio_distribute | rich/_ratio.py107 | Proportionally distributes a total across ratios |
Edge (Protocol) | rich/_ratio.py6 | Duck-type contract for ratio_resolve consumers |
RowSplitter | rich/layout.py101 | Divides a Region into side-by-side columns |
ColumnSplitter | rich/layout.py121 | Divides a Region into stacked rows |
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.