close

自定义主题

  1. 对于 CSS,Rspress 提供了 CSS 变量BEM 类名进行定制。

  2. 对于 JS / React,Rspress 基于 ESM 重导出覆盖实现了一套运行时接口,支持对内置组件进行修改或替换,实现自己的首页、侧边栏、搜索组件等。

    在此之上有两种使用模式:

    • wrap:通过 props / 插槽来对 Rspress 内置的组件进行 包装 并增强。
    • eject:直接 覆盖 整个组件,可以使用 rspress eject 命令将源码拷贝到本地直接修改并覆盖。

下面会根据主题定制化的程度会依次进行介绍。

CSS 变量

Rspress 暴露了一些常用的 CSS 变量,相比重写 Rspress 内置的 React 组件,覆盖 CSS 变量实现定制化更简单也更易维护。你可以在 UI - CSS 变量 页面查看这些 CSS 变量,并通过:

theme/index.tsx
theme/index.css
import './index.css';
export * from '@rspress/core/theme-original';

BEM 类名

Rspress 内置组件均使用 BEM 命名规范。你可以使用这些类名进行样式覆盖,覆盖方式和 CSS 变量 一致。

.rp-[component-name]__[element-name]--[modifier-name] {
  /* 样式 */
}

例如:

.rp-nav {
}
.rp-link {
}
.rp-tabs {
}
.rp-codeblock {
}
.rp-codeblock__title {
}
.rp-codeblock__description {
}
.rp-nav-menu__item,
.rp-nav-menu__item--active {
}

使用 ESM 重导出覆盖内置组件

默认情况下,你需要在项目根目录下创建一个 theme 目录,然后在 theme 目录下创建一个 index.ts 或者 index.tsx 文件,该文件用于导出主题组件。

docs
theme
index.tsx
rspress.config.ts

你可以使用 @rspress/core/theme-original 的内置组件,来编写 theme/index.tsx 文件:

theme/index.tsx
import { Layout as BasicLayout } from '@rspress/core/theme-original';

const Layout = () => <BasicLayout beforeNavTitle={<div>some content</div>} />;

export { Layout }; 
export * from '@rspress/core/theme-original'; 

通过 ESM 重导出 覆写内置的组件,所有 Rspress 内部引用的内置组件都会优先使用你重导出的版本。

关于 @rspress/core/theme-original

@rspress/core/theme-original 用于避免循环引用,仅在自定义主题的时候使用。

docs
index.mdx<-- 使用 "@rspress/core/theme"
theme
index.tsx<-- 使用 "@rspress/core/theme-original"
rspress.config.ts
  1. docs 目录下,使用 @rspress/core/theme@rspress/core/theme 指向你的 theme/index.tsx

  2. theme 目录下,使用 @rspress/core/theme-original@rspress/core/theme-original 永远指向 Rspress 内置的主题组件。

Wrap:传 props/插槽

Wrap 指在重导出的组件上增加 props。下面是一个例子,在导航栏标题前面插入一些内容:

theme/index.tsx
i18n.json
import { Layout as BasicLayout } from '@rspress/core/theme-original';
import { useI18n } from '@rspress/core';

const Layout = () => {
  const t = useI18n();
  return <BasicLayout beforeNavTitle={<div>{t('some content')}</div>} />;
};

export { Layout };
export * from '@rspress/core/theme-original';
Tip

Layout 组件设计了一系列的插槽 props 专门用于 wrap,你可以通过这些 props 来扩展默认主题的布局:

Eject:直接覆盖整个组件

Eject 指将 Rspress 单个内置组件直接进行覆盖,全部使用自己的版本。对此 Rspress 提供了 rspress eject [component] 命令将内置组件的源码拷贝到本地并直接改动,步骤如下:

  1. 执行 CLI ,Rspress 会将指定组件的源码 eject 到本地 theme/components 目录,不会 eject 依赖。

  2. 更新 theme/index.tsx 重导出:

theme/index.tsx
// 假设你 eject 了 DocFooter 组件
export { DocFooter } from './components/DocFooter';
export * from '@rspress/core/theme-original';
  1. 任意修改 theme/components/DocFooter.tsx,使它满足你的需要。

为了方便用户 eject,Rspress 的组件经过细粒度的拆分,你可在 布局组件 中看到哪些组件适合 eject。

你是否真的需要 eject?

eject 会增加一定的维护成本,因为 Rspress 未来版本更新时,这些被 eject 的组件不会自动获得更新,你需要手动对比并合并变更。

请先查看 wrap 能否满足你的需求,只有在 wrap 无法满足你的需求时,才考虑 eject。