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 (likeImGuiCol_WindowBgandImGuiCol_Button) to RGBA valuesfloat Variables[ImGuiStyleVar_COUNT]: An array storing size and spacing metrics (likeImGuiStyleVar_FramePaddingandImGuiStyleVar_ItemSpacing)- Font and layout fields: Including
WindowRounding,FrameBorderSize, andScrollBarSize
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 includingImGuiCol_TitleBgActive,ImGuiCol_Text, andImGuiCol_CheckMarkenum ImGuiStyleVar_: Defines 27+ sizing targets includingImGuiStyleVar_WindowPaddingandImGuiStyleVar_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 accentsImGui::StyleColorsLight(): Inverted light theme suitable for productivity applicationsImGui::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
ImGuiStyleis the central structure (defined inimgui.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(), andStyleColorsClassic()to reset to known good themes - Temporarily override specific colors or metrics using
PushStyleColor()andPushStyleVar(), always paired with theirPopcounterparts - Leverage
ShowStyleEditor()(fromimgui_demo.cpp) for interactive tweaking andSaveIniSettingsToDisk()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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →