How to Customize ImGui Styling and Themes: A Complete Guide to ImGuiStyle
Customize ImGui styling and themes by modifying the ImGuiStyle structure via ImGui::GetStyle(), applying built-in presets like StyleColorsDark(), or using the PushStyleVar() and PushStyleColor() stack APIs for temporary overrides.
Dear ImGui's appearance is controlled entirely through a single public data structure. If you want to customize ImGui styling and themes in the ocornut/imgui repository, you will work directly with the ImGuiStyle struct defined in imgui.h. The library provides both global initialization helpers and per-frame stack APIs so you can tweak everything from button rounding to window background colors.
Understanding the ImGuiStyle Structure
The foundation of every custom theme is the ImGuiStyle structure defined in imgui.h around lines 2308-2399. It stores the full look-and-feel state as plain old data, including scalar fields for spacing, rounding, and borders, plus a Colors[ImGuiCol_COUNT] array that maps ImGuiCol_ enum values to RGBA vectors.
Because it is a POD struct with no hidden state, you can copy, compare, or serialize it freely. The active style instance is retrieved with ImGui::GetStyle() and should generally be modified once during setup, before your first call to ImGui::NewFrame().
Built-In Theme Presets: Dark, Classic, and Light
Dear ImGui ships with three official preset palettes implemented in imgui_draw.cpp between lines 887 and 1085. These helper functions populate an ImGuiStyle with a complete color scheme:
ImGui::StyleColorsDark()— Lines 887-954. The modern dark theme used by default.ImGui::StyleColorsClassic()— Lines 955-1022. The legacy orange-tinted theme.ImGui::StyleColorsLight()— Lines 1023-1085. A light alternative for bright environments.
Each function takes an optional ImGuiStyle* pointer; passing your own struct lets you start from a known baseline without mutating the global style immediately.
Applying a Global Custom Theme at Initialization
The standard workflow is to create a local ImGuiStyle, run a preset through it, override specific colors or metrics, then copy it into the global state:
// Start from the built-in dark palette
ImGuiStyle customStyle;
ImGui::StyleColorsDark(&customStyle);
// Override specific colors using the ImGuiCol_ enum
customStyle.Colors[ImGuiCol_TitleBgActive] = ImVec4(0.2f, 0.4f, 0.9f, 1.0f);
customStyle.Colors[ImGuiCol_Button] = ImVec4(0.1f, 0.7f, 0.3f, 0.8f);
// Adjust geometry and rounding
customStyle.WindowRounding = 6.0f;
customStyle.FrameRounding = 4.0f;
customStyle.WindowPadding = ImVec2(12, 12);
customStyle.ItemSpacing = ImVec2(8, 8);
// Apply before the first frame
ImGui::GetStyle() = customStyle;
Setting ImGui::GetStyle() via assignment copies the entire structure into the current context. This approach is the recommended way to customize ImGui styling and themes for an entire application session.
Temporary Runtime Overrides with Push and Pop
Not every style change should last for the whole session. Dear ImGui provides a stack-based API declared in imgui.h around lines 527-560 that lets you push temporary values for a single window or widget group. Behind the scenes, the library records these changes as ImGuiStyleMod objects, as seen in imgui_internal.h.
ImGui::PushStyleVar()/ImGui::PopStyleVar()— Modify numeric fields like rounding or padding.ImGui::PushStyleColor()/ImGui::PopStyleColor()— Modify color entries.
A typical usage block looks like this:
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.0f);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.9f, 0.2f, 0.2f, 1.0f));
// Draw affected widgets here
if (ImGui::Button("Danger")) { /* ... */ }
ImGui::PopStyleColor();
ImGui::PopStyleVar();
Always match the number of push and pop calls within the same frame to avoid stack corruption.
Interactive Prototyping with ShowStyleEditor
If you prefer to tune values visually, ImGui::ShowStyleEditor() declared in imgui.h at line 414 opens an integrated window that edits ImGui::GetStyle() in real time. This is the fastest way to experiment with metrics before hard-coding them into your initialization routine.
// Call anywhere inside your main loop
ImGui::ShowStyleEditor();
Once you find a combination you like, read the values back from ImGui::GetStyle() and save them to your own configuration format.
Serializing and Reloading Custom Themes
Because ImGuiStyle is plain data, you can persist customized themes to JSON, INI, or binary files and reload them at runtime. This enables user-adjustable themes without recompiling. Below is a JSON-oriented example using nlohmann/json:
#include <nlohmann/json.hpp>
#include <fstream>
void SaveStyle(const ImGuiStyle& style, const std::string& path)
{
nlohmann::json j;
j["Alpha"] = style.Alpha;
j["WindowRounding"] = style.WindowRounding;
// ... store additional scalars as needed ...
for (int i = 0; i < ImGuiCol_COUNT; ++i)
j["Colors"][i] = {style.Colors[i].x, style.Colors[i].y,
style.Colors[i].z, style.Colors[i].w};
std::ofstream f(path);
f << j.dump(4);
}
void LoadStyle(ImGuiStyle& style, const std::string& path)
{
std::ifstream f(path);
nlohmann::json j;
f >> j;
style.Alpha = j["Alpha"];
style.WindowRounding = j["WindowRounding"];
// ... load additional scalars ...
for (int i = 0; i < ImGuiCol_COUNT; ++i)
{
auto c = j["Colors"][i];
style.Colors[i] = ImVec4(c[0], c[1], c[2], c[3]);
}
}
Be aware that future releases of Dear ImGui may add new fields to ImGuiStyle. Version-check your saved data or merge missing fields against current defaults when loading older theme files.
Key Source Files for Theme Customization
When reading the ocornut/imgui source to deepen your understanding, focus on these files:
imgui.h— Public API declarations includingImGuiStyle, theImGuiCol_enum, push/pop functions, andShowStyleEditor().imgui_draw.cpp— Implementations ofStyleColorsDark(),StyleColorsClassic(), andStyleColorsLight().imgui_internal.h— Internal structures such asImGuiStyleModthat power the push/pop stack.imgui.cpp— Commentary on style system evolution around lines 1000-1600.
Summary
ImGuiStyleis the central POD struct that controls every visual aspect of Dear ImGui.- Use
StyleColorsDark(),StyleColorsClassic(), orStyleColorsLight()inimgui_draw.cppto establish a baseline palette. - Apply global changes by writing to
ImGui::GetStyle()before the firstImGui::NewFrame(). - Use
PushStyleVar()andPushStyleColor()for temporary, scoped overrides that automatically restore previous values. - Call
ShowStyleEditor()for interactive prototyping, then serialize your finalImGuiStyleto disk for reusable themes.
Frequently Asked Questions
How do I change the default theme in Dear ImGui?
Call one of the preset functions on a local ImGuiStyle object and copy it into ImGui::GetStyle() before your main loop starts. For example, invoke ImGui::StyleColorsLight(&myStyle); followed by ImGui::GetStyle() = myStyle; to switch the entire application to the light theme.
What is the difference between PushStyleColor and editing ImGui::GetStyle() directly?
PushStyleColor() and PushStyleVar() create temporary, stack-based overrides that last until their matching Pop call, making them ideal for short-lived changes on specific widgets. Editing ImGui::GetStyle() directly changes the global defaults for the rest of the session or until you overwrite it again.
Can I save and load custom ImGui themes at runtime?
Yes. Because ImGuiStyle is a simple C++ struct with no private state, you can serialize its scalar fields and Colors array to JSON or binary and reload them later. Just ensure you handle version mismatches when upgrading to newer Dear ImGui releases that may add new style fields.
Where are the built-in color themes defined in the ImGui source code?
The built-in themes are implemented in imgui_draw.cpp between lines 887 and 1085. StyleColorsDark() occupies lines 887-954, StyleColorsClassic() lines 955-1022, and StyleColorsLight() lines 1023-1085.
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 →