How to Implement Docking and Split View Layouts in Dear ImGui

Enable the ImGuiConfigFlags_DockingEnable flag, create a DockSpace container with ImGui::DockSpace() or ImGui::DockSpaceOverViewport(), and use the DockBuilder* API to split nodes and dock windows into specific regions.

Dear ImGui provides a built-in docking system that transforms any window into a flexible container for split-view layouts. This architecture, implemented in the ocornut/imgui repository, centers on three core concepts: DockSpace containers, DockNode regions, and the DockBuilder API for procedural layout construction. Understanding how to enable and configure these components allows you to create persistent, user-adjustable panel layouts that work across all rendering backends.

Enable Docking Support

Before creating split views, you must enable the docking system during initialization. Set the ImGuiConfigFlags_DockingEnable flag in your ImGuiIO configuration, optionally enabling multi-viewport support for dragging windows outside the main application frame.

ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;          // Required: turn on docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;       // Optional: multi-viewport support

All docking state lives inside ImGui’s context, making the system completely decoupled from your rendering backend.

Create a DockSpace Container

A DockSpace is a hidden container that owns a hierarchy of dock nodes. You must create this space every frame inside a regular ImGui window that covers the area you want to dock into. The function ImGui::DockSpace() is declared in imgui.h (around line 4020) and requires a unique ImGuiID generated via ImGui::GetID().

// In your main render loop, after starting a new ImGui frame:
ImGui::Begin("MainViewport", nullptr,
             ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_NoTitleBar |
             ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize |
             ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoBringToFrontOnFocus |
             ImGuiWindowFlags_NoNavFocus);

// Make the window fill the entire viewport
ImGui::SetWindowPos(ImVec2(0,0));
ImGui::SetWindowSize(ImGui::GetIO().DisplaySize);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);

ImGui::BeginChild("DockSpaceArea", ImVec2(0,0), false,
                  ImGuiWindowFlags_NoDocking);

ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0,0), ImGuiDockNodeFlags_None);

ImGui::EndChild();
ImGui::PopStyleVar(2);
ImGui::End();

As a convenience, you can use ImGui::DockSpaceOverViewport() to automatically create a dock space covering the entire viewport without manually sizing a host window.

Build Split-View Layouts with DockBuilder

To create a deterministic starting layout rather than relying on manual user arrangement, use the DockBuilder API defined in imgui_internal.h (around line 3840). This procedural interface lets you split nodes horizontally or vertically and assign windows to specific regions before the first frame renders.

The following example creates a three-panel layout: a left panel occupying 30% of the width, and a right side split into top (60%) and bottom (40%) sections.

// Call this once after the first frame when the dockspace exists
static bool layout_created = false;
if (!layout_created) {
    ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
    
    // Clear any previous layout and create a root node
    ImGui::DockBuilderRemoveNode(dockspace_id);
    ImGui::DockBuilderAddNode(dockspace_id, ImGuiDockNodeFlags_None);
    ImGui::DockBuilderSetNodeSize(dockspace_id, ImGui::GetIO().DisplaySize);

    // Split the root node into left (30%) and right (70%)
    ImGuiID dock_main_id = dockspace_id;
    ImGuiID dock_id_left, dock_id_right;
    ImGui::DockBuilderSplitNode(dock_main_id, ImGuiDir_Left, 0.30f, 
                               &dock_id_left, &dock_id_right);

    // Split the right side into top (60%) and bottom (40%)
    ImGuiID dock_id_right_top, dock_id_right_bottom;
    ImGui::DockBuilderSplitNode(dock_id_right, ImGuiDir_Up, 0.60f,
                               &dock_id_right_top, &dock_id_right_bottom);

    // Dock specific windows into the leaf nodes
    ImGui::DockBuilderDockWindow("Editor", dock_id_left);
    ImGui::DockBuilderDockWindow("Console", dock_id_right_bottom);
    ImGui::DockBuilderDockWindow("Inspector", dock_id_right_top);

    ImGui::DockBuilderFinish(dockspace_id); // Finalize the layout
    layout_created = true;
}

The DockBuilderSplitNode function takes a direction (ImGuiDir_Left, ImGuiDir_Right, ImGuiDir_Up, ImGuiDir_Down), a split ratio, and two output IDs for the resulting child nodes.

Render Dockable Windows

Once the dock space exists, regular ImGui windows automatically dock when their title bars are dragged over a dock node, or when pre-assigned via the builder. Simply create windows as usual with matching names.

// Editor panel
ImGui::Begin("Editor");
ImGui::Text("Write your UI here...");
ImGui::End();

// Console panel
ImGui::Begin("Console");
ImGui::TextWrapped("Log output …");
ImGui::End();

// Inspector panel
ImGui::Begin("Inspector");
ImGui::BulletText("Selected entity: Player");
ImGui::End();

Key Source Files and Architecture

Understanding the implementation helps debug complex layouts. The docking system relies on three primary files in the ocornut/imgui repository:

  • imgui.h – Declares the public API including ImGui::DockSpace(), ImGui::DockSpaceOverViewport(), and docking flags.
  • imgui_internal.h – Contains the DockNode structure (around line 3550) representing rectangular regions, and the DockBuilder* functions (around line 3840) for procedural manipulation.
  • imgui.cpp – Implements the docking backend including node creation, tab handling, and split logic.

The DockNode structure represents individual rectangular regions that can host windows or be split into child nodes. When ImGui::DockSpace() is called, ImGui looks up or creates a DockNode tree attached to the supplied ImGuiID, maintaining all state internally.

Summary

  • Enable docking by setting ImGuiConfigFlags_DockingEnable in your ImGuiIO configuration during initialization.
  • Create a DockSpace every frame using ImGui::DockSpace() inside a host window, or use ImGui::DockSpaceOverViewport() for full-screen coverage.
  • Build deterministic layouts with the DockBuilder* API to split nodes and assign windows to specific regions before the first render.
  • Render windows normally with ImGui::Begin/End; they automatically dock based on user interaction or builder assignments.
  • Reference internal headers (imgui_internal.h) when using the builder API, as these functions are not exposed in the public imgui.h interface.

Frequently Asked Questions

How do I enable docking support in Dear ImGui?

Set the ImGuiConfigFlags_DockingEnable flag in your ImGuiIO configuration before the first frame. This flag activates the internal docking system that manages node hierarchies and window placement.

What is the difference between DockSpace and DockSpaceOverViewport?

ImGui::DockSpace() requires you to manually create a host window and call the function inside it every frame, giving you precise control over the dockable area. ImGui::DockSpaceOverViewport() is a convenience wrapper that automatically creates a full-screen dock space over the current or specified viewport with appropriate window flags.

Do I need to call DockBuilder functions every frame?

No. The DockBuilder* API is designed for initial layout construction or explicit layout resets. Call these functions once after creating your dock space, typically guarded by a static boolean flag. However, you must call ImGui::DockSpace() every frame to maintain the docking context.

Can docked windows be dragged outside the main application window?

Yes, when you enable both ImGuiConfigFlags_DockingEnable and ImGuiConfigFlags_ViewportsEnable. Multi-viewport support allows docked windows to be dragged outside the main viewport into their own floating OS windows while remaining part of the dock node hierarchy.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →