Skip to content

Custom Theme

Learn how to create and customize themes in VitePress.

Theme Structure

Basic Theme Setup

Create a custom theme by extending the default theme:

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

export default {
  extends: DefaultTheme,
  enhanceApp({ app, router, siteData }) {
    // App-level enhancements
  }
}

Theme Directory Structure

.vitepress/
└── theme/
    ├── index.js          # Theme entry
    ├── custom.css        # Custom styles
    ├── components/       # Custom components
    │   ├── MyComponent.vue
    │   └── CustomLayout.vue
    └── layouts/          # Custom layouts
        └── MyLayout.vue

Customizing Styles

CSS Variables

Override default theme variables:

css
/* .vitepress/theme/custom.css */
:root {
  --vp-c-brand-1: #646cff;
  --vp-c-brand-2: #747bff;
  --vp-c-brand-3: #9499ff;
  
  --vp-home-hero-name-color: transparent;
  --vp-home-hero-name-background: linear-gradient(120deg, #bd34fe 30%, #41d1ff);
}

Component Styling

Style specific components:

css
.VPNavBar {
  background-color: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
}

.VPSidebar {
  border-right: 1px solid var(--vp-c-divider);
}

.VPContent {
  max-width: 1200px;
}

Custom Components

Global Components

Register components globally:

javascript
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyComponent from './components/MyComponent.vue'

export default {
  extends: DefaultTheme,
  enhanceApp({ app }) {
    app.component('MyComponent', MyComponent)
  }
}

Layout Components

Create custom layout components:

vue
<!-- .vitepress/theme/components/CustomLayout.vue -->
<template>
  <Layout>
    <template #nav-bar-title-after>
      <span class="custom-badge">Beta</span>
    </template>
    
    <template #sidebar-nav-before>
      <div class="custom-sidebar-header">
        <h3>Quick Links</h3>
      </div>
    </template>
  </Layout>
</template>

<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>

Layout Customization

Custom Layouts

Create completely custom layouts:

vue
<!-- .vitepress/theme/layouts/CustomHome.vue -->
<template>
  <div class="custom-home">
    <header class="hero">
      <h1>{{ $site.title }}</h1>
      <p>{{ $site.description }}</p>
    </header>
    
    <main class="content">
      <Content />
    </main>
    
    <footer class="footer">
      <p>&copy; 2024 My Site</p>
    </footer>
  </div>
</template>

<script setup>
import { useData } from 'vitepress'
const { site } = useData()
</script>

Layout Slots

Use available layout slots:

javascript
// Available slots in default theme
- nav-bar-title-before
- nav-bar-title-after  
- nav-bar-content-before
- nav-bar-content-after
- nav-screen-content-before
- nav-screen-content-after
- sidebar-nav-before
- sidebar-nav-after
- page-top
- page-bottom
- not-found
- home-hero-before
- home-hero-info
- home-hero-actions
- home-hero-after
- home-features-before
- home-features-after
- doc-footer-before
- doc-before
- doc-after
- aside-top
- aside-bottom
- aside-outline-before
- aside-outline-after
- aside-ads-before
- aside-ads-after

Advanced Customization

Theme Configuration

Add theme-specific configuration:

javascript
// .vitepress/config.js
export default {
  themeConfig: {
    // Custom theme options
    customOption: 'value',
    
    // Override default theme config
    nav: [...],
    sidebar: {...}
  }
}

Plugin Integration

Integrate with Vite plugins:

javascript
// .vitepress/config.js
import { defineConfig } from 'vitepress'

export default defineConfig({
  vite: {
    plugins: [
      // Add Vite plugins
    ]
  }
})

Theme Distribution

Package Structure

Structure for distributing themes:

my-vitepress-theme/
├── package.json
├── index.js
├── styles/
│   └── vars.css
├── components/
│   └── MyComponent.vue
└── layouts/
    └── Layout.vue

Package Configuration

json
{
  "name": "my-vitepress-theme",
  "version": "1.0.0",
  "main": "index.js",
  "peerDependencies": {
    "vitepress": "^1.0.0"
  }
}

Theme Entry Point

javascript
// index.js
import DefaultTheme from 'vitepress/theme'
import './styles/vars.css'

export default {
  extends: DefaultTheme,
  // Theme customizations
}

Best Practices

Performance

  • Minimize CSS bundle size
  • Use CSS variables for theming
  • Optimize component loading
  • Implement proper caching

Accessibility

  • Maintain proper contrast ratios
  • Ensure keyboard navigation
  • Use semantic HTML
  • Test with screen readers

Maintainability

  • Follow consistent naming conventions
  • Document theme customizations
  • Use TypeScript for better DX
  • Implement proper testing

VitePress Development Guide