# Customizing ImGui Theme and Style: A Complete Guide to ImGuiStyle

> Learn to customize ImGui theme and style with this complete guide. Modify ImGuiStyle for a unique look using GetStyle or PushStyleVar API.

- Repository: [omar/imgui](https://github.com/ocornut/imgui)
- Tags: how-to-guide
- Published: 2026-07-19

---

**Dear ImGui's appearance is controlled entirely through the `ImGuiStyle` structure, which you can modify at initialization via `ImGui::GetStyle()` or temporarily per-widget using the `PushStyleVar`/`PushStyleColor` stack API.**

Dear ImGui (`ocornut/imgui`) exposes every visual parameter through a single plain-old-data structure, making **customizing ImGui theme and style** straightforward once you understand the **`ImGuiStyle`** fields and the built-in palette helpers. The style system is defined in **[`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h)** and implemented across **[`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp)** and **[`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp)**, giving you full access to colors, spacing, rounding, and layout constants. Whether you want a dark, light, or fully bespoke look, you can achieve it by manipulating this structure before the first **`ImGui::NewFrame()`** call.

## Customizing ImGui Theme and Style with the `ImGuiStyle` Structure

The foundation of every Dear ImGui theme is the **`ImGuiStyle`** structure declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) around lines 2308–2399. It is a flat POD struct that holds scalar **float** and **`ImVec2`** fields—such as `WindowPadding`, `FrameRounding`, and `ItemSpacing`—plus a **`Colors[ImGuiCol_COUNT]`** array that stores an **`ImVec4`** for every color index defined by the `ImGuiCol_` enum. Because it is plain data with no hidden state, you can copy, compare, or serialize the entire structure with standard C++.

## Built-In Palette Helpers for Quick Theme Presets

Dear ImGui ships with three preset color schemes implemented in [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp). These functions populate a fresh `ImGuiStyle` with curated palettes:

- **`ImGui::StyleColorsDark()`** – The modern dark theme (default). Implementation occupies [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp) lines 887–954.

- **`ImGui::StyleColorsClassic()`** – The original ImGui look from early versions. Implementation occupies lines 955–1022.

- **`ImGui::StyleColorsLight()`** – A light-colored scheme for bright environments. Implementation occupies lines 1023–1085.

Each helper accepts an optional **`ImGuiStyle*`** pointer; passing one writes the palette into your existing instance instead of the global style.

## Applying a Custom Theme Before the First Frame

The recommended workflow for customizing ImGui theme and style is to perform changes **once during application initialization**, before the first call to `ImGui::NewFrame()`. You can either overwrite the global style returned by `ImGui::GetStyle()` or fill a local `ImGuiStyle` and assign it.

```cpp
// 1️⃣ Initialise a custom dark theme with a few tweaks
ImGuiStyle customStyle;
ImGui::StyleColorsDark(&customStyle);           // start from built‑in dark palette

// Override a few colours
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);

// Change rounding and padding
customStyle.WindowRounding   = 6.0f;
customStyle.FrameRounding    = 4.0f;
customStyle.WindowPadding    = ImVec2(12, 12);
customStyle.ItemSpacing      = ImVec2(8, 8);

// Apply it before the first frame
ImGui::GetStyle() = customStyle;   // or: ImGui::GetStyle() = customStyle; (C++ copy)

```

Calling `ImGui::GetStyle() = customStyle;` performs a plain struct copy, so all colors and metrics take effect globally for the remainder of the session.

## Runtime Style Overrides Using the Push/Pop Stack

When you need temporary, scoped changes—such as turning a single button red—you should avoid mutating the global style directly. Instead, use the stack-based API declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) lines 527–560:

- **`ImGui::PushStyleVar(ImGuiStyleVar_idx, value)`** / **`ImGui::PopStyleVar()`** – For numeric and `ImVec2` metrics.

- **`ImGui::PushStyleColor(ImGuiCol_idx, color)`** / **`ImGui::PopStyleColor()`** – For color overrides.

Behind the scenes, these calls store **`ImGuiStyleMod`** objects defined in **[`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h)**, so the previous value is restored automatically when you pop.

```cpp
// 2️⃣ Temporary per‑frame tweaks using the stack API
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 12.0f);
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0.9f, 0.2f, 0.2f, 1.0f));

// ... draw UI ...

ImGui::PopStyleColor();
ImGui::PopStyleVar();

```

## Prototyping Themes with `ShowStyleEditor()`

Dear ImGui includes a built-in visual editor for rapid theme tweaking. The **`ImGui::ShowStyleEditor()`** function, declared in [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) at line 414, opens a debug window that edits the current global style in real time.

```cpp
// 3️⃣ Show the live editor (useful for rapid prototyping)
ImGui::ShowStyleEditor();   // opens a window that edits ImGui::GetStyle()

```

Use this to find the exact color indices and metric values you want, then transfer those values into your initialization code or serialization format.

## Serializing Custom ImGui Themes for Persistence

Because `ImGuiStyle` is simple POD data, you can persist it to JSON, INI, or binary and reload it at runtime. This enables user-adjustable themes across sessions. The example below uses `nlohmann/json` to store the `Alpha`, rounding, and `Colors` array:

```cpp
// 4️⃣ Serialize/deserialize a style (example with JSON – requires nlohmann/json)
#include <nlohmann/json.hpp>

void SaveStyle(const ImGuiStyle& style, const std::string& path)
{
    nlohmann::json j;
    j["Alpha"] = style.Alpha;
    j["WindowRounding"] = style.WindowRounding;
    // ... (store every scalar you care about)
    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 all 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 Dear ImGui releases may add new fields to `ImGuiStyle`. Persisted themes should be version-checked or rebuilt against the latest defaults to avoid layout mismatches.

## Key Files in the Dear ImGui Source

| File | Purpose |
|------|---------|
| [`imgui.h`](https://github.com/ocornut/imgui/blob/main/imgui.h) | Public API declarations for `ImGuiStyle`, push/pop functions, and `ShowStyleEditor` (lines 527–560 and 2308–2399). |
| [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp) | Implementations of `StyleColorsDark`, `StyleColorsClassic`, and `StyleColorsLight` (lines 887–1085). |
| [`imgui_internal.h`](https://github.com/ocornut/imgui/blob/main/imgui_internal.h) | Internal `ImGuiStyleMod` struct that backs the push/pop stack. |
| [`imgui.cpp`](https://github.com/ocornut/imgui/blob/main/imgui.cpp) | Usage comments and evolution notes on the style system. |

## Summary

- **`ImGuiStyle`** is the single POD structure that defines every color, padding, and rounding value in Dear ImGui.

- Call **`ImGui::StyleColorsDark()`**, **`StyleColorsClassic()`**, or **`StyleColorsLight()`** to populate a baseline palette from [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp).

- Assign your customized struct to **`ImGui::GetStyle()`** once at startup, before the first `NewFrame()`.

- Use **`PushStyleVar`** / **`PushStyleColor`** and the corresponding **`Pop*`** calls for temporary, scoped overrides.

- Leverage **`ImGui::ShowStyleEditor()`** to prototype themes interactively.

- Serialize the struct to JSON or binary if you want persistent, user-customizable themes, but guard against future struct layout changes.

## Frequently Asked Questions

### How do I change the default theme in Dear ImGui?

Call one of the built-in palette helpers—such as `ImGui::StyleColorsDark()`, `ImGui::StyleColorsClassic()`, or `ImGui::StyleColorsLight()`—before your first `ImGui::NewFrame()`. You can pass a pointer to your own `ImGuiStyle` instance or let the function update the global style directly.

### What is the difference between `PushStyleColor` and editing `ImGui::GetStyle()` directly?

Modifying `ImGui::GetStyle()` changes the global theme permanently until you overwrite it again, so it is best done once at initialization. In contrast, `PushStyleColor` and `PushStyleVar` apply temporary overrides on a stack that are automatically reverted when you call the corresponding `Pop*()` function, making them ideal for one-off widget variations.

### Can I save and load custom ImGui themes at runtime?

Yes. Because `ImGuiStyle` is plain-old-data, you can serialize its scalar fields and `Colors` array to JSON, INI, or binary and deserialize them back into the struct. Just ensure you validate the data version when upgrading Dear ImGui, since newer releases may extend the struct with additional fields.

### Where are the default ImGui theme colors defined?

The default dark, classic, and light palettes are implemented in [`imgui_draw.cpp`](https://github.com/ocornut/imgui/blob/main/imgui_draw.cpp) between lines 887 and 1085. Each palette function explicitly sets every entry of the `Colors` array using hard-coded `ImVec4` values.