# How to Customize AionUi's UI Using User CSS Injection Through Settings

> Customize AionUi's appearance by injecting custom CSS through Settings. Persist styles globally via ConfigStorage for a personalized developer experience.

- Repository: [OfficeAI/AionUi](https://github.com/iofficeai/aionui)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Developers can customize AionUi's appearance by injecting custom CSS through the Settings → Display panel, which persists styles via ConfigStorage and applies them globally to the renderer process.**

AionUi is an open-source UI framework that enables runtime theming without requiring application rebuilds. By leveraging user CSS injection through the settings interface, developers and end-users can override default styles, create persistent custom themes, and customize AionUi's UI appearance across sessions.

## Understanding the CSS Injection Architecture

The CSS injection system in AionUi consists of three coordinated layers: storage persistence, event broadcasting, and DOM injection. This architecture ensures that custom styles survive application restarts while updating the interface in real-time when changes occur.

### Storage and Persistence Layer

User-defined CSS is stored in `ConfigStorage` under the key `customCss`. The storage schema, defined in [`src/common/storage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/common/storage.ts), treats this value as a plain string that the renderer consumes at startup. When users save CSS through the settings UI, the [`CssThemeModal.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/CssThemeModal.tsx) component (lines 45-57) persists the text via `ConfigStorage.set('customCss', css)`.

### Event-Driven Update Mechanism

To enable real-time updates without reloading, AionUi dispatches a custom DOM event `custom-css-updated` whenever CSS changes. The `applyThemeCss` function in [`src/renderer/components/CssThemeSettings/index.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/components/CssThemeSettings/index.tsx) (lines 86-95) both persists the CSS to storage and broadcasts this event with the new styles in `detail.customCss`.

## How to Customize AionUi's UI Using the Settings Panel

The most straightforward method to inject custom CSS uses the built-in graphical interface located in the Display settings.

### Accessing the CSS Theme Settings

Navigate to **Settings → Display → CSS Settings** to open the theme management panel. This interface, implemented in [`src/renderer/components/SettingsModal/contents/DisplayModalContent.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/components/SettingsModal/contents/DisplayModalContent.tsx), embeds the `CssThemeSettings` component and provides controls for creating, editing, and activating CSS themes.

### Creating and Saving Custom CSS

Click the **+** button to create a new theme, which opens [`CssThemeModal.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/CssThemeModal.tsx) containing a CodeMirror editor. Paste your CSS rules into the editor—for example:

```css
.arco-button {
  border-radius: 8px !important;
  background-color: #6366f1 !important;
}

```

Click **Save** to persist the CSS to `ConfigStorage` under the `customCss` key. The layout component immediately injects these styles into the document head.

## Programmatic CSS Injection for Developers

For plugin authors or advanced use cases, AionUi exposes APIs to manipulate custom CSS programmatically without using the settings UI.

### Setting Custom CSS via ConfigStorage API

You can inject CSS directly using the `ConfigStorage` API and dispatch the update event:

```typescript
import { ConfigStorage } from '@/common/storage';

const customStyles = `
  body { background: #1e1e1e !important; }
  .arco-button-primary { background: #ff4081 !important; }
`;

async function applyCustomStyles() {
  await ConfigStorage.set('customCss', customStyles);
  window.dispatchEvent(new CustomEvent('custom-css-updated', {
    detail: { customCss: customStyles }
  }));
}
applyCustomStyles();

```

This approach mirrors the behavior of `applyThemeCss` in [`src/renderer/components/CssThemeSettings/index.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/components/CssThemeSettings/index.tsx).

### Listening for CSS Changes in Components

Components can react to CSS updates by listening for the `custom-css-updated` event:

```typescript
import { useEffect, useState } from 'react';

function useCustomCss() {
  const [css, setCss] = useState('');

  useEffect(() => {
    const handler = (e: CustomEvent) => {
      setCss(e.detail?.customCss ?? '');
    };
    window.addEventListener('custom-css-updated', handler as EventListener);
    return () => window.removeEventListener('custom-css-updated', handler as EventListener);
  }, []);

  return css;
}

```

This hook allows any part of the renderer to synchronize with the current custom CSS state.

## CSS Processing and Safety Mechanisms

AionUi processes user CSS before injection to prevent style leakage and ensure priority over default themes.

### The processCustomCss Pipeline

Before injection, raw CSS passes through `processCustomCss` in [`src/renderer/utils/customCssProcessor.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/utils/customCssProcessor.ts). This utility performs two operations:

1. **Selector wrapping**: The `wrapCustomCss` function surrounds user rules with a unique selector to isolate them from built-in styles
2. **Priority enforcement**: The `addImportantToAll` function appends `!important` to every declaration to ensure user styles override defaults

### Automatic !important Injection

The `addImportantToAll` implementation (lines 14-62 in [`customCssProcessor.ts`](https://github.com/iOfficeAI/AionUi/blob/main/customCssProcessor.ts)) parses CSS declarations and automatically injects `!important` flags. This guarantees that user CSS takes precedence over AionUi's default Arco Design styles without requiring manual `!important` typing in the editor.

## Summary

- AionUi supports **user CSS injection** through both a graphical settings panel and programmatic APIs
- Custom CSS is stored in `ConfigStorage` under the `customCss` key and persists across sessions
- The system uses a **custom event** (`custom-css-updated`) to broadcast style changes in real-time
- The `Layout` component in [`src/renderer/layout.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/layout.tsx) handles actual DOM injection via a `<style>` tag appended to `<head>`
- **Safety mechanisms** including selector wrapping and automatic `!important` injection prevent style conflicts

## Frequently Asked Questions

### Where is custom CSS stored in AionUi?

Custom CSS is stored in the electron-store backed `ConfigStorage` under the key `customCss`, defined in [`src/common/storage.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/common/storage.ts). This storage persists between application restarts and is accessible from both the main and renderer processes.

### Can I use CSS injection without using the Settings UI?

Yes. Developers can programmatically set custom CSS using `ConfigStorage.set('customCss', css)` and dispatch the `custom-css-updated` event to trigger immediate application. This approach is useful for plugins or automated theming without user interaction.

### How does AionUi prevent custom CSS from breaking the interface?

AionUi processes all user CSS through `processCustomCss` in [`src/renderer/utils/customCssProcessor.ts`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/utils/customCssProcessor.ts) before injection. This utility wraps selectors to isolate styles and automatically adds `!important` to declarations, ensuring user rules override defaults without leaking into critical UI components.

### What file handles the actual injection of CSS into the document head?

The `Layout` component in [`src/renderer/layout.tsx`](https://github.com/iOfficeAI/AionUi/blob/main/src/renderer/layout.tsx) manages DOM injection. It creates a `<style id="user-defined-custom-css">` element, appends it as the last child of `<head>`, and updates its content whenever the `custom-css-updated` event fires or `ConfigStorage` changes.