Two things you can theme
In GrapesJS there are two separate surfaces: the editor UI (panels, buttons, managers) and the canvas (the page being edited, which lives in an iframe). They’re styled independently. This guide rebrands the UI with CSS variables and themes the canvas separately.
1. Override the UI color variables
GrapesJS exposes CSS custom properties. Load your stylesheet after the GrapesJS CSS and override them:
:root {
--gjs-primary-color: #1f2937; /* top bars / base */
--gjs-secondary-color: #e5e7eb; /* icons / text */
--gjs-tertiary-color: #6d28d9; /* active / accents */
--gjs-quaternary-color: #7c3aed; /* highlights */
}
These four variables cover most branding needs — the editor chrome picks them up immediately.
2. Target editor classes for finer control
/* GrapesJS UI classes are prefixed with gjs- */
.gjs-pn-btn.gjs-pn-active { color: var(--gjs-tertiary-color); }
.gjs-block { border-radius: 8px; }
3. Theme the canvas independently
grapesjs.init({
container: '#gjs',
canvas: {
// Stylesheets injected into the canvas iframe (your site's CSS, fonts, etc.)
styles: ['/assets/site.css', 'https://fonts.googleapis.com/css2?family=Inter'],
},
});
Because the canvas is an iframe, its styles never leak into the editor UI and vice-versa — so the page preview matches production while the UI keeps your brand.
Tips
Get the order and scope right. Your override stylesheet must load after grapes.min.css or the defaults win. The CSS custom properties (--gjs-primary-color and friends) restyle the editor UI only — the canvas is a separate iframe themed through canvas.styles, so don't expect host changes to reach it. To support a dark UI, redefine the variables under your dark scope (e.g. .dark :root) rather than overriding dozens of classes. And lean on the four colour variables before targeting gjs- classes directly — they cover most branding with far less code.
Prerequisites
You need a running GrapesJS editor and a stylesheet that loads after the GrapesJS CSS. Remember the two surfaces: the editor UI (panels, buttons) and the canvas (the page being edited, in an iframe) — they're styled independently.
The colour variables in full
GrapesJS exposes CSS custom properties for the UI. Override the four core colours, plus the font colour, in your own stylesheet:
:root {
--gjs-primary-color: #1f2937;
--gjs-secondary-color: #e5e7eb;
--gjs-tertiary-color: #6d28d9;
--gjs-quaternary-color: #7c3aed;
--gjs-font-color: #111827;
}
Support a dark UI
Redefine the variables under your dark scope rather than overriding dozens of classes:
.dark :root, :root[data-theme="dark"] {
--gjs-primary-color: #0b1220;
--gjs-secondary-color: #94a3b8;
}
Theme the canvas independently
grapesjs.init({
container: '#gjs',
canvas: { styles: ['/assets/site.css', 'https://fonts.googleapis.com/css2?family=Inter'] },
});
Because the canvas is an iframe, its styles never leak into the editor UI — so the preview matches production while the chrome keeps your brand.
Best practices
Lean on the colour variables before targeting gjs- classes directly — they
cover most branding with far less code and survive GrapesJS updates better. Load your
overrides after the base CSS so they win. Keep canvas fonts and resets in
canvas.styles so the preview is faithful.
Next steps
Pair custom styling with a custom plugin and custom blocks, or explore styling plugins and the full GrapesJS plugins catalog on GJS.Market.
FAQ
How do I change the GrapesJS editor colors?
Override the CSS custom properties (--gjs-primary-color,
--gjs-secondary-color, --gjs-tertiary-color,
--gjs-quaternary-color) in a stylesheet loaded after the GrapesJS CSS.
Is the canvas styled separately from the UI?
Yes — the canvas is an iframe with its own document. Use
canvas.styles to add stylesheets to it.
Can I fully restyle the panels?
Yes — target the gjs- prefixed classes for fine control, though the
variables cover most branding.