rspress-custom-theme
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRspress Custom Theme
Rspress 自定义主题
Guide for customizing Rspress (v2) themes. Rspress offers four levels of customization, from lightest to heaviest. Always prefer the lightest approach that meets the requirement — lighter approaches are more maintainable and survive Rspress upgrades.
Rspress(v2)主题定制指南。Rspress 提供四种定制层级,从最轻量到最重度。请优先选择满足需求的最轻量方案——轻量方案更易维护,且能在 Rspress 版本升级后继续使用。
Workflow
工作流程
- Understand the user's goal — what do they want to change? (colors, layout, inject content, replace a component entirely?)
- Pick the right level using the decision flow below
- Set up if needed (Levels 1A, 3, 4 all need it)
theme/index.tsx - Implement following the patterns in this skill and reference files
- Verify the user's Rspress version is v2 (imports use not
@rspress/core/*)rspress/*
- 明确用户目标——用户想要更改什么?(颜色、布局、注入内容、完全替换组件?)
- 根据下方决策流程选择合适的层级
- 按需设置 (层级1A、3、4均需用到)
theme/index.tsx - 参考本指南的模式和参考文件实现定制
- 验证用户的 Rspress 版本为 v2(导入路径使用 而非
@rspress/core/*)rspress/*
Decision Flow
决策流程
| User wants to... | Level | Approach |
|---|---|---|
| Change brand colors, fonts, spacing, shadows | 1 | CSS variables |
| Adjust a specific component's style (borders, padding, etc.) | 2 | BEM class overrides |
| Add content around existing components (banners, footers, logos) | 3 | Layout slots (wrap) |
Override MDX rendering (custom | 3 | |
| Wrap the app in a provider (state, analytics, auth) | 4 | Eject |
| Replace built-in icons (logo, GitHub, search, etc.) | — | Icon re-export |
| Completely replace a built-in component | 4 | Eject that component |
| Add a global floating component (back-to-top, chat widget) | — | |
| Control page layout structure (hide sidebar, blank page) | — | Frontmatter |
| 用户需求 | 层级 | 实现方式 |
|---|---|---|
| 更改品牌颜色、字体、间距、阴影 | 1 | CSS variables |
| 调整特定组件的样式(边框、内边距等) | 2 | BEM 类覆盖 |
| 在现有组件周围添加内容(横幅、页脚、Logo) | 3 | Layout slots(封装) |
覆盖 MDX 渲染逻辑(自定义 | 3 | |
| 用提供者包裹整个应用(状态、统计、权限) | 4 | Eject |
| 替换内置图标(Logo、GitHub、搜索等) | — | 图标重导出 |
| 完全替换内置组件 | 4 | Eject 目标组件 |
| 添加全局悬浮组件(返回顶部、聊天窗口) | — | |
| 控制页面布局结构(隐藏侧边栏、空白页面) | — | Frontmatter |
theme/index.tsx — The Entry Point
theme/index.tsx — 入口文件
Levels 1A, 3, and 4 all require a file in the project root (sibling to ). This is the single entry point for all theme customizations:
theme/index.tsxdocs/text
project/
├── docs/
├── theme/
│ ├── index.tsx # Theme entry — re-exports + overrides
│ ├── index.css # CSS variable / BEM overrides (optional)
│ └── components/ # Ejected components (Level 4)
└── rspress.config.tsMinimal setup:
tsx
// theme/index.tsx
import './index.css'; // optional
export * from '@rspress/core/theme-original';Critical import rule: Inside files, always import from . The path resolves to your own , which causes circular imports. (In MDX files, is fine — it correctly points to your custom theme.)
theme/@rspress/core/theme-original@rspress/core/themetheme/index.tsxdocs/@rspress/core/theme层级1A、3、4均需要在项目根目录(与 同级)创建 文件。这是所有主题定制的统一入口:
docs/theme/index.tsxtext
project/
├── docs/
├── theme/
│ ├── index.tsx # 主题入口 — 重导出 + 覆盖
│ ├── index.css # CSS 变量 / BEM 覆盖(可选)
│ └── components/ # Eject 出的组件(层级4)
└── rspress.config.ts最小化配置:
tsx
// theme/index.tsx
import './index.css'; // 可选
export * from '@rspress/core/theme-original';重要导入规则:在 目录的文件中,务必从 导入。 路径会指向你自己的 ,从而导致循环导入。(在 目录的 MDX 文件中,使用 是没问题的——它会正确指向你的自定义主题。)
theme/@rspress/core/theme-original@rspress/core/themetheme/index.tsxdocs/@rspress/core/themeLevel 1: CSS Variables
层级1:CSS Variables
Override CSS custom properties for brand colors, backgrounds, text, code blocks, and more.
Option A — (use when you also have component overrides in ):
theme/index.csstheme/index.tsxcss
/* theme/index.css */
:root {
--rp-c-brand: #7c3aed;
--rp-c-brand-light: #8b5cf6;
--rp-c-brand-dark: #6d28d9;
}
.dark {
--rp-c-brand: #a78bfa;
}Option B — (use when you only need CSS changes, no component overrides):
globalStylests
// rspress.config.ts
export default defineConfig({
globalStyles: path.join(__dirname, 'styles/custom.css'),
});Full variable list: Readfor all available CSS variables with light/dark defaults.references/css-variables.md
覆盖 CSS 自定义属性以修改品牌颜色、背景、文字、代码块等样式。
选项A — (当你同时需要在 中覆盖组件时使用):
theme/index.csstheme/index.tsxcss
/* theme/index.css */
:root {
--rp-c-brand: #7c3aed;
--rp-c-brand-light: #8b5cf6;
--rp-c-brand-dark: #6d28d9;
}
.dark {
--rp-c-brand: #a78bfa;
}选项B — (仅需要修改 CSS,无需覆盖组件时使用):
globalStylests
// rspress.config.ts
export default defineConfig({
globalStyles: path.join(__dirname, 'styles/custom.css'),
});完整变量列表:查看获取所有带亮色/暗色默认值的可用 CSS 变量。references/css-variables.md
Level 2: BEM Class Overrides
层级2:BEM 类覆盖
All built-in components follow BEM naming: .
.rp-[component]__[element]--[modifier]Common targets: , , , , , .
.rp-nav.rp-link.rp-tabs.rp-codeblock.rp-codeblock__title.rp-nav-menu__item--activeUse these in your CSS file for targeted style changes when CSS variables aren't granular enough.
所有内置组件均遵循 BEM 命名规范:。
.rp-[component]__[element]--[modifier]常见目标类:、、、、、。
.rp-nav.rp-link.rp-tabs.rp-codeblock.rp-codeblock__title.rp-nav-menu__item--active当 CSS 变量的粒度不足以满足需求时,可在 CSS 文件中使用这些类进行针对性样式修改。
Level 3: Wrap (Layout Slots)
层级3:封装(Layout Slots)
Inject content at specific positions in the layout without replacing built-in components. Override in :
Layouttheme/index.tsxtsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
export function Layout() {
return (
<OriginalLayout beforeNavTitle={<MyLogo />} bottom={<CustomFooter />} />
);
}Use runtime hooks inside slot components — import from : , , , , , , .
@rspress/core/runtimeuseDark()useLang()useVersion()usePage()useSite()useFrontmatter()useI18n()All slots & examples: Readfor the complete slot list and usage patterns including i18n and MDX component overrides.references/layout-slots.md
在布局的特定位置注入内容,无需替换内置组件。在 中覆盖 组件:
theme/index.tsxLayouttsx
// theme/index.tsx
import { Layout as OriginalLayout } from '@rspress/core/theme-original';
export * from '@rspress/core/theme-original';
export function Layout() {
return (
<OriginalLayout beforeNavTitle={<MyLogo />} bottom={<CustomFooter />} />
);
}可在插槽组件中使用运行时钩子——从 导入:、、、、、、。
@rspress/core/runtimeuseDark()useLang()useVersion()usePage()useSite()useFrontmatter()useI18n()所有插槽及示例:查看获取完整插槽列表及使用模式,包括国际化和 MDX 组件覆盖。references/layout-slots.md
Level 4: Eject
层级4:Eject 操作
Copy a built-in component's source for full replacement. Only use when wrap/slots cannot achieve the customization.
bash
rspress eject # list available components
rspress eject DocFooter # eject to theme/components/DocFooter/Then re-export in (named export takes precedence over the wildcard):
theme/index.tsxtsx
export * from '@rspress/core/theme-original';
export { DocFooter } from './components/DocFooter';Component list & patterns: Readfor available components, workflow, and common patterns.references/eject-components.md
复制内置组件的源码以实现完全替换。仅当封装/插槽无法满足定制需求时使用。
bash
rspress eject # 列出可用组件
rspress eject DocFooter # 导出到 theme/components/DocFooter/然后在 中重导出(命名导出优先级高于通配符导出):
theme/index.tsxtsx
export * from '@rspress/core/theme-original';
export { DocFooter } from './components/DocFooter';组件列表及模式:查看获取可用组件、工作流程及常见模式。references/eject-components.md
Custom Icons
自定义图标
Rspress has 27 built-in icons used across the UI. You can replace any of them by re-exporting your own icon component with the same name — no ejection needed. This uses the same mechanism: your named export takes precedence over the wildcard re-export.
theme/index.tsxIcon type: Each icon is a React component or a URL string:
ts
import type { FC, SVGProps } from 'react';
type Icon = FC<SVGProps<SVGSVGElement>> | string;Example 1 — Replace an icon with a custom SVG component:
tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
// Named export overrides the wildcard — replaces the GitHub icon site-wide
export const IconGithub = (props: React.SVGProps<SVGSVGElement>) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}>
<path d="M12 2C6.477 2 2 6.484 2 12.017c0 ..." fill="currentColor" />
</svg>
);Example 2 — Use an SVGR import:
tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
import CustomGithubIcon from './icons/github.svg?react';
export const IconGithub = CustomGithubIcon;Using in MDX or custom components:
SvgWrappermdx
import { SvgWrapper, IconGithub } from '@rspress/core/theme';
<SvgWrapper icon={IconGithub} width={24} height={24} />Available icons: , , , , , , , , , , , , , , , , , , , , , , , , , , .
IconArrowDownIconArrowRightIconCloseIconCopyIconDeprecatedIconDownIconEditIconEmptyIconExperimentalIconExternalLinkIconFileIconGithubIconGitlabIconHeaderIconJumpIconLinkIconLoadingIconMenuIconMoonIconScrollToTopIconSearchIconSmallMenuIconSuccessIconSunIconTitleIconWrapIconWrappedSource: See the icons source for default implementations.
Rspress 包含27个用于 UI 各处的内置图标。你可以通过重导出同名自定义图标组件来替换任意内置图标——无需执行 eject 操作。这使用了与 相同的机制:你的命名导出优先级高于通配符重导出。
theme/index.tsx图标类型:每个图标都是 React 组件或 URL 字符串:
ts
import type { FC, SVGProps } from 'react';
type Icon = FC<SVGProps<SVGSVGElement>> | string;示例1 — 使用自定义 SVG 组件替换图标:
tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
// 命名导出覆盖通配符导出——全站替换 GitHub 图标
export const IconGithub = (props: React.SVGProps<SVGSVGElement>) => (
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" {...props}>
<path d="M12 2C6.477 2 2 6.484 2 12.017c0 ..." fill="currentColor" />
</svg>
);示例2 — 使用 SVGR 导入:
tsx
// theme/index.tsx
export * from '@rspress/core/theme-original';
import CustomGithubIcon from './icons/github.svg?react';
export const IconGithub = CustomGithubIcon;在 MDX 或自定义组件中使用 :
SvgWrappermdx
import { SvgWrapper, IconGithub } from '@rspress/core/theme';
<SvgWrapper icon={IconGithub} width={24} height={24} />可用图标:、、、、、、、、、、、、、、、、、、、、、、、、、、。
IconArrowDownIconArrowRightIconCloseIconCopyIconDeprecatedIconDownIconEditIconEmptyIconExperimentalIconExternalLinkIconFileIconGithubIconGitlabIconHeaderIconJumpIconLinkIconLoadingIconMenuIconMoonIconScrollToTopIconSearchIconSmallMenuIconSuccessIconSunIconTitleIconWrapIconWrapped源码:查看 图标源码 获取默认实现。
Global UI Components
全局 UI 组件
For components that should render on every page without theme overrides:
ts
// rspress.config.ts
export default defineConfig({
globalUIComponents: [
path.join(__dirname, 'components', 'BackToTop.tsx'),
[
path.join(__dirname, 'components', 'Analytics.tsx'),
{ trackingId: '...' },
],
],
});如需在所有页面渲染组件且无需修改主题:
ts
// rspress.config.ts
export default defineConfig({
globalUIComponents: [
path.join(__dirname, 'components', 'BackToTop.tsx'),
[
path.join(__dirname, 'components', 'Analytics.tsx'),
{ trackingId: '...' },
],
],
});Page Types
页面类型
Control layout per page via frontmatter :
pageType| Value | Description |
|---|---|
| Home page with navbar |
| Standard doc with sidebar and outline |
| Doc without sidebar/outline |
| Custom content with navbar only |
| Custom content without navbar |
| 404 error page |
Fine-grained: set , , , individually.
navbar: falsesidebar: falseoutline: falsefooter: false通过 Frontmatter 的 属性控制单页面布局:
pageType| 值 | 描述 |
|---|---|
| 带导航栏的首页 |
| 带侧边栏和大纲的标准文档页 |
| 无侧边栏/大纲的文档页 |
| 仅带导航栏的自定义内容页 |
| 无导航栏的自定义内容页 |
| 404 错误页 |
更精细的控制:可单独设置 、、、。
navbar: falsesidebar: falseoutline: falsefooter: falseCommon Pitfalls
常见陷阱
- Circular import: Using instead of
@rspress/core/themein@rspress/core/theme-originalfiles — causes infinite loop.theme/ - Eject over-use: Ejecting when a Layout slot or CSS variable would suffice — creates upgrade burden.
- Missing re-export: Forgetting in
export * from '@rspress/core/theme-original'— breaks all un-overridden components.theme/index.tsx - v1 imports: Using or
rspress/theme— these are v1 paths. v2 uses@rspress/theme-default.@rspress/core/theme-original
- 循环导入:在 文件中使用
theme/而非@rspress/core/theme——会导致无限循环。@rspress/core/theme-original - 过度使用 Eject:在 Layout 插槽或 CSS 变量可满足需求时仍执行 Eject——会增加版本升级的负担。
- 遗漏重导出:在 中忘记添加
theme/index.tsx——会导致所有未覆盖的组件失效。export * from '@rspress/core/theme-original' - v1 导入路径:使用 或
rspress/theme——这些是 v1 路径,v2 使用@rspress/theme-default。@rspress/core/theme-original
Reference
参考链接
- Custom theme guide: https://rspress.rs/guide/basic/custom-theme
- CSS variables: https://rspress.rs/ui/vars
- Layout component: https://rspress.rs/ui/layout-components/layout
- Built-in icons: https://rspress.rs/ui/icons/
- Built-in hooks: https://rspress.rs/ui/hooks/
- CLI commands (eject): https://rspress.rs/api/commands
- 自定义主题指南:https://rspress.rs/guide/basic/custom-theme
- CSS 变量:https://rspress.rs/ui/vars
- Layout 组件:https://rspress.rs/ui/layout-components/layout
- 内置图标:https://rspress.rs/ui/icons/
- 内置钩子:https://rspress.rs/ui/hooks/
- CLI 命令(eject):https://rspress.rs/api/commands