# How to Manage ImGui Docking and Tab Windows: A Complete Guide to the Built-In Docking System

> Learn to manage ImGui docking and tab windows with this complete guide. Enable ImGui docking and build flexible UIs by splitting and persisting windows.

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

---

**Enable `ImGuiConfigFlags_DockingEnable` in the `ImGuiIO` configuration, create a host dock space with `ImGui::DockSpace()`, and use `ImGuiTabBarFlags_DockingEnable` when building tab bars so that windows and tabs can be dragged, split, and persisted between sessions.**

Dear ImGui (ocornut/imgui) ships with a built-in docking system that lets you create IDE-style layouts without external dependencies. Learning how to manage ImGui docking and tab windows starts with three configuration and API calls that activate dock nodes, host spaces, and tab grouping. The entire implementation is compiled from the master branch and exposed through headers and functions found in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp).

## Enable Docking with ImGuiConfigFlags_DockingEnable

Set the flag on the IO object during setup. This flag is declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and activates the docking code path compiled under the `IMGUI_HAS_DOCK` preprocessor guard.

```cpp
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;

```

## Create a Dock Space Host Window

Call `ImGui::DockSpace()` inside a host window to allocate a region that receives dockable windows. The convenience wrapper `ImGui::DockSpaceOverViewport()` is also available. In [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp), the `DockSpace()` implementation handles node allocation and layout resolution.

```cpp
ImGui::Begin("MainDockSpace", nullptr,
             ImGuiWindowFlags_NoTitleBar |
             ImGuiWindowFlags_NoCollapse |
             ImGuiWindowFlags_NoResize |
             ImGuiWindowFlags_NoMove |
             ImGuiWindowFlags_NoBringToFrontOnFocus |
             ImGuiWindowFlags_NoNavFocus);
ImGuiID dockspace_id = ImGui::DockSpace(ImGui::GetID("MyDockSpace"));
ImGui::End();

```

## Assign Windows to Specific Dock Nodes

After you have a dock node ID, use `ImGui::SetNextWindowDockID()` to force a window to open inside that node.

```cpp
ImGui::SetNextWindowDockID(my_dock_id, ImGuiCond_Once);
ImGui::Begin("MyFixedPanel");
ImGui::Text("This window always starts docked in the same node.");
ImGui::End();

```

## Program Default Layouts with the Dock Builder API

For tool-style applications, use the `ImGui::DockBuilder*` family declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) and defined in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) to split nodes and assign windows before the first frame.

```cpp
ImGuiID dock_main = ImGui::GetID("MainDockSpace");
ImGui::DockBuilderRemoveNode(dock_main);
ImGui::DockBuilderAddNode(dock_main, ImGuiDockNodeFlags_None);
ImGui::DockBuilderSetNodeSize(dock_main, ImGui::GetMainViewport()->Size);

ImGuiID dock_left, dock_right;
dock_left = ImGui::DockBuilderSplitNode(dock_main, ImGuiDir_Left, 0.25f, nullptr, &dock_main);
dock_right = dock_main;

ImGui::DockBuilderDockWindow("LeftPanel", dock_left);
ImGui::DockBuilderDockWindow("RightPanel", dock_right);
ImGui::DockBuilderFinish(dock_main);

```

## Build Tab Windows That Integrate with Docking

Tab bars participate in the docking system when you pass `ImGuiTabBarFlags_DockingEnable`. This lets users drag an entire tab group between dock slots.

```cpp
ImGui::Begin("TabHost");
if (ImGui::BeginTabBar("MyTabBar", ImGuiTabBarFlags_DockingEnable)) {
    if (ImGui::BeginTabItem("Tab A")) {
        ImGui::Text("Content of Tab A");
        ImGui::EndTabItem();
    }
    if (ImGui::BeginTabItem("Tab B")) {
        ImGui::Text("Content of Tab B");
        ImGui::EndTabItem();
    }
    ImGui::EndTabBar();
}
ImGui::End();

```

## Persist and Restore Docking Layouts

Docking hierarchies are written to the `.ini` file as `[Dock][...]` entries. Call `ImGui::SaveIniSettingsToDisk()` before shutdown and `ImGui::LoadIniSettingsFromDisk()` at startup.

```cpp
ImGui::SaveIniSettingsToDisk("my_imgui_layout.ini");
// ...
ImGui::LoadIniSettingsFromDisk("my_imgui_layout.ini");

```

## Key Source Files and Internal Architecture

The docking system relies on a few critical files in the ocornut/imgui repository. [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) contains the public flags and `DockSpace()` prototype, while [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) implements the core docking logic, layout persistence, and the `DockBuilder*` family. Internal structures such as `ImGuiDockNode` and `ImGuiDockContext` are defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h). You can find usage examples in [`examples/example_sdl2_opengl3/main.cpp`](https://github.com/ocornut/imgui/blob/main/examples/example_sdl2_opengl3/main.cpp) and the interactive docking demo inside [`imgui_demo.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_demo.cpp).

## Summary

- Enable docking globally by setting `ImGuiConfigFlags_DockingEnable` in `ImGuiIO`.
- Host dockable panels inside a region created with `ImGui::DockSpace()` or `ImGui::DockSpaceOverViewport()`.
- Pin windows to nodes with `ImGui::SetNextWindowDockID()` or build default trees with the `ImGui::DockBuilder*` API.
- Combine tabs into draggable groups by passing `ImGuiTabBarFlags_DockingEnable` to `ImGui::BeginTabBar()`.
- Persist layouts between sessions using `ImGui::SaveIniSettingsToDisk()` and `ImGui::LoadIniSettingsFromDisk()`.

## Frequently Asked Questions

### Why is my dock space not interacting with windows?

Docking only activates if `ImGuiConfigFlags_DockingEnable` is set in the `ImGuiIO` object before the first frame, and if the host window containing `ImGui::DockSpace()` is submitted before the child windows. Verify that the dock space ID is consistent and that the host window uses correct flags such as `ImGuiWindowFlags_NoNavFocus`.

### Can I dock windows without a user dragging them?

Yes. Use `ImGui::SetNextWindowDockID()` to place a single window, or use the `ImGui::DockBuilder*` API to split nodes and assign multiple windows to a default tree programmatically as implemented in [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp).

### Do tab bars require a separate dock space to work?

No. Tab bars that use `ImGuiTabBarFlags_DockingEnable` live inside normal windows and participate in the same docking system. You can drag the entire tab group into any existing dock node because the tab bar integrates with the `ImGuiDockContext` structures defined in [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h).

### How do I reset the docking layout to the original default?

Call `ImGui::DockBuilderRemoveNode()` on your dock space ID before rebuilding the tree with `ImGui::DockBuilderAddNode()` and `ImGui::DockBuilderDockWindow()`. Alternatively, delete the saved `.ini` file and restart so that `ImGui::LoadIniSettingsFromDisk()` finds no prior state.