How to Customize the Visual Appearance of Dear ImGui Using ImGuiStyle

Dear ImGui's visual appearance is controlled entirely by the ImGuiStyle structure, which stores every color, spacing, and sizing value used to render the UI, accessible via ImGui::GetStyle() for global changes or temporarily overridden per-widget using PushStyleColor() and PushStyleVar().

Customizing the visual appearance of Dear ImGui using ImGuiStyle allows you to align the library's default look with your application's branding or user preferences. The ocornut/imgui repository defines this system in imgui.h, where the ImGuiStyle struct holds 55+ color entries and 27+ sizing variables that the renderer consults every frame. By manipulating these values—either persistently through the global style object or transiently via the style stack—you achieve complete control over the UI's aesthetic without modifying the library's source code.

Understanding the ImGuiStyle Architecture

The Core Data Structure

The visual configuration lives in the ImGuiStyle structure declared in imgui.h (around line 2088). This struct contains two primary arrays that drive rendering:

  • ImVec4 Colors[ImGuiCol_COUNT] – Stores RGBA values for every UI element type, indexed by the ImGuiCol_ enumeration (e.g., ImGuiCol_WindowBg, ImGuiCol_Button).
  • float Variables[ImGuiStyleVar_COUNT] – Holds scalar and vector spacing values indexed by ImGuiStyleVar_ (e.g., ImGuiStyleVar_FramePadding, ImGuiStyleVar_ItemSpacing).

According to the ocornut/imgui source code, these arrays are populated with defaults when you create an ImGui context, and every drawing function reads from them during the render loop.

Context and Global Access

When you call ImGui::CreateContext(), the library allocates an ImGuiContext that embeds a fully initialized ImGuiStyle instance at ImGuiContext::Style. You retrieve a reference to this global style using:

ImGuiStyle& style = ImGui::GetStyle();

Because this returns a reference, modifications apply immediately to subsequent rendering calls. The style persists for the lifetime of the context unless you explicitly reload presets or override values.

Built-in Style Presets

Dear ImGui ships with three hard-coded presets implemented in imgui.cpp (around line 1045). These functions completely overwrite the Colors and Variables arrays:

  • ImGui::StyleColorsDark() – Modern dark theme (default since v1.50).
  • ImGui::StyleColorsLight() – Light/white background theme.
  • ImGui::StyleColorsClassic() – Original ImGui look (dark with blue accents).

You typically call one of these once after creating your context to establish a baseline, then tweak individual values as needed.

Global vs. Temporary Style Modifications

Modifying the Global Style

For persistent changes that affect the entire application, modify the structure returned by GetStyle() directly. This approach changes the default appearance for all subsequent frames until you modify the values again or reload a preset.

// Initialize with dark preset, then customize
ImGui::StyleColorsDark();
ImGuiStyle& style = ImGui::GetStyle();

// Customize colors
style.Colors[ImGuiCol_WindowBg]       = ImVec4(0.10f, 0.10f, 0.12f, 1.00f);
style.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.30f, 0.31f, 0.35f, 1.00f);
style.Colors[ImGuiCol_Button]        = ImVec4(0.20f, 0.25f, 0.30f, 1.00f);

// Adjust spacing
style.FramePadding = ImVec2(8, 4);
style.ItemSpacing  = ImVec2(12, 8);

Scoped Style Overrides

To temporarily change a style property for a specific widget or section without affecting the global state, use the push/pop API defined in imgui.h (around line 2930). The library maintains an internal stack (implemented in imgui_internal.h) that stores previous values.

// Temporarily make buttons red
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.2f, 0.2f, 1.0f));
if (ImGui::Button("Danger Zone")) {
    // Handle click
}
ImGui::PopStyleColor();  // Restore previous button color

// Temporarily increase padding for the next items
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(12, 6));
ImGui::Button("Padded Button");
ImGui::PopStyleVar();

Always match every Push with a corresponding Pop to avoid stack imbalances that trigger assertions in debug builds.

Interactive Style Editing and Preset Selection

Dear ImGui provides built-in debugging utilities that let you experiment with style values at runtime. The ShowStyleEditor() function, implemented in imgui_demo.cpp (around line 1400), renders a comprehensive panel exposing every field of ImGuiStyle.

static bool show_style_editor = false;

if (ImGui::BeginMainMenuBar()) {
    if (ImGui::BeginMenu("Tools")) {
        ImGui::MenuItem("Style Editor", NULL, &show_style_editor);
        ImGui::EndMenu();
    }
    ImGui::EndMainMenuBar();
}

if (show_style_editor) {
    ImGui::ShowStyleEditor();  // Interactive editor window
}

For a compact UI, use ShowStyleSelector() (declared in imgui.h around line 2915), which renders a combo box to switch between the Dark, Light, and Classic presets:

if (ImGui::ShowStyleSelector("Theme##Selector")) {
    // Selection changed; the function internally calls 
    // StyleColorsDark(), StyleColorsLight(), or StyleColorsClassic()
}

Saving and Loading Custom Styles

Because ImGuiStyle lives within the ImGui context, you can serialize user modifications to disk using the built-in settings API. The SaveIniSettingsToDisk() and LoadIniSettingsFromDisk() functions handle persistence automatically when ImGuiIO::IniFilename is configured.

// Save current style (and window positions) on exit
ImGui::SaveIniSettingsToDisk("my_app_config.ini");

// Load previous configuration during initialization
// Call before NewFrame() but after CreateContext()
ImGui::LoadIniSettingsFromDisk("my_app_config.ini");

The .ini file format serializes the ImGuiStyle fields alongside window data, ensuring your custom theme persists across application restarts.

Summary

  • ImGuiStyle in imgui.h is the central structure containing all 55+ colors and 27+ sizing variables that define Dear ImGui's appearance.
  • Access the active style via ImGui::GetStyle() for global modifications, or use PushStyleColor/**PushStyleVar** for temporary, scoped overrides.
  • Initialize themes using StyleColorsDark(), StyleColorsLight(), or StyleColorsClassic() from imgui.cpp.
  • Use ShowStyleEditor() (from imgui_demo.cpp) to interactively tweak visuals, and ShowStyleSelector() to offer preset switching.
  • Persist custom themes across sessions using SaveIniSettingsToDisk and LoadIniSettingsFromDisk.

Frequently Asked Questions

What is the difference between PushStyleColor and modifying GetStyle() directly?

PushStyleColor and PushStyleVar create temporary overrides on an internal stack that last until the corresponding Pop call, making them ideal for highlighting individual buttons or adjusting spacing for specific layouts. Modifying ImGui::GetStyle() directly changes the global default values stored in the ImGuiContext, affecting all subsequent rendering until the application restarts or you overwrite the values again.

How do I reset Dear ImGui to the default dark theme?

Call ImGui::StyleColorsDark(), which is implemented in imgui.cpp around line 1045. This function completely overwrites the Colors array in the current ImGuiStyle with the hard-coded dark theme values, restoring the default look instantly.

Can I save custom themes to a file in Dear ImGui?

Yes. The SaveIniSettingsToDisk() function serializes the current ImGuiStyle state (along with window positions) to an .ini file. You can reload these settings on startup using LoadIniSettingsFromDisk(). This mechanism respects the ImGuiIO::IniFilename field and provides automatic persistence without manual file parsing.

Where are the ImGuiCol_ and ImGuiStyleVar_ enumerations defined?

The ImGuiCol_ enumeration (defining color indices like ImGuiCol_WindowBg) and the ImGuiStyleVar_ enumeration (defining sizing indices like ImGuiStyleVar_FramePadding) are both defined in imgui.h. These enums index into the Colors and Variables arrays inside the ImGuiStyle structure, respectively.

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 →