# How to Use Dear ImGui Tables API (BeginTable) for Complex Layouts

> Master complex layouts with Dear ImGui's Tables API and BeginTable. Explore scrolling, sorting, nested tables, and per-cell formatting for a modern grid system.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-30

---

**Dear ImGui's Tables API provides a modern, flexible grid system through `BeginTable()` and `EndTable()`, replacing the legacy Columns API with support for scrolling, sorting, nested tables, and per-cell formatting.**

The **Dear ImGui Tables API** (available in the [ocornut/imgui](https://github.com/ocornut/imgui) repository) offers a robust framework for creating data grids and complex widget layouts. Introduced to supersede the older Columns API, this system handles automatic row/column management, horizontal scrolling, and dynamic sizing through declarative flags and helper functions declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and implemented in [`imgui_tables.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_tables.cpp).

## Core Tables API Workflow

Creating a table requires a strict lifecycle: initialization, column setup, row population, and termination.

### Initializing with BeginTable

Call `BeginTable()` to instantiate a new table context. This function accepts an identifier, column count, optional flags for borders and scrolling, and sizing constraints. The declaration in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)【https://github.com/ocornut/imgui/blob/master/imgui.h#L882-L909】 shows it returns a boolean indicating visibility—always wrap table content in an `if` block to avoid processing clipped elements.

```cpp
if (ImGui::BeginTable("MyTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
    // Column setup and row data here
    ImGui::EndTable();
}

```

### Configuring Columns with TableSetupColumn

Before populating data, declare column properties using `TableSetupColumn()`. This function accepts flags like `ImGuiTableColumnFlags_WidthFixed` or `ImGuiTableColumnFlags_WidthStretch` to control sizing behavior, as defined in the `ImGuiTableColumnFlags` enum【https://github.com/ocornut/imgui/blob/master/imgui.h#L2043】.

```cpp
ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed, 50.0f);
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableHeadersRow(); // Creates header row from setup calls

```

### Populating Rows and Cells

Use `TableNextRow()` to advance to a new row, then `TableNextColumn()` to iterate through cells sequentially. For random access, `TableSetColumnIndex()` allows jumping to specific columns. The implementation in [`imgui_tables.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_tables.cpp) handles automatic row wrapping when column limits are reached.

## Implementing Complex Layout Patterns

### Fixed versus Stretch Column Sizing

Control column behavior through flags passed to `TableSetupColumn()`. **Fixed width** columns maintain absolute pixel sizes, while **stretch** columns distribute available space proportionally.

```cpp
ImGui::BeginTable("SizingDemo", 3, ImGuiTableFlags_SizingStretchSame);
ImGui::TableSetupColumn("Fixed", ImGuiTableColumnFlags_WidthFixed, 100.0f);
ImGui::TableSetupColumn("Stretch1", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Stretch2", ImGuiTableColumnFlags_WidthStretch);

```

### Nested Tables for Hierarchical Data

The Tables API supports recursion because each `BeginTable()` creates an isolated child window. You can embed tables within table cells to create master-detail views or complex grid hierarchies.

```cpp
if (ImGui::BeginTable("Outer", 2, ImGuiTableFlags_Borders)) {
    ImGui::TableNextRow();
    ImGui::TableNextColumn();
    ImGui::Text("Summary Data");
    
    ImGui::TableNextColumn();
    if (ImGui::BeginTable("Inner", 3, ImGuiTableFlags_Borders)) {
        // Inner table content
        ImGui::EndTable();
    }
    ImGui::EndTable();
}

```

### Column Spanning and Cell Formatting

To span a cell across multiple columns, advance to the starting column with `TableSetColumnIndex()`, render your content, and skip subsequent `TableNextColumn()` calls for the spanned columns. Use `TableSetBgColor()` to apply background colors to specific cells (`ImGuiTableBgTarget_CellBg`) or entire rows (`ImGuiTableBgTarget_RowBg0`).

```cpp
ImGui::TableNextRow();
ImGui::TableSetColumnIndex(0);
ImGui::Text("Spans two columns");
// Skip column 1 to create span effect
ImGui::TableSetColumnIndex(2);
ImGui::Text("Third column");
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, IM_COL32(40, 40, 40, 255));

```

### Frozen Headers and Scrolling

For large datasets, call `TableSetupScrollFreeze(columns, rows)` to lock headers in place during vertical or horizontal scrolling. This creates Excel-like frozen panes. Combine with `ImGuiTableFlags_ScrollX` or `ImGuiTableFlags_ScrollY` to enable scrollable containers.

```cpp
ImGui::BeginTable("Scrollable", 4, ImGuiTableFlags_ScrollX | ImGuiTableFlags_Borders);
ImGui::TableSetupScrollFreeze(1, 1); // Freeze first column and header row

```

## Practical Implementation Examples

### Basic Data Grid with Fixed Widths

```cpp
if (ImGui::BeginTable("SimpleTable", 3, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
    ImGui::TableSetupColumn("ID", ImGuiTableColumnFlags_WidthFixed);
    ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed);
    ImGui::TableSetupColumn("Score", ImGuiTableColumnFlags_WidthFixed);
    ImGui::TableHeadersRow();

    for (int i = 0; i < 5; ++i) {
        ImGui::TableNextRow();
        ImGui::TableNextColumn(); ImGui::Text("%d", i);
        ImGui::TableNextColumn(); ImGui::Text("Player %d", i);
        ImGui::TableNextColumn(); ImGui::Text("%d", rand() % 100);
    }
    ImGui::EndTable();
}

```

### Stretch Columns with Horizontal Scrolling

```cpp
ImGui::BeginTable("StretchTable", 4,
                  ImGuiTableFlags_Borders |
                  ImGuiTableFlags_ScrollX |
                  ImGuiTableFlags_SizingStretchSame,
                  ImVec2(0.0f, 0.0f), 0.0f);
{
    ImGui::TableSetupColumn("A");
    ImGui::TableSetupColumn("B");
    ImGui::TableSetupColumn("C");
    ImGui::TableSetupColumn("D");
    ImGui::TableHeadersRow();

    for (int row = 0; row < 10; ++row) {
        ImGui::TableNextRow();
        for (int col = 0; col < 4; ++col) {
            ImGui::TableNextColumn();
            ImGui::Text("R%dC%d", row, col);
        }
    }
}
ImGui::EndTable();

```

### Advanced Layout with Row Spanning and Colors

```cpp
if (ImGui::BeginTable("ComplexLayout", 3, ImGuiTableFlags_Borders)) {
    ImGui::TableSetupColumn("Name");
    ImGui::TableSetupColumn("Description");
    ImGui::TableSetupColumn("Value");
    ImGui::TableHeadersRow();

    ImGui::TableNextRow();
    ImGui::TableSetColumnIndex(0);
    ImGui::Text("Item A");
    ImGui::TableSetColumnIndex(1);
    ImGui::TextUnformatted("This text spans across the description and value columns visually");
    ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, IM_COL32(30, 30, 160, 255));
    
    ImGui::EndTable();
}

```

## Key Source Files and Architecture

Understanding the implementation requires examining three primary files in the [ocornut/imgui](https://github.com/ocornut/imgui) repository:

- **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)**【https://github.com/ocornut/imgui/blob/master/imgui.h#L882-L909】: Contains public API declarations including `BeginTable()`, `EndTable()`, `TableSetupColumn()`, and the `ImGuiTableFlags` / `ImGuiTableColumnFlags` enums.
- **[`imgui_tables.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_tables.cpp)**: Houses the complete table layout engine, row/column iteration logic, and rendering implementation.
- **[`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h)**【https://github.com/ocornut/imgui/blob/master/imgui_internal.h#L3068-L3177】: Defines internal structures `ImGuiTable` and `ImGuiTableColumn` used by the layout engine to manage state, clipping, and sizing calculations.

## Summary

- **Always guard table content** with the boolean returned by `BeginTable()` to skip rendering when the table is off-screen.
- **Configure columns upfront** using `TableSetupColumn()` with specific flags (`WidthFixed`, `WidthStretch`, `NoResize`) to control layout behavior.
- **Support complex layouts** through nested tables, column spanning (by skipping `TableNextColumn()` calls), and background color customization via `TableSetBgColor()`.
- **Enable scrolling and freezing** with `TableSetupScrollFreeze()` and table flags to handle large datasets efficiently.
- **Reference the source** in [`imgui_tables.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_tables.cpp) and [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) for advanced usage patterns and performance optimizations.

## Frequently Asked Questions

### What is the difference between Dear ImGui Tables API and the old Columns API?

The **Tables API** (`BeginTable`/`EndTable`) is a complete rewrite that provides proper horizontal scrolling, per-column sizing policies, sorting capabilities, and frozen rows/columns. The old Columns API (`ImGui::Columns`) lacked these features and is considered deprecated; Tables handle layout calculations in [`imgui_tables.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_tables.cpp) rather than the general window layout code.

### How do I make columns resizable or fixed width in BeginTable?

Pass specific flags to `TableSetupColumn()`: use `ImGuiTableColumnFlags_WidthFixed` with an explicit pixel width to prevent resizing, or `ImGuiTableColumnFlags_WidthStretch` with a weight parameter to allow dynamic resizing. The `ImGuiTableFlags_Resizable` flag on the table itself enables interactive resizing via drag handles.

### Can I nest tables inside other tables using BeginTable?

Yes, you can call `BeginTable()` inside a table cell (after `TableNextColumn()`). Each table creates its own child window context with independent scrolling and clipping, as managed by the `ImGuiTable` structures in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h). This allows for complex hierarchical layouts without coordinate conflicts.

### How do I freeze header rows when scrolling in Dear ImGui tables?

Call `TableSetupScrollFreeze(0, 1)` after `BeginTable()` to freeze the first row (typically headers), or `TableSetupScrollFreeze(1, 1)` to freeze both the first column and first row. This locks the specified rows/columns in place while the rest of the table scrolls, implemented through clipping rect calculations in [`imgui_tables.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_tables.cpp).