Theming & Styling
Customize the editor's appearance with themes, CSS variables, and custom styles.
Imigi provides a flexible theming system built on CSS custom properties. You can use the built-in light and dark themes, create fully custom themes with your own brand colors, or override individual styles with plain CSS. Theme changes can also be applied dynamically at runtime without reinitializing the editor.
Built-in Themes
Imigi ships with two built-in themes that work out of the box:
| Theme | Value | Description |
|---|---|---|
| Light | 'light' |
Clean white backgrounds with dark text. This is the default theme applied when no theme is specified. |
| Dark | 'dark' |
Dark backgrounds with light text. Reduces eye strain in low-light environments and provides a professional editing feel. |
To set the active theme, use the ui.activeTheme configuration option during initialization:
// Use the light theme (default)
Imigi.init({
selector: '#editor',
ui: {
activeTheme: 'light',
},
});
// Use the dark theme
Imigi.init({
selector: '#editor',
ui: {
activeTheme: 'dark',
},
});
The light theme is applied by default if you omit ui.activeTheme entirely. You only need to set it explicitly when you want dark mode or a custom theme.
Theme Configuration
The theme is configured through the ui section of the Imigi configuration object. The activeTheme property accepts a string that matches the name of any built-in or custom theme.
Imigi.init({
selector: '#editor',
ui: {
activeTheme: 'dark',
},
});
The ui object also supports additional display-related options that work alongside theming:
activeTheme— The name of the theme to apply ('light','dark', or any custom theme name).themes— An array of custom theme definitions (see Creating Custom Themes).
Creating Custom Themes
You can define fully custom themes by providing a themes array in the ui configuration. Each theme object requires a name, an isDark boolean (controls base text and icon colors), and a colors map of CSS variable overrides.
Imigi.init({
selector: '#editor',
ui: {
activeTheme: 'my-brand',
themes: [
{
name: 'my-brand',
isDark: false,
colors: {
'--be-foreground-base': '30 41 59',
'--be-primary': '234 88 12',
'--be-background': '255 247 237',
'--be-background-alt': '255 237 213',
'--be-paper': '255 255 255',
},
},
],
},
});
Color values must be specified as space-separated RGB values (e.g., '234 88 12'), not as hex codes or rgb() functions. Imigi uses these raw RGB values internally with rgba() for opacity variations.
Theme Object Properties
| Property | Type | Description |
|---|---|---|
name |
string |
Unique identifier for the theme. Used in activeTheme to activate it. |
isDark |
boolean |
Whether this is a dark theme. Controls default foreground colors for text and icons. |
colors |
object |
Key-value map of CSS custom property names to RGB color values. |
CSS Variables Reference
The following CSS custom properties control the editor's visual appearance. All color values use the space-separated RGB format (e.g., 59 130 246).
| Variable | Description | Light Default | Dark Default |
|---|---|---|---|
--be-foreground-base |
Base text and icon color (RGB) | 0 0 0 |
255 255 255 |
--be-primary |
Primary accent color used for buttons, links, and active states | 59 130 246 |
191 219 254 |
--be-background |
Main editor background color | 255 255 255 |
20 21 23 |
--be-background-alt |
Alternate background for secondary areas and hover states | 250 250 250 |
26 27 30 |
--be-paper |
Card, panel, and dialog background color | 255 255 255 |
44 46 51 |
Imigi uses raw RGB triplets so it can construct colors with varying opacity levels. For example, --be-primary: 59 130 246 is used internally as rgba(59, 130, 246, 0.5) for hover states. This approach is more flexible than passing pre-formed color strings.
CSS Classes
Imigi applies the following key CSS classes to its DOM elements. You can use these as selectors when writing custom style overrides.
| Class | Description |
|---|---|
.imigi-root |
The outermost root container element of the editor. All CSS variables are scoped to this element. |
.pi |
Shorthand alias for the root container class. Can be used interchangeably with .imigi-root. |
.pi-light |
Applied to the root element when the light theme is active. |
.pi-dark |
Applied to the root element when the dark theme is active. |
.bg-controls |
Toolbar and controls background. Applied to the top navigation bar and tool option panels. |
.bg-paper |
Panel, card, and dialog backgrounds. Used for floating menus and option panels. |
.cropzone |
The crop zone overlay element displayed when the crop tool is active. |
.svg-icon |
Applied to all SVG icon elements within the editor UI. |
Overriding Styles
You can override any of Imigi's default styles using standard CSS. Target the .imigi-root selector to scope your overrides to the editor without affecting the rest of your page.
/* Override the primary color */
.imigi-root {
--be-primary: 234 88 12; /* orange */
}
/* Custom button styles */
.imigi-root .bg-controls {
backdrop-filter: blur(12px);
}
/* Custom scrollbar */
.imigi-root .tiny-scrollbar::-webkit-scrollbar-thumb {
background: rgba(59, 130, 246, 0.3);
}
Always scope your overrides under .imigi-root to ensure they only affect the editor. This prevents unintended style leakage into other parts of your application and keeps specificity manageable.
Theme-Specific Overrides
You can target specific themes using the theme classes:
/* Only apply in light mode */
.imigi-root.pi-light .bg-controls {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
}
/* Only apply in dark mode */
.imigi-root.pi-dark .bg-controls {
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}
Dynamic Theme Switching
You can change the active theme at runtime without reinitializing the editor. Use the setConfig() method to update the ui.activeTheme value.
// Toggle between light and dark
function toggleEditorTheme() {
const isDark = imigi.state.config.ui.activeTheme === 'dark';
imigi.setConfig({
ui: { activeTheme: isDark ? 'light' : 'dark' }
});
}
// Switch to a custom theme
imigi.setConfig({
ui: { activeTheme: 'my-brand' }
});
Theme transitions are instantaneous. The editor re-renders with the new theme colors immediately. No page reload or editor reinitialization is required.
Syncing with System Preferences
You can automatically match the user's system color scheme preference:
// Match the OS light/dark preference
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
Imigi.init({
selector: '#editor',
ui: {
activeTheme: prefersDark ? 'dark' : 'light',
},
});
// Listen for OS theme changes
window.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (e) => {
imigi.setConfig({
ui: { activeTheme: e.matches ? 'dark' : 'light' }
});
});
Z-Index Layers
Imigi uses a structured z-index layering system to ensure UI elements stack correctly. Understanding these layers is useful when positioning custom elements relative to the editor.
| Layer | Z-Index | Description |
|---|---|---|
loading-indicator |
50 |
Loading spinner overlay displayed during image loading and processing operations. |
navbar |
40 |
Top navigation bar containing tool buttons and action controls. |
tool-overlay |
30 |
Tool option panels and dropdown menus that appear above the canvas. |
obj-box |
20 |
Object selection bounding boxes, resize handles, and rotation controls. |
cropzone |
10 |
The semi-transparent crop zone overlay with drag handles. |
Avoid setting z-index values on parent elements of the editor container, as this can create new stacking contexts that interfere with the editor's layer system. If you must set z-index on a parent, make sure it is high enough that all editor layers remain accessible.
Tailwind CSS Integration
Imigi uses Tailwind CSS internally for its component styling. The editor bundles its own scoped Tailwind build, so it will not conflict with your project's Tailwind setup.
Custom Design Tokens
Imigi extends Tailwind's default configuration with custom design tokens in its internal tailwind.config.js:
Spacing
| Token | Value | Usage |
|---|---|---|
4.5 |
1.125rem (18px) |
Small icon button sizing |
18 |
4.5rem (72px) |
Tool panel width |
50 |
12.5rem (200px) |
Side panel width |
70 |
17.5rem (280px) |
Extended panel width |
Font Size
| Token | Size | Line Height |
|---|---|---|
2xs |
0.625rem (10px) |
0.75rem |
Border Radius
| Token | Value | Usage |
|---|---|---|
panel |
0.5rem (8px) |
Panels and cards |
input |
0.375rem (6px) |
Input fields and small controls |
button |
0.5rem (8px) |
Buttons and action elements |
If your project also uses Tailwind CSS, you do not need to worry about conflicts. Imigi's Tailwind classes are scoped within the .imigi-root container and will not leak into your application's styles.
Responsive Design
Imigi includes built-in responsive behavior that adapts the editor layout and controls for different screen sizes, including mobile phones and tablets.
Overlay Mode on Mobile
By default, Imigi can be configured to switch to an overlay (fullscreen) mode on small screens. This gives users the maximum canvas area for editing on constrained viewports.
Imigi.init({
selector: '#editor',
ui: {
forceOverlayModeOnMobile: true,
},
});
Touch Support
Imigi automatically detects touch-capable devices and adjusts its interaction model accordingly:
- Pinch to zoom — Zoom in and out of the canvas using standard pinch gestures.
- Touch drawing — The draw tool supports finger and stylus input with pressure sensitivity (where available).
- Drag and resize — Objects can be moved, resized, and rotated using touch gestures.
- Swipe navigation — Swipe between tool panels on small screens.
Mobile-Friendly Controls
On smaller screens, the editor UI automatically adjusts:
- Tool panels collapse into a compact bottom sheet layout.
- Buttons and touch targets are enlarged to meet minimum 44px accessibility guidelines.
- The toolbar switches from horizontal to a scrollable icon strip.
- Color pickers and sliders are optimized for touch interaction.
Imigi uses an internal breakpoint at 768px viewport width to switch between desktop and mobile layouts. You do not need to add your own media queries for the editor — it handles responsiveness internally.
Brand-Matching Examples
Below are three complete custom theme configurations you can use as starting points for matching your brand identity.
1. Warm Orange / Amber Theme
A warm, inviting theme suitable for creative and lifestyle applications.
{
name: 'warm-amber',
isDark: false,
colors: {
'--be-foreground-base': '41 37 36', // stone-800
'--be-primary': '217 119 6', // amber-600
'--be-background': '255 251 235', // amber-50
'--be-background-alt': '254 243 199', // amber-100
'--be-paper': '255 255 255', // white
},
}
2. Cool Teal / Cyan Theme
A clean, professional theme ideal for business and productivity applications.
{
name: 'cool-teal',
isDark: true,
colors: {
'--be-foreground-base': '204 251 241', // teal-100
'--be-primary': '20 184 166', // teal-500
'--be-background': '15 23 42', // slate-900
'--be-background-alt': '30 41 59', // slate-800
'--be-paper': '51 65 85', // slate-700
},
}
3. Purple / Violet Theme
A vibrant, modern theme that works well for creative tools and design-oriented applications.
{
name: 'vivid-violet',
isDark: false,
colors: {
'--be-foreground-base': '46 16 101', // violet-950
'--be-primary': '139 92 246', // violet-500
'--be-background': '245 243 255', // violet-50
'--be-background-alt': '237 233 254', // violet-100
'--be-paper': '255 255 255', // white
},
}
Using Multiple Custom Themes
You can register all three themes at once and switch between them dynamically:
Imigi.init({
selector: '#editor',
ui: {
activeTheme: 'warm-amber',
themes: [
{ name: 'warm-amber', isDark: false, colors: { /* ... */ } },
{ name: 'cool-teal', isDark: true, colors: { /* ... */ } },
{ name: 'vivid-violet', isDark: false, colors: { /* ... */ } },
],
},
});
// Later, switch themes at runtime
imigi.setConfig({ ui: { activeTheme: 'cool-teal' } });
When building a theme selector UI, store the user's theme preference in localStorage and apply it on initialization. This gives returning users a consistent experience without having to re-select their preferred theme each time.