close
  • 中文
  • 自定义主题

    For your Agent

    如果你正在使用 Coding Agent,可以安装 rspress-custom-theme Agent Skill,让 Agent 帮你生成一个全新的主题。

    如果想了解更多 Rspress AI 辅助开发能力,请查看 AI 页面

    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 变量,并复制到项目中进行样式覆盖,例如:

    docs
    index.mdx
    theme
    index.tsx
    index.css<-- 复制 CSS 变量代码到这里来进行样式覆盖
    rspress.config.ts
    theme/index.tsx
    import './index.css';
    export * from '@rspress/core/theme-original';

    另一种方式是使用 rspress.config.ts 中的 globalStyles 配置:

    rspress.config.ts
    import { defineConfig } from '@rspress/core';
    import path from 'path';
    
    export default defineConfig({
      globalStyles: path.join(__dirname, 'styles/index.css'), // 指向你创建的 CSS 文件
    });

    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。