Appearance
Appearance
Comnto adapts to the page around it while giving you fine-grained control over colours and theming.
Theme modes
- auto (default) Detects the container’s background and switches between light or dark themes automatically. Ideal for dynamic themes or toggles.
- light and dark Locks all elements to the selected palette.
When a background sits in the middle—neither bright nor dark enough—the auto detector might classify it as light or dark. Override the decision by setting data-theme="light" / data-theme="dark" or calling widget.setTheme(...).
To disable automatic background detection, set data-surface or colors.surface to your desired backdrop. Once set, the loader will stop trying to detect the background and use your palette as is.
Brand colours
Pass a colors object to override individual CSS variables. The widget understands the following keys:
primary, primaryHover, onPrimary,
link, linkHover,
success, successHover, onSuccess,
danger, dangerHover, onDanger,
warning, warningHover, onWarning,
surface, surfaceAlt,
textUse the action tokens (primary, link, success, danger, warning) to tint buttons, links, and status badges. Pair them with the matching foreground tokens (onPrimary, onSuccess, onDanger, onWarning) to keep icon and text contrast. surface / surfaceAlt control the widget background layers, while text ensures the default body copy stays readable.
Derived values (border, muted text) are calculated automatically. Provide colours as hex (#2563eb), rgb, or any CSS colour string.
js
const widget = window.comnto({
el: '#comments',
site: 'my-blog',
colors: {
primary: '#2563eb',
primaryHover: '#1d4ed8',
onPrimary: '#ffffff',
surface: '#ffffff',
surfaceAlt: '#f7f7f9',
text: '#111827'
}
});You can update colours later without rebuilding the iframe:
js
widget.setColors({
primary: '#22c55e',
success: '#16a34a',
successHover: '#15803d'
});Custom CSS overrides
For advanced adjustments, Comnto accepts a small custom stylesheet. You can manage it from the dashboard (Appearance → Custom CSS) or set it programmatically by updating the site configuration (css) via the API.
The CSS snippet is sanitised before it reaches the iframe: HTML tags, javascript: URLs, and legacy expression() rules are stripped, and the payload is capped at 16 KB to prevent runaway injections.
js
window.comnto({
el: '#comments',
site: 'my-blog',
css: `
.comnto-comment-card {
border-radius: 1.25rem;
}
.comnto-badge--moderator {
background: linear-gradient(135deg, #2563eb, #22d3ee);
color: #fff;
}
`
});Wrap multiline CSS in a template literal string if you embed it through a framework. Plain HTML attributes accept escaped newlines ( ) or you can keep the snippet compact on one line.
If you prefer declarative embeds, place the CSS on the container:
html
<div
id="comments"
data-site="my-blog"
data-css="
.comnto-editor-toolbar { border: 0; background: transparent; }
.comnto-button--primary { font-family: 'Inter', sans-serif; }
"
></div>Clear the override by sending an empty string (
widget.update({ css: '' })). When no override is present, only the built-in theme variables are applied.
Background detection hints
- When you pass
colors.surface, it takes priority over automatic background detection. - In auto mode, text colour derives from
surfaceunless you supplycolors.text. - The widget may not detect backgrounds accurately if you use gradients or semi-transparent colors. In such cases, you can send extra context from the host page by posting
comnto:backgroundevents. The loader already sends background colors it observes, so you rarely need this.
js
widget.iframe.contentWindow.postMessage({
type: 'comnto:background',
payload: { color: '#f6f6f7' }
}, '*');Branding controls
The footer shows “Powered by Comnto” unless your plan includes white-label branding and you choose to hide it in the dashboard. The widget automatically applies this setting—no code changes needed.
Responsive layout
- The iframe always uses 100% width. Wrap your container in a parent element with the desired max-width to constrain it.
- The widget reports its height whenever content changes (
comnto:height). Use that event if you implement custom iframe resizing logic.
js
widget.on('comnto:height', ({ height }) => {
console.log('New widget height:', height);
});