CSS theming
Customize Rho's visuals — CSS variables are the preferred path; class overrides and full custom CSS also supported.
Importing default CSS
import '@rho/md/css';
Or:
<link rel="stylesheet" href="path/to/@rho/md/css/stl-md.css">
The default CSS includes all DSL styles + light/dark themes + responsive breakpoints.
CSS variables (preferred customization)
Rho exposes all customizable colors / spacing / typography as CSS variables, scoped to .markdown-body:
.markdown-body {
/* === Color base === */
--bg-color: #ffffff;
--text-color: #1a1a2e;
--muted-color: #6b7280;
--border-color: #e5e7eb;
--code-bg: #f8f8f8;
/* === Accent palette (6 colors) === */
--accent-blue: #2563eb;
--accent-red: #dc2626;
--accent-green: #16a34a;
--accent-yellow: #ca8a04;
--accent-purple: #9333ea;
--accent-gray: #6b7280;
/* === Spacing === */
--spacing-xs: 4px;
--spacing-sm: 8px;
--spacing-md: 16px;
--spacing-lg: 24px;
--spacing-xl: 32px;
/* === Typography === */
--font-body: -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif;
--font-mono: 'JetBrains Mono', monospace;
--font-size-base: 16px;
--line-height-base: 1.65;
/* === Border radius === */
--radius-sm: 4px;
--radius-md: 8px;
--radius-lg: 12px;
}
Change brand colors — one line:
.markdown-body {
--accent-blue: #007aff; /* iOS blue */
--accent-purple: #a020f0; /* Custom purple */
}
→ Every callout / card / annotation using accent=blue or accent=purple updates accordingly.
Dark theme
Rho ships a default dark theme. Two ways to trigger:
Option A: data-theme attribute
<div class="markdown-body" data-theme="dark">
...
</div>
Option B: follow system preferences
@media (prefers-color-scheme: dark) {
.markdown-body {
--bg-color: #0f1115;
--text-color: #e8ecf1;
--muted-color: #8a93a3;
--border-color: #2a2f3c;
--code-bg: #1c2030;
--accent-blue: #60a5fa;
--accent-red: #f87171;
--accent-green: #34d399;
--accent-yellow: #fbbf24;
--accent-purple: #c084fc;
--accent-gray: #94a3b8;
}
}
CSS class hooks
Rho's HTML uses stable class names so you can completely override default styles:
| Class | Maps to |
|---|---|
.markdown-body |
container |
.rho-callout / .rho-callout-info / .rho-callout-warn / .rho-callout-zen / etc. |
Callout |
.rho-layout-grid / .rho-card / .rho-card-blue / etc. |
Layout |
.rho-annotate / .rho-anno / .rho-anno-red / etc. |
Annotate |
.rho-tabs / .rho-tabs-bar / .rho-tab-btn / .rho-tab-active / .rho-tab-panel |
Tabs |
.rho-stepper / .rho-stepper-progress / .rho-step-marker / .rho-step-active / .rho-step-panel / .rho-stepper-nav |
Stepper |
.rho-timeline / .rho-event / .rho-event-blue / etc. |
Timeline |
.rho-modal-trigger / .rho-modal |
Modal |
.rho-interact / .rho-slider / .rho-input / .rho-select / .rho-toggle / .rho-button |
Interact controls |
.rho-template-output |
template output |
.rho-vega-chart |
Vega-Lite chart container |
.rho-svg |
SVG scene container |
Full class list in source (the CSS file itself).
Custom callout types
Rho ships 8 built-in callout types (INFO/WARN/ZEN + 5 GFM). Add your own:
.markdown-body .rho-callout-custom-tip {
--callout-bg: rgba(255, 200, 0, 0.1);
--callout-border: orange;
--callout-icon-color: orange;
}
.markdown-body .rho-callout-custom-tip .rho-callout-icon::before {
content: "💡";
}
Then in markdown > [!CUSTOM_TIP] uses this style (Rho doesn't recognize but preserves the type string in class).
Note:
> [!CUSTOM_TIP]shows as[!CUSTOM_TIP]literal in non-supporting readers — non-standard types break plain-text fallback elegance. Recommendation: stick to the 8 standard types.
Per-block style overrides
/* Change layout grid default gap */
.markdown-body .rho-layout-grid {
gap: 32px;
}
/* Change tab bar color */
.markdown-body .rho-tabs-bar {
background: linear-gradient(to right, #007aff, #5856d6);
}
/* Change slider track color */
.markdown-body .rho-slider input[type="range"] {
accent-color: #ff3b30;
}
Tailwind / CSS-in-JS integration
Tailwind
Rho CSS doesn't conflict with Tailwind (different namespaces). In a Tailwind project:
import '@rho/md/css'for Rho default styles- Use Tailwind for your page / wrapper
- Inside
.markdown-body, Rho CSS rules; outside, Tailwind
If you want Rho to use your Tailwind colors:
@layer components {
.markdown-body {
--accent-blue: theme('colors.blue.600');
--accent-red: theme('colors.red.600');
--bg-color: theme('colors.white');
--text-color: theme('colors.gray.900');
}
}
CSS-in-JS (Emotion / styled-components)
import { css, Global } from '@emotion/react';
const rhoTheme = css`
.markdown-body {
--accent-blue: ${myTheme.brand};
--accent-green: ${myTheme.success};
/* ... */
}
`;
<>
<Global styles={rhoTheme} />
<div className="markdown-body">{rhoHTML}</div>
</>
Fully custom styles (skip default CSS)
// Don't import '@rho/md/css'
import { hydrateAll, renderRho } from '@rho/md';
Then write fully your own .rho-* class CSS (use the default CSS file as a starting reference). Suitable for:
- Deep integration with an existing design system
- Fully custom visuals
- Removing default Rho appearance overhead
CSS file location / size
@rho/md/css/stl-md.css ← Full CSS (~30 KB unminified)
@rho/md/css/stl-md.min.css ← Minified (~8 KB)
See also
- API reference
- Quick start — Standard import
- Hydration utilities — Doesn't affect CSS (hydration adds classes, not styles)
- Default CSS source file:
node_modules/@rho/md/css/stl-md.css(look up specific rules)