Table Widget
Display tabular data with customizable columns, rows, borders, and styling
The Table widget displays structured data in rows and columns with configurable borders, alignment, and styling.
When to Use
Use Table when you need to display structured, multi-column data. Common scenarios:
- Data display: Show records, configuration settings, or query results
- Comparison: Side-by-side feature comparisons or specifications
- Reports: Formatted output with headers, totals, and alignment
For simple key-value pairs, consider using a table with hidden headers or a Grid. For proportional data visualization, use BarChart or BreakdownChart.
Basic Usage
Add columns first, then rows. Each row must have the same number of cells as columns.
var table = new Table();
// Add columns
table.AddColumn("Name");
table.AddColumn("Age");
table.AddColumn("City");
// Add rows
table.AddRow("Alice", "28", "New York");
table.AddRow("Bob", "35", "London");
table.AddRow("Charlie", "42", "Tokyo");
AnsiConsole.Write(table);
Styling
Border Styles
Choose from 18 built-in border styles. Use RoundedBorder() for a modern look or AsciiBorder() for maximum compatibility.
ShowBorder("Square", t => t.SquareBorder());
ShowBorder("Rounded", t => t.RoundedBorder());
ShowBorder("Minimal", t => t.MinimalBorder());
ShowBorder("Heavy", t => t.HeavyBorder());
ShowBorder("Double", t => t.DoubleBorder());
ShowBorder("ASCII", t => t.AsciiBorder());
static void ShowBorder(string name, Func<Table, Table> setBorder)
{
var table = new Table();
setBorder(table);
table.AddColumn("Border");
table.AddColumn("Style");
table.AddRow(name, "Example");
AnsiConsole.Write(table);
AnsiConsole.WriteLine();
}
Note
See the Table Border Reference for a visual guide to all border styles.
Border Colors
Use BorderColor() to match your application's theme. Combine with markup in headers for emphasis.
var table = new Table()
.RoundedBorder()
.BorderColor(Color.Blue);
table.AddColumn("[yellow]Product[/]");
table.AddColumn("[yellow]Price[/]");
table.AddRow("Widget", "[green]$9.99[/]");
table.AddRow("Gadget", "[green]$19.99[/]");
AnsiConsole.Write(table);
Column Configuration
Alignment
Align column content with LeftAligned(), Centered(), or RightAligned(). Right-align numeric data for easier comparison.
var table = new Table();
table.AddColumn("Left", col => col.LeftAligned());
table.AddColumn("Center", col => col.Centered());
table.AddColumn("Right", col => col.RightAligned());
table.AddRow("Text", "Text", "Text");
table.AddRow("Aligned", "Aligned", "Aligned");
table.AddRow("Left", "Center", "Right");
AnsiConsole.Write(table);
Width and Padding
Fix column widths with Width(), adjust spacing with PadLeft() and PadRight(), or prevent wrapping with NoWrap().
var table = new Table();
// Fixed width column
table.AddColumn("ID", col => col.Width(5).Centered());
// Column with custom padding
table.AddColumn("Description", col => col.Width(30).PadLeft(2).PadRight(2));
// NoWrap column for long text
table.AddColumn("Status", col => col.NoWrap().RightAligned());
table.AddRow("001", "This is a longer description that will wrap within the column width", "Active");
table.AddRow("002", "Short text", "Pending");
AnsiConsole.Write(table);
Headers and Footers
Headers display by default. Add footers for totals or summaries. Use HideHeaders() for key-value style layouts.
var table = new Table();
// Add columns with footers
table.AddColumn("Item");
table.AddColumn("Quantity", col => col.RightAligned());
table.AddColumn("Price", col => col.RightAligned());
table.AddRow("Apples", "10", "$5.00");
table.AddRow("Oranges", "5", "$3.50");
table.AddRow("Bananas", "8", "$4.00");
// Add footers
table.Columns[0].Footer = new Text("Total", new Style(foreground: Color.Yellow));
table.Columns[1].Footer = new Text("23", new Style(foreground: Color.Yellow));
table.Columns[2].Footer = new Text("$12.50", new Style(foreground: Color.Green, decoration: Decoration.Bold));
AnsiConsole.Write(table);
Hidden Headers
Tables without headers work well for configuration or property displays.
var table = new Table()
.HideHeaders()
.Border(TableBorder.None);
table.AddColumn("Key");
table.AddColumn("Value");
table.AddRow("[blue]Name:[/]", "Application");
table.AddRow("[blue]Version:[/]", "1.0.0");
table.AddRow("[blue]Status:[/]", "[green]Running[/]");
AnsiConsole.Write(table);
Titles and Captions
Add context with a title above the table and a caption below. Both support markup.
var table = new Table()
.RoundedBorder()
.BorderColor(Color.Aqua)
.Title("[yellow]Monthly Sales Report[/]")
.Caption("[grey]Data as of October 2025[/]");
table.AddColumn("Month");
table.AddColumn("Revenue", col => col.RightAligned());
table.AddRow("August", "$45,000");
table.AddRow("September", "$52,000");
table.AddRow("October", "$48,500");
AnsiConsole.Write(table);
Row Formatting
Row Separators
Use ShowRowSeparators() to add horizontal lines between rows, improving readability for dense data.
var table = new Table()
.RoundedBorder()
.ShowRowSeparators();
table.AddColumn("Category");
table.AddColumn("Item");
table.AddColumn("Count", col => col.RightAligned());
table.AddRow("Fruits", "Apples", "10");
table.AddRow("Fruits", "Oranges", "5");
table.AddRow("Vegetables", "Carrots", "15");
table.AddRow("Vegetables", "Broccoli", "8");
AnsiConsole.Write(table);
Empty Rows
Insert empty rows to group related data visually.
var table = new Table()
.RoundedBorder();
table.AddColumn("Section");
table.AddColumn("Value");
table.AddRow("[yellow]Header Info[/]", "Data");
table.AddEmptyRow();
table.AddRow("[yellow]Body Info[/]", "Data");
table.AddEmptyRow();
table.AddRow("[yellow]Footer Info[/]", "Data");
AnsiConsole.Write(table);
Layout
By default, tables use minimum width. Use Expand() to fill available console width—useful for reports or dashboards.
AnsiConsole.Write(new Markup("[yellow]Normal (collapsed) table:[/]\n"));
var normalTable = new Table();
normalTable.AddColumn("Name");
normalTable.AddColumn("Value");
normalTable.AddRow("Setting", "Value");
AnsiConsole.Write(normalTable);
AnsiConsole.WriteLine();
AnsiConsole.Write(new Markup("[yellow]Expanded table:[/]\n"));
var expandedTable = new Table()
.Expand();
expandedTable.AddColumn("Name");
expandedTable.AddColumn("Value");
expandedTable.AddRow("Setting", "Value");
AnsiConsole.Write(expandedTable);
Advanced Usage
Nested Tables
Embed tables within cells for hierarchical data or sub-groupings.
// Create inner table
var innerTable = new Table()
.RoundedBorder()
.BorderColor(Color.Grey);
innerTable.AddColumn("Detail");
innerTable.AddColumn("Value");
innerTable.AddRow("CPU", "95%");
innerTable.AddRow("Memory", "12GB");
// Create outer table
var outerTable = new Table()
.SquareBorder();
outerTable.AddColumn("Server");
outerTable.AddColumn("Metrics");
outerTable.AddRow(new Text("server-01"), innerTable);
AnsiConsole.Write(outerTable);
Mixed Content
Cells accept any IRenderable—combine Markup, Panels, and other widgets for rich layouts.
var table = new Table()
.RoundedBorder();
table.AddColumn("Type");
table.AddColumn("Example");
// Markup in cells
table.AddRow(new Text("Markup"), new Markup("[bold green]Success[/] :check_mark:"));
// Panel in a cell
var panel = new Panel("[yellow]Warning[/]")
.BorderColor(Color.Yellow)
.Padding(1, 0);
table.AddRow(new Text("Panel"), panel);
// Styled text
table.AddRow(new Text("Text"), new Text("Styled Text", new Style(foreground: Color.Aqua, decoration: Decoration.Italic)));
AnsiConsole.Write(table);
Dynamic Updates
Modify tables at runtime with UpdateCell(), InsertRow(), and RemoveRow().
var table = new Table()
.RoundedBorder();
table.AddColumn("ID");
table.AddColumn("Status");
table.AddColumn("Progress");
// Add initial rows
table.AddRow("Task 1", "[yellow]Pending[/]", "0%");
table.AddRow("Task 2", "[yellow]Pending[/]", "0%");
table.AddRow("Task 3", "[yellow]Pending[/]", "0%");
// Update cells dynamically
table.UpdateCell(0, 1, new Markup("[green]Complete[/]"));
table.UpdateCell(0, 2, new Markup("[green]100%[/]"));
table.UpdateCell(1, 1, new Markup("[blue]In Progress[/]"));
table.UpdateCell(1, 2, new Markup("[blue]45%[/]"));
// Insert a new row
table.InsertRow(3, new Markup("Task 4"), new Markup("[yellow]Pending[/]"), new Markup("0%"));
AnsiConsole.Write(table);
See Also
- Display Tabular Data - Step-by-step guide for common table tasks
- Table Border Reference - All 18 border styles with visual examples
- Color Reference - Available colors for borders and cells
- Building a Rich Console App - Learn Spectre.Console basics
- Understanding Spectre.Console's Rendering Model - How tables measure and layout
API Reference
A renderable table.
Constructors
public Table()
Initializes a new instance of the Table class.
Properties
Border
: TableBorderGets or sets the border.
Caption
: TableTitleGets or sets the table footnote.
Columns
: IReadOnlyList<TableColumn>Gets the table columns.
Expand
: boolGets or sets a value indicating whether or not the table should fit the available space. If false, the table width will be auto calculated. Defaults to false.
Rows
: TableRowCollectionGets the table rows.
ShowFooters
: boolGets or sets a value indicating whether or not table footers should be shown.
ShowHeaders
: boolGets or sets a value indicating whether or not table headers should be shown.
ShowRowSeparators
: boolGets or sets a value indicating whether or not row separators should be shown.
Title
: TableTitleGets or sets the table title.
UseSafeBorder
: boolGets or sets a value indicating whether or not to use a "safe" border on legacy consoles that might not be able to render non-ASCII characters.
Width
: int?Gets or sets the width of the table.
Methods
public Table AddColumn(TableColumn column)
Adds a column to the table.
Parameters:
column (TableColumn)Returns:
The same instance so that multiple calls can be chained.
Extension Methods
Table AddColumn(this Table table, string column, Action<TableColumn> configure)Adds a column to the table.
Returns:
The same instance so that multiple calls can be chained.
Table AddColumns(this Table table, string[] columns)Adds multiple columns to the table.
Returns:
The same instance so that multiple calls can be chained.
Table AddColumns(this Table table, TableColumn[] columns)Adds multiple columns to the table.
Returns:
The same instance so that multiple calls can be chained.
Table AddEmptyRow(this Table table)Adds an empty row to the table.
Returns:
The same instance so that multiple calls can be chained.
Table AddRow(this Table table, string[] columns)Adds a row to the table.
Returns:
The same instance so that multiple calls can be chained.
Table AddRow(this Table table, IRenderable[] columns)Adds a row to the table.
Returns:
The same instance so that multiple calls can be chained.
Table AddRow(this Table table, IEnumerable<IRenderable> columns)Adds a row to the table.
Returns:
The same instance so that multiple calls can be chained.
Table HideFooters(this Table table)Hides table footers.
Returns:
The same instance so that multiple calls can be chained.
Table HideHeaders(this Table table)Hides table headers.
Returns:
The same instance so that multiple calls can be chained.
Table HideRowSeparators(this Table table)Hides row separators.
Returns:
The same instance so that multiple calls can be chained.
Table InsertRow(this Table table, int index, string[] columns)Inserts a row in the table at the specified index.
Returns:
The same instance so that multiple calls can be chained.
Table InsertRow(this Table table, int index, IRenderable[] columns)Inserts a row in the table at the specified index.
Returns:
The same instance so that multiple calls can be chained.
Table InsertRow(this Table table, int index, IEnumerable<IRenderable> columns)Inserts a row in the table at the specified index.
Returns:
The same instance so that multiple calls can be chained.
Table RemoveRow(this Table table, int index)Removes a row from the table with the specified index.
Returns:
The same instance so that multiple calls can be chained.
Table ShowFooters(this Table table)Shows table footers.
Returns:
The same instance so that multiple calls can be chained.
Table ShowHeaders(this Table table)Shows table headers.
Returns:
The same instance so that multiple calls can be chained.
Table ShowRowSeparators(this Table table)Shows row separators.
Returns:
The same instance so that multiple calls can be chained.
Table UpdateCell(this Table table, int rowIndex, int columnIndex, string cellData)Updates a tables cell.
Returns:
The same instance so that multiple calls can be chained.
Table UpdateCell(this Table table, int rowIndex, int columnIndex, IRenderable cellData)Updates a tables cell.
Returns:
The same instance so that multiple calls can be chained.
Table Width(this Table table, int? width)Sets the table width.
Returns:
The same instance so that multiple calls can be chained.