Change CSS styles

Redactor ships default typography and spacing for editable content. Those styles target the content class on the editable root — by default rx-content.

You customize content in three ways:

  1. Override CSS rules.rx-content p { font-size: 18px; }
  2. Override CSS variables — change --rx-body-size, --rx-text-color, etc.
  3. Use your own class — set classname: 'article' and write styles for .article

Default hook — .rx-content#

By default Redactor adds rx-content to the editable element:

const app = Redactor('#entry');
// editable root: <div class="rx-content rx-editor …" contenteditable>

Scope your overrides under .rx-content so they win over built-in rules:

.rx-content p {
    font-size: 18px;
    line-height: 1.7;
}

.rx-content h2 {
    font-family: Georgia, serif;
}

Load the editor stylesheet on the page (or in an iframe host) so the default content styles are available to override.

CSS variables#

Content styles use --rx-* variables. Override them on :root, on a page wrapper, or on .rx-content itself.

Quick tweak — one variable

.rx-content {
    --rx-body-size: 18px;
    --rx-text-color: #222;
    --rx-link-color: #0066cc;
}

Colors and borders often pull from shared palette tokens (--rx-fg-dark-body, --rx-border-dark-subtle, …). Overriding a content variable is usually enough; you rarely need to touch the palette directly.

Font

Variable Default Used for
--rx-font-text sans-serif Body text
--rx-font-heading inherit Headings
--rx-font-mono monospace code, var, pre

Size and spacing

Variable Default Used for
--rx-body-size 16px Base font size on .rx-content
--rx-content-line-height 1.6 Line height
--rx-heading-top 24px Margin above h2h6
--rx-heading-bottom 8px Margin below headings
--rx-paragraph-bottom 16px Margin below blocks (p, ul, table, …)
--rx-line-padding half of --rx-paragraph-bottom Empty line placeholder height
--rx-h1-size--rx-h6-size 2.25em1em Heading sizes
--rx-heading-letter-spacing -0.01em Headings
--rx-lead-size 1.25em .lead class
--rx-small-size 0.875em .small class
--rx-table-size 0.9375em Tables
--rx-pre-size 0.875em pre blocks
--rx-code-size 0.875em Inline code
--rx-kbd-size 0.875em kbd
--rx-caption-size 0.875em figcaption
--rx-quote-size 1em Blockquote text
--rx-quote-footer-size 1em Blockquote footer / caption
--rx-list-indent 20px List left margin

Colors

Variable Default Used for
--rx-body-bg transparent Content background
--rx-text-color --rx-fg-dark-body Body text
--rx-heading-color --rx-fg-dark-accent Headings
--rx-link-color --rx-fg-info-accent Links
--rx-pre-color --rx-fg-dark-body pre text
--rx-pre-bg --rx-bg-dark-section pre background
--rx-code-color --rx-fg-dark-body Inline code
--rx-code-bg --rx-bg-dark-surface Inline code background
--rx-kbd-color --rx-fg-dark-body kbd text
--rx-kbd-bg --rx-bg-raised kbd background
--rx-var-color --rx-fg-dark-body var element

Optional (with fallbacks in rules):

Variable Fallback Used for
--rx-table-color --rx-text-color Table text
--rx-caption-color --rx-text-color Figure captions
--rx-caption-bg transparent Caption background
--rx-quote-color --rx-text-color Blockquote text
--rx-quote-footer-color --rx-text-color Quote attribution

Borders

Variable Default Used for
--rx-table-border --rx-border-dark-subtle Table cells
--rx-line-border --rx-border-dark-subtle hr
--rx-pre-border transparent pre
--rx-code-border transparent Inline code
--rx-kbd-border --rx-border-dark-default kbd
--rx-quote-border --rx-border-dark-accent Blockquote left border
--rx-quote-border-width 3px Blockquote border width
--rx-abbr-border rgb(0 0 0 / 40%) abbr underline (light); adjusted in dark theme

Image layout

Float and outset helpers use these variables:

Variable Default Used for
--rx-float-width 200px Max width of floated images
--rx-float-margin 1em Margin around floated images
--rx-outset 26px Outset shift (.outset-left, .outset-right, .outset-both)

Example — wider floats and larger outset:

.rx-content {
    --rx-float-width: 280px;
    --rx-outset: 40px;
}

Custom classname#

Replace the default hook with your own class:

const app = Redactor('#entry', {
    classname: 'article'
});

The editable root gets article instead of rx-content. Built-in .rx-content rules no longer apply — you style content yourself:

.article {
    font-size: 18px;
    line-height: 1.6;
    color: #111;
}

.article p {
    margin-bottom: 1em;
}

.article h2 {
    font-size: 1.5rem;
    margin-top: 1.5em;
}

classname accepts multiple classes (space-separated):

classname: 'prose prose-slate max-w-none'

Typical with Tailwind Typography or your design system.

Related option: classes adds CSS classes to block types inside the editor (blocks, tags), not to the editable root. Do not confuse it with classname.

Dark theme#

Redactor sets rx-data-theme="light" or rx-data-theme="dark" on the editor container and on the document root (including iframe mode). Use it to scope dark overrides.

Override rules per theme

/* light */
.rx-content p {
    color: #111;
}

/* dark */
[rx-data-theme="dark"] .rx-content p {
    color: #cdcdcd;
}

Override variables (recommended)

Most content colors already react to theme through palette tokens. For explicit control:

.rx-content {
    --rx-text-color: #111;
    --rx-heading-color: #000;
    --rx-link-color: #0066cc;
}

[rx-data-theme="dark"] .rx-content {
    --rx-text-color: #cdcdcd;
    --rx-heading-color: #f0f0f0;
    --rx-link-color: #6eb5ff;
    --rx-body-bg: transparent;
}

Set the editor theme in options:

const app = Redactor('#entry', {
    theme: 'dark'   // 'light' | 'dark' | 'auto'
});

Or at runtime: app.theme.set('dark').

If your site uses a custom attribute (e.g. data-theme), enable themeAttr — Redactor mirrors the resolved mode onto <html>.

Use page styles#

When you already have site-wide typography and do not want Redactor’s default content class:

const app = Redactor('#entry', {
    nostyle: true
});

With nostyle: true and default classname: 'rx-content', Redactor does not add rx-content. The editable element keeps only editor classes (rx-editor, …) and inherits styles from your page.

Write CSS for the host or a wrapper you control:

#entry p {
    font-size: 18px;
}

nostyle only skips the default rx-content class. If you set a custom classname, that class is still applied:

Redactor('#entry', {
    nostyle: true,
    classname: 'article'   // "article" is still added
});

Pair nostyle: true with classname: 'rx-content' when you want full control without the built-in class name on the element.

Iframe mode#

In iframe mode, content styles load inside the iframe document. Inject your overrides with custom.css:

const app = Redactor('#entry', {
    css: '/assets/redactor/',
    custom: {
        css: [
            '/styles/my-content.css',
            '.rx-content { --rx-body-size: 18px; }'
        ]
    }
});