You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
vitepress/docs/guide/extending-default-theme.md

4.3 KiB

Extending the Default Theme

VitePress' default theme is optimized for documentation, and can be customized. Consult the Default Theme Config Overview for a comprehensive list of options.

However, there are a number of cases where configuration alone won't be enough. For example:

  1. You need to tweak the CSS styling;
  2. You need to modify the Vue app instance, for example to register global components;
  3. You need to inject custom content into the theme via layout slots.

These advanced customizations will require using a custom theme that "extends" the default theme.

:::tip Before proceeding, make sure to first read Using a Custom Theme to understand how custom themes work. :::

Customizing CSS

The default theme CSS is customizable by overriding root level CSS variables:

// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import './custom.css'

export default DefaultTheme
/* .vitepress/theme/custom.css */
:root {
  --vp-c-brand: #646cff;
  --vp-c-brand-light: #747bff;
}

See default theme CSS variables that can be overridden.

Registering Global Components

// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'

export default {
  extends: DefaultTheme,
  enhanceApp(ctx) {
    // register your custom global components
    ctx.app.component('MyGlobalComponent' /* ... */)
  }
}

Since we are using Vite, you can also leverage Vite's glob import feature to auto register a directory of components.

Layout Slots

The default theme's <Layout/> component has a few slots that can be used to inject content at certain locations of the page. Here's an example of injecting a component into the before outline:

// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyLayout from './MyLayout.vue'

export default {
  ...DefaultTheme,
  // override the Layout with a wrapper component that
  // injects the slots
  Layout: MyLayout
}
<!--.vitepress/theme/MyLayout.vue-->
<script setup>
import DefaultTheme from 'vitepress/theme'

const { Layout } = DefaultTheme
</script>

<template>
  <Layout>
    <template #aside-outline-before>
      My custom sidebar top content
    </template>
  </Layout>
</template>

Or you could use render function as well.

// .vitepress/theme/index.js
import { h } from 'vue'
import DefaultTheme from 'vitepress/theme'
import MyComponent from './MyComponent.vue'

export default {
  ...DefaultTheme,
  Layout() {
    return h(DefaultTheme.Layout, null, {
      'aside-outline-before': () => h(MyComponent)
    })
  }
}

Full list of slots available in the default theme layout:

  • When layout: 'doc' (default) is enabled via frontmatter:
    • doc-footer-before
    • doc-before
    • doc-after
    • sidebar-nav-before
    • sidebar-nav-after
    • aside-top
    • aside-bottom
    • aside-outline-before
    • aside-outline-after
    • aside-ads-before
    • aside-ads-after
  • When layout: 'home' is enabled via frontmatter:
    • home-hero-before
    • home-hero-info
    • home-hero-image
    • home-hero-after
    • home-features-before
    • home-features-after
  • On not found (404) page:
    • not-found
  • Always:
    • layout-top
    • layout-bottom
    • nav-bar-title-before
    • nav-bar-title-after
    • nav-bar-content-before
    • nav-bar-content-after
    • nav-screen-content-before
    • nav-screen-content-after

Overriding Internal Components

You can use Vite's aliases to replace default theme components with your custom ones:

import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vitepress'

export default defineConfig({
  vite: {
    resolve: {
      alias: [
        {
          find: /^.*\/VPNavBar\.vue$/,
          replacement: fileURLToPath(
            new URL('./components/CustomNavBar.vue', import.meta.url)
          )
        }
      ]
    }
  }
})

To know the exact name of the component refer our source code. Since the components are internal, there is a slight chance their name is updated between minor releases.