Default Theme: Footer
Learn how to configure and customize the footer in the VitePress default theme.
Basic Configuration
Simple Footer
Configure a basic footer with message and copyright:
javascript
// .vitepress/config.js
export default {
themeConfig: {
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2024 My Company'
}
}
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Rich Footer with HTML
Use HTML in footer content:
javascript
export default {
themeConfig: {
footer: {
message: 'Released under the <a href="/license">MIT License</a>.',
copyright: 'Copyright © 2024-present <a href="https://example.com">My Company</a>'
}
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Advanced Configuration
Conditional Footer
Show footer only on specific pages:
javascript
export default {
themeConfig: {
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2024 My Company',
// Show footer only on home page
showOnHome: true,
// Hide footer on specific pages
exclude: ['/privacy', '/terms']
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Dynamic Footer Content
Create dynamic footer content:
vue
<script setup>
import { computed } from 'vue'
import { useData } from 'vitepress'
const { page } = useData()
const footerMessage = computed(() => {
if (page.value.relativePath.startsWith('api/')) {
return 'API documentation is updated regularly'
}
if (page.value.relativePath.startsWith('guide/')) {
return 'Need help? Check our community forum'
}
return 'Released under the MIT License'
})
const copyrightYear = computed(() => new Date().getFullYear())
</script>
<template>
<footer class="custom-footer">
<p>{{ footerMessage }}</p>
<p>Copyright © {{ copyrightYear }} My Company</p>
</footer>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
Styling
Default Footer Styling
The default footer uses these CSS classes:
css
.vp-doc-footer {
margin-top: 64px;
border-top: 1px solid var(--vp-c-divider);
padding-top: 32px;
}
.vp-doc-footer .message {
font-size: 14px;
color: var(--vp-c-text-2);
margin-bottom: 8px;
}
.vp-doc-footer .copyright {
font-size: 14px;
color: var(--vp-c-text-3);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Custom Footer Styling
Customize footer appearance:
css
/* Custom footer styles */
.vp-doc-footer {
background: var(--vp-c-bg-soft);
border-radius: 8px;
padding: 24px;
margin-top: 48px;
text-align: center;
}
.vp-doc-footer .message {
font-size: 16px;
font-weight: 500;
color: var(--vp-c-text-1);
margin-bottom: 12px;
}
.vp-doc-footer .copyright {
font-size: 14px;
color: var(--vp-c-text-2);
opacity: 0.8;
}
.vp-doc-footer a {
color: var(--vp-c-brand-1);
text-decoration: none;
font-weight: 500;
}
.vp-doc-footer a:hover {
text-decoration: underline;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Multi-language Footer
Localized Footer Content
Configure different footer content for different languages:
javascript
export default {
locales: {
root: {
themeConfig: {
footer: {
message: 'Released under the MIT License.',
copyright: 'Copyright © 2024 My Company'
}
}
},
zh: {
themeConfig: {
footer: {
message: '基于 MIT 许可发布',
copyright: '版权所有 © 2024 我的公司'
}
}
},
es: {
themeConfig: {
footer: {
message: 'Publicado bajo la Licencia MIT.',
copyright: 'Copyright © 2024 Mi Empresa'
}
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Custom Footer Component
Enhanced Footer Component
Create a custom footer with additional features:
vue
<!-- .vitepress/theme/components/CustomFooter.vue -->
<template>
<footer class="custom-footer">
<div class="footer-content">
<div class="footer-section">
<h4>Documentation</h4>
<ul>
<li><a href="/guide/">Getting Started</a></li>
<li><a href="/api/">API Reference</a></li>
<li><a href="/examples/">Examples</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Community</h4>
<ul>
<li><a href="https://github.com/username/repo">GitHub</a></li>
<li><a href="https://discord.gg/example">Discord</a></li>
<li><a href="https://twitter.com/username">Twitter</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Resources</h4>
<ul>
<li><a href="/blog/">Blog</a></li>
<li><a href="/changelog/">Changelog</a></li>
<li><a href="/roadmap/">Roadmap</a></li>
</ul>
</div>
<div class="footer-section">
<h4>Legal</h4>
<ul>
<li><a href="/privacy/">Privacy Policy</a></li>
<li><a href="/terms/">Terms of Service</a></li>
<li><a href="/license/">License</a></li>
</ul>
</div>
</div>
<div class="footer-bottom">
<div class="footer-message">
<p v-html="footerMessage"></p>
</div>
<div class="footer-copyright">
<p v-html="footerCopyright"></p>
</div>
<div class="footer-social">
<a
v-for="link in socialLinks"
:key="link.link"
:href="link.link"
:aria-label="link.ariaLabel"
target="_blank"
rel="noopener noreferrer"
>
<component :is="link.icon" />
</a>
</div>
</div>
</footer>
</template>
<script setup>
import { computed } from 'vue'
import { useData } from 'vitepress'
import GitHubIcon from './icons/GitHubIcon.vue'
import TwitterIcon from './icons/TwitterIcon.vue'
import DiscordIcon from './icons/DiscordIcon.vue'
const { theme } = useData()
const footerMessage = computed(() =>
theme.value.footer?.message || 'Released under the MIT License.'
)
const footerCopyright = computed(() =>
theme.value.footer?.copyright || `Copyright © ${new Date().getFullYear()}`
)
const socialLinks = computed(() => [
{
icon: GitHubIcon,
link: 'https://github.com/username/repo',
ariaLabel: 'GitHub'
},
{
icon: TwitterIcon,
link: 'https://twitter.com/username',
ariaLabel: 'Twitter'
},
{
icon: DiscordIcon,
link: 'https://discord.gg/example',
ariaLabel: 'Discord'
}
])
</script>
<style scoped>
.custom-footer {
margin-top: 64px;
border-top: 1px solid var(--vp-c-divider);
background: var(--vp-c-bg-soft);
}
.footer-content {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 32px;
padding: 48px 24px 32px;
max-width: 1200px;
margin: 0 auto;
}
.footer-section h4 {
margin: 0 0 16px 0;
font-size: 16px;
font-weight: 600;
color: var(--vp-c-text-1);
}
.footer-section ul {
list-style: none;
padding: 0;
margin: 0;
}
.footer-section li {
margin-bottom: 8px;
}
.footer-section a {
color: var(--vp-c-text-2);
text-decoration: none;
font-size: 14px;
transition: color 0.2s;
}
.footer-section a:hover {
color: var(--vp-c-brand-1);
}
.footer-bottom {
display: flex;
justify-content: space-between;
align-items: center;
padding: 24px;
border-top: 1px solid var(--vp-c-divider);
max-width: 1200px;
margin: 0 auto;
}
.footer-message,
.footer-copyright {
font-size: 14px;
color: var(--vp-c-text-2);
}
.footer-social {
display: flex;
gap: 16px;
}
.footer-social a {
display: flex;
align-items: center;
justify-content: center;
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--vp-c-bg-mute);
color: var(--vp-c-text-2);
transition: all 0.2s;
}
.footer-social a:hover {
background: var(--vp-c-brand-1);
color: white;
transform: translateY(-2px);
}
@media (max-width: 768px) {
.footer-content {
grid-template-columns: repeat(2, 1fr);
gap: 24px;
padding: 32px 16px 24px;
}
.footer-bottom {
flex-direction: column;
gap: 16px;
text-align: center;
padding: 24px 16px;
}
}
@media (max-width: 480px) {
.footer-content {
grid-template-columns: 1fr;
}
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
Integration with Custom Theme
javascript
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import CustomFooter from './components/CustomFooter.vue'
export default {
extends: DefaultTheme,
Layout() {
return h(DefaultTheme.Layout, null, {
'doc-footer-before': () => h(CustomFooter)
})
}
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Footer Slots
Using Footer Slots
VitePress provides slots for customizing footer content:
vue
<!-- .vitepress/theme/Layout.vue -->
<template>
<Layout>
<template #doc-footer-before>
<div class="custom-footer-content">
<p>Additional footer content before default footer</p>
</div>
</template>
</Layout>
</template>
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Available Footer Slots
doc-footer-before
- Content before the default footerdoc-after
- Content after the entire document
SEO and Footer
Structured Data in Footer
Add structured data to footer:
vue
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
// Add organization structured data
const script = document.createElement('script')
script.type = 'application/ld+json'
script.textContent = JSON.stringify({
"@context": "https://schema.org",
"@type": "Organization",
"name": "My Company",
"url": "https://example.com",
"logo": "https://example.com/logo.png",
"sameAs": [
"https://twitter.com/username",
"https://github.com/username",
"https://linkedin.com/company/username"
]
})
document.head.appendChild(script)
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Footer Links for SEO
Include important links in footer for SEO:
javascript
export default {
themeConfig: {
footer: {
message: 'Released under the <a href="/license" rel="license">MIT License</a>.',
copyright: 'Copyright © 2024 <a href="https://example.com" rel="author">My Company</a>',
links: [
{ text: 'Privacy Policy', link: '/privacy', rel: 'privacy-policy' },
{ text: 'Terms of Service', link: '/terms', rel: 'terms-of-service' },
{ text: 'Sitemap', link: '/sitemap.xml', rel: 'sitemap' }
]
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
Analytics Integration
Track Footer Interactions
Add analytics tracking to footer links:
vue
<script setup>
import { onMounted } from 'vue'
onMounted(() => {
// Track footer link clicks
document.addEventListener('click', (event) => {
const footerLink = event.target.closest('.vp-doc-footer a')
if (footerLink) {
const linkText = footerLink.textContent
const linkUrl = footerLink.href
// Google Analytics
if (typeof gtag !== 'undefined') {
gtag('event', 'footer_link_click', {
event_category: 'engagement',
event_label: linkText,
value: linkUrl
})
}
// Custom analytics
if (typeof analytics !== 'undefined') {
analytics.track('Footer Link Clicked', {
text: linkText,
url: linkUrl,
page: window.location.pathname
})
}
}
})
})
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
Accessibility
Screen Reader Support
Make footer accessible:
vue
<template>
<footer
class="vp-doc-footer"
role="contentinfo"
aria-label="Site footer"
>
<div class="footer-message">
<p>{{ message }}</p>
</div>
<div class="footer-copyright">
<p>{{ copyright }}</p>
</div>
</footer>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
Keyboard Navigation
Ensure footer links are keyboard accessible:
css
.vp-doc-footer a:focus {
outline: 2px solid var(--vp-c-brand-1);
outline-offset: 2px;
border-radius: 2px;
}
.vp-doc-footer a:focus:not(:focus-visible) {
outline: none;
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
Performance Optimization
Lazy Load Footer Content
Lazy load footer content for better performance:
vue
<script setup>
import { ref, onMounted } from 'vue'
const footerVisible = ref(false)
onMounted(() => {
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
footerVisible.value = true
observer.unobserve(entry.target)
}
})
},
{ threshold: 0.1 }
)
const footerElement = document.querySelector('.vp-doc-footer')
if (footerElement) {
observer.observe(footerElement)
}
})
</script>
<template>
<footer v-if="footerVisible" class="vp-doc-footer">
<!-- Footer content -->
</footer>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Best Practices
Content Guidelines
- Keep it concise - Footer should be informative but not overwhelming
- Include essential links - Privacy policy, terms, contact information
- Update copyright year - Use dynamic year calculation
- Use proper HTML - Semantic markup for better accessibility
Design Guidelines
- Consistent styling - Match the overall site design
- Responsive design - Work well on all screen sizes
- Clear hierarchy - Organize information logically
- Sufficient contrast - Ensure text is readable
Performance Guidelines
- Minimize content - Avoid heavy images or scripts in footer
- Optimize images - Use appropriate formats and sizes
- Lazy loading - Load footer content when needed
- Cache effectively - Use appropriate caching strategies
SEO Guidelines
- Include important links - Help search engines discover content
- Use proper markup - Semantic HTML for better understanding
- Structured data - Add organization information
- Internal linking - Link to important site pages
Examples
Minimal Footer
javascript
export default {
themeConfig: {
footer: {
message: 'MIT Licensed',
copyright: '© 2024 My Company'
}
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Comprehensive Footer
javascript
export default {
themeConfig: {
footer: {
message: 'Released under the <a href="/license">MIT License</a>. Documentation built with <a href="https://vitepress.dev">VitePress</a>.',
copyright: 'Copyright © 2024-present <a href="https://example.com">My Company</a>. All rights reserved.'
}
}
}
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
Multi-section Footer
vue
<template>
<footer class="comprehensive-footer">
<div class="footer-main">
<div class="footer-brand">
<img src="/logo.svg" alt="Company Logo" />
<p>Building the future of documentation</p>
</div>
<div class="footer-links">
<div class="link-group">
<h4>Product</h4>
<a href="/features">Features</a>
<a href="/pricing">Pricing</a>
<a href="/enterprise">Enterprise</a>
</div>
<div class="link-group">
<h4>Resources</h4>
<a href="/docs">Documentation</a>
<a href="/blog">Blog</a>
<a href="/help">Help Center</a>
</div>
<div class="link-group">
<h4>Company</h4>
<a href="/about">About</a>
<a href="/careers">Careers</a>
<a href="/contact">Contact</a>
</div>
</div>
</div>
<div class="footer-bottom">
<p>{{ footerMessage }}</p>
<p>{{ footerCopyright }}</p>
</div>
</footer>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38