How to Customize and Theme Dear ImGui Using ImGuiStyle: A Complete Guide

Dear ImGui's visual appearance is controlled entirely through the ImGuiStyle structure, accessed via ImGui::GetStyle(), which stores color palettes, spacing values, and sizing constants that you can modify globally, override per-widget, or persist across sessions.

The ocornut/imgui library renders its immediate-mode interface using a centralized styling system defined in imgui.h. Every frame, Dear ImGui reads from the active ImGuiStyle instance to determine how to draw windows, buttons, text, and borders. By manipulating this structure—either through persistent global changes or temporary stack-based overrides—you can completely transform the UI's visual language to match your application.

Understanding the ImGuiStyle Architecture

The styling system revolves around three core components that work together to define the final rendered output.

The Core Data Structure

At the heart of the system is the ImGuiStyle struct defined in imgui.h around line 2088. This structure contains:

  • ImVec4 Colors[ImGuiCol_COUNT]: An array mapping color indices (like ImGuiCol_WindowBg and ImGuiCol_Button) to RGBA values
  • float Variables[ImGuiStyleVar_COUNT]: An array storing size and spacing metrics (like ImGuiStyleVar_FramePadding and ImGuiStyleVar_ItemSpacing)
  • Font and layout fields: Including WindowRounding, FrameBorderSize, and ScrollBarSize

When you call ImGui::CreateContext(), the library automatically initializes an ImGuiStyle instance within the ImGuiContext. All drawing functions reference this style every frame, meaning changes take effect immediately for subsequent UI elements.

Color and Variable Indices

Rather than direct member access for every property, Dear ImGui uses enumeration-based indexing:

  • enum ImGuiCol_: Defines 55+ color targets including ImGuiCol_TitleBgActive, ImGuiCol_Text, and ImGuiCol_CheckMark
  • enum ImGuiStyleVar_: Defines 27+ sizing targets including ImGuiStyleVar_WindowPadding and ImGuiStyleVar_GrabMinSize

These indices allow the stack-based override system to work efficiently by pushing and popping specific indices rather than full structure copies.

Applying Global Themes with Preset Functions

Dear ImGui ships with three built-in color schemes defined in imgui.cpp (around line 1045). These functions populate the Colors and Variables arrays with complete, coherent palettes.

  • ImGui::StyleColorsDark(): The modern default theme with dark backgrounds and high-contrast accents
  • ImGui::StyleColorsLight(): Inverted light theme suitable for productivity applications
  • ImGui::StyleColorsClassic(): The original ImGui look from early versions

These presets are called automatically during context creation if you don't specify otherwise, but you can reapply them at any time to reset to a known state.

Modifying Styles at Runtime

The library provides two distinct approaches to style modification: persistent global changes that affect all subsequent widgets, and temporary overrides scoped to specific UI blocks.

Persistent Global Modifications

To permanently alter the appearance of your entire application, modify the global style structure returned by ImGui::GetStyle():

// Start from a clean preset
ImGui::StyleColorsDark();

// Reference the global style struct
ImGuiStyle& style = ImGui::GetStyle();

// Customize background 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);

// Adjust spacing and padding
style.FramePadding = ImVec2(8.0f, 4.0f);
style.ItemSpacing = ImVec2(12.0f, 8.0f);
style.WindowRounding = 4.0f;

Changes to this reference affect all ImGui rendering until the context is destroyed or you modify the values again.

Temporary Widget Overrides

For one-off styling—such as highlighting a danger button or creating compact layout sections—use the push/pop API:

// Push a red color override for the next widget only
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.2f, 0.2f, 1.0f));
if (ImGui::Button("Delete")) {
    // Handle action
}
ImGui::PopStyleColor();  // Restore previous button color

// Push multiple style changes simultaneously
ImImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(4.0f, 2.0f));
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(8.0f, 4.0f));
// ... draw compact widgets ...
ImGui::PopStyleVar(2);   // Pop both changes

The PushStyleColor and PushStyleVar functions (declared in imgui.h around line 2930) store previous values on an internal stack, restoring them when you call the corresponding Pop function. These stacks are frame-scoped and automatically cleared if you forget to pop, though correct pairing is recommended.

Interactive Style Editing and Persistence

The repository provides utilities for runtime experimentation and saving user preferences.

Built-in Style Editor

imgui_demo.cpp (around line 1400) implements ImGui::ShowStyleEditor(), which renders a complete debugging panel:

bool show_style_editor = true;

if (show_style_editor) {
    ImGui::ShowStyleEditor();  // Interactive panel for tweaking every field
}

This editor allows you to adjust colors and variables in real-time with immediate visual feedback, making it ideal for finding the right values before hardcoding them.

Style Selector

For quick preset switching, use ImGui::ShowStyleSelector() (declared in imgui.h around line 2915):

// Renders a combo box with Dark, Light, and Classic options
if (ImGui::ShowStyleSelector("##ThemeSelector")) {
    // Selection automatically applies the chosen preset
}

Persisting User Customizations

Because ImGuiStyle lives in the context, you can serialize modifications using the INI settings system:

// Save current style and layout to disk on application exit
ImGui::SaveIniSettingsToDisk("my_application.ini");

// Load saved settings during initialization (before the first frame)
ImGui::LoadIniSettingsFromDisk("my_application.ini");

The ImGuiIO::IniFilename field controls automatic serialization, ensuring your theme customizations survive application restarts.

Summary

  • ImGuiStyle is the central structure (defined in imgui.h) containing all colors, spacing, and sizing data for the entire UI
  • Access the active style via ImGui::GetStyle() to make persistent global changes to the appearance
  • Use preset functions like StyleColorsDark(), StyleColorsLight(), and StyleColorsClassic() to reset to known good themes
  • Temporarily override specific colors or metrics using PushStyleColor() and PushStyleVar(), always paired with their Pop counterparts
  • Leverage ShowStyleEditor() (from imgui_demo.cpp) for interactive tweaking and SaveIniSettingsToDisk() for persistence across sessions

Frequently Asked Questions

How do I change the background color of all ImGui windows?

Modify the ImGuiCol_WindowBg entry in the global style structure. After calling ImGui::StyleColorsDark() or your preferred preset, get a reference via ImGuiStyle& style = ImGui::GetStyle() and set style.Colors[ImGuiCol_WindowBg] = ImVec4(r, g, b, a). This affects all windows drawn after the modification.

What is the difference between ImGuiCol_ and ImGuiStyleVar_?

ImGuiCol_ values are indices into the Colors array for RGBA color data (like button backgrounds or text colors), while ImGuiStyleVar_ values are indices into the Variables array for scalar sizing data (like padding, rounding, or spacing). Use PushStyleColor for colors and PushStyleVar for sizes.

Can I save my custom theme to a file and reload it later?

Yes. Dear ImGui automatically serializes style data when you use ImGui::SaveIniSettingsToDisk("filename.ini"). Call this on application shutdown, then call ImGui::LoadIniSettingsFromDisk("filename.ini") immediately after ImGui::CreateContext() but before your main loop starts. The INI system handles ImGuiStyle persistence automatically.

How do I make only one button red while keeping others the default color?

Wrap the specific button between PushStyleColor and PopStyleColor calls. For example: ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.8f, 0.2f, 0.2f, 1.0f)); ImGui::Button("Alert"); ImGui::PopStyleColor();. This creates a scoped override that restores the previous color immediately after popping.

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 →