前言
所有修改都采用 Hugo 的主题覆盖机制,不直接修改主题文件,确保主题可以随时更新而不影响自定义内容。
基础知识:理解 Hugo 主题覆盖机制
Hugo 的文件查找顺序
Hugo 在查找模板和资源文件时,会按以下顺序查找:
1. 项目根目录/layouts/ (最高优先级)
2. 项目根目录/themes/主题名/layouts/
3. 项目根目录/assets/ (最高优先级)
4. 项目根目录/themes/主题名/assets/
原理:只需在项目根目录创建与主题相同路径的文件,就可以覆盖主题的默认文件。
使用 Git 子模块管理主题
添加主题子模块:
git submodule add https://github.com/CaiJimmy/hugo-theme-stack themes/hugo-theme-stack
优势:
- 主题和自定义修改完全分离
- 可以随时更新主题:
git submodule update --remote - 版本控制清晰
全局样式定制方法
创建自定义样式文件
步骤 1:在项目根目录创建 assets/scss/custom.scss 文件
// assets/scss/custom.scss
// 这个文件会被 Hugo 自动编译并添加到页面中
步骤 2:确保 Hugo 配置中启用了自定义样式
主题会自动查找并加载 assets/scss/custom.scss,无需额外配置。
使用 CSS 变量统一管理样式
方法:在 :root 中定义全局变量
:root {
// 间距和尺寸
--main-top-padding: 30px;
--card-border-radius: 10px;
--tag-border-radius: 8px;
--section-separation: 40px;
// 字体大小
--article-font-size: 1.8rem;
// 颜色定义
--other-color: #e99312; // 主题强调色
--code-background-color: #f8f8f8; // 代码背景色
--code-text-color: var(--other-color); // 代码文字颜色
}
为什么使用 CSS 变量?
- 统一管理样式,修改一处即可全局生效
- 支持暗色模式切换
- 便于维护和调试
实现暗色模式适配
方法:在 :root 中添加暗色模式条件
:root {
// 浅色模式样式
--code-background-color: #f8f8f8;
--code-text-color: var(--other-color);
// 暗色模式样式
&[data-scheme="dark"] {
--code-background-color: #ff6d1b17;
--code-text-color: var(--other-color);
}
}
修改文字选中效果
需求:让选中的文字有更明显的视觉反馈
::selection {
color: #fff; // 选中文字颜色
background: #34495e; // 选中背景色
}
提示:可以使用主题色或品牌色,增强品牌识别度。
优化链接和代码的换行
问题:在移动端,长链接和代码会导致页面横向滚动
解决方法:
// 修复引用块和代码在窄屏幕显示问题
a {
word-break: break-all; // 允许在任意字符间断行
}
code {
word-break: break-all;
}
注意:break-all 可能会在不理想的位置断行,如果需要更智能的断行,可以使用 word-wrap: break-word。
定制文章列表封面高度
需求:让封面图高度在不同屏幕尺寸下都有合适的显示
方法:使用响应式断点
.article-list article .article-image img {
width: 100%;
height: 200px !important; // 移动端
object-fit: cover; // 裁剪图片以填充区域
@include respond(md) { // 平板
height: 250px !important;
}
@include respond(xl) { // 桌面
height: 285px !important;
}
}
Stack 主题的响应式断点:
sm: < 768pxmd: ≥ 768pxlg: ≥ 1024pxxl: ≥ 1280px
为文章内图片添加圆角和自适应
方法:
.article-page .main-article .article-content {
img {
max-width: 96% !important; // 略小于容器,留出边距
height: auto !important; // 自动高度保持比例
border-radius: 8px; // 圆角
}
}
美化引用块样式
方法:
.article-content {
blockquote {
border-radius: 10px; // 整体圆角
margin-left: -8px; // 轻微左移
max-width: 102%; // 略超出容器
// 左侧彩色边框
border-inline-start: var(--blockquote-border-size) solid var(--accent-color);
}
}
美化全局滚动条
方法一:隐藏滚动条(如菜单)
.menu::-webkit-scrollbar {
display: none;
}
方法二:定制滚动条样式
html {
::-webkit-scrollbar {
width: 20px; // 滚动条宽度
}
::-webkit-scrollbar-track {
background-color: transparent; // 轨道透明
}
::-webkit-scrollbar-thumb {
background-color: #d6dee1; // 滑块颜色
border-radius: 20px; // 圆角滑块
border: 6px solid transparent; // 内边距效果
background-clip: content-box; // 背景裁剪
}
::-webkit-scrollbar-thumb:hover {
background-color: #a8bbbf; // 悬停时加深
}
}
代码块工具栏功能增强
需求分析
目标:为每个代码块添加工具栏,显示编程语言并提供一键复制功能。
效果预览:
┌─────────────────────────────────┐
│ JAVASCRIPT ✂ Copy │ ← 工具栏
├─────────────────────────────────┤
│ console.log('Hello World') │ ← 代码
└─────────────────────────────────┘
添加工具栏样式
步骤 1:覆盖主题的文章样式文件
在项目根目录创建 assets/scss/partials/layout/article.scss
步骤 2:添加工具栏样式
.article-content {
.highlight {
max-width: 102% !important;
padding: 0px;
position: relative;
border-radius: 8px;
margin-left: -8px !important;
margin-right: -2px;
box-shadow: var(--shadow-l1) !important;
// 工具栏样式
.toolbar {
position: relative;
width: 100%;
height: 30px;
background-color: var(--scrollbar-thumb); // 使用主题变量
z-index: 10;
display: flex;
justify-content: space-between; // 两端对齐
align-items: center;
padding: 6px 16px;
border-top-left-radius: 8px;
border-top-right-radius: 8px; // 只有顶部圆角
// 语言标签按钮
.languageTagButton {
background: none;
border: none;
font-size: 12px;
font-family: var(--code-font-family);
color: var(--code-button-color);
cursor: default; // 不可点击
}
// 复制按钮
.copyCodeButton {
background: none;
border: none;
color: var(--code-button-color);
font-size: 12px;
cursor: pointer; // 可点击
}
}
// 代码区域样式
pre {
margin: initial;
padding: 15px 25px;
margin: 0;
width: auto;
border-radius: 0 0 8px 8px; // 只有底部圆角
}
}
}
实现 JavaScript 功能
步骤 1:覆盖主题的 JavaScript 文件
在项目根目录创建 assets/ts/main.ts
步骤 2:复制主题原有的 main.ts 内容
首先从 themes/hugo-theme-stack/assets/ts/main.ts 复制所有代码。
步骤 3:在初始化函数中添加代码块增强功能
在 Stack.init() 函数中添加:
/**
* 为代码块添加复制按钮和语言标签
*/
const highlights = document.querySelectorAll('.article-content div.highlight');
const copyText = '✂ Copy';
const copiedText = '✔ Copied';
highlights.forEach(highlight => {
const codeBlock = highlight.querySelector('code[data-lang]');
if (!codeBlock) return;
// 获取并处理语言标签
const rawLang = codeBlock.getAttribute('data-lang');
const lang = (rawLang === "fallback" || !rawLang) ? "TEXT" : rawLang.toUpperCase();
// 创建语言标签
const langTag = createButton(lang, 'languageTagButton');
// 创建复制按钮
const copyButton = createButton(copyText, 'copyCodeButton');
// 创建工具栏容器
const toolbar = document.createElement('div');
toolbar.classList.add('toolbar');
toolbar.appendChild(langTag);
toolbar.appendChild(copyButton);
// 将工具栏插入到代码块前面
highlight.insertBefore(toolbar, highlight.firstChild);
// 绑定复制功能
copyButton.addEventListener('click', () => {
navigator.clipboard.writeText(codeBlock.textContent)
.then(() => {
copyButton.textContent = copiedText;
// 1秒后恢复按钮文字
setTimeout(() => {
copyButton.textContent = copyText;
}, 1000);
})
.catch(err => {
alert(err);
console.error('Copy failed:', err);
});
});
});
// 辅助函数:创建按钮
function createButton(text, className) {
const button = document.createElement('button');
button.innerHTML = text;
button.classList.add(className);
return button;
}
代码解析:
- 选择所有代码块:
querySelectorAll('.article-content div.highlight') - 获取语言信息:从
data-lang属性读取,Hugo 会自动添加 - 处理特殊情况:如果语言为
fallback或空,显示为TEXT - 使用 Clipboard API:
navigator.clipboard.writeText()实现复制 - 用户反馈:复制成功后改变按钮文字 1 秒
兼容性:Clipboard API 需要 HTTPS 或 localhost 环境。
页添加欢迎横幅动画
创建动画效果
步骤 1:在 custom.scss 中定义动画
动画一:握手摇摆动画
.shake {
display: inline-block;
animation: shake 1s;
animation-delay: 2s; // 延迟2秒开始
}
@keyframes shake {
0% {
transform: rotate(0);
}
25% {
transform: rotate(45deg) scale(1.2);
}
50% {
transform: rotate(0) scale(1.2);
}
75% {
transform: rotate(45deg) scale(1.2);
}
100% {
transform: rotate(0);
}
}
动画二:文字跳跃动画
// 基础跳跃动画
@keyframes jump {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-20px); // 向上跳20px
}
100% {
transform: translateY(0);
}
}
// 创建9个不同延迟的类
.jump-text1 {
display: inline-block;
animation: jump .5s 1;
animation-delay: 0s;
}
.jump-text2 {
display: inline-block;
animation: jump .5s 1;
animation-delay: .1s; // 递增延迟
}
// ... 依此类推到 .jump-text9 (延迟0.9s)
动画三:欢迎卡片样式
.welcome {
color: var(--card-text-color-main);
background: var(--card-background);
box-shadow: var(--shadow-l2);
border-radius: var(--card-border-radius);
display: inline-block;
}
修改首页模板
步骤 1:覆盖首页模板
在项目根目录创建 layouts/index.html
步骤 2:复制主题原有代码
从 themes/hugo-theme-stack/layouts/index.html 复制所有代码。
步骤 3:在文章列表前添加欢迎横幅
{{ define "main" }}
{{ $pages := where .Site.RegularPages "Type" "in" .Site.Params.mainSections }}
{{ $notHidden := where .Site.RegularPages "Params.hidden" "!=" true }}
{{ $filtered := ($pages | intersect $notHidden) }}
{{ $pag := .Paginate ($filtered) }}
<!-- 首页欢迎横幅 -->
<div class="welcome">
<p style="font-size: 2rem; text-align: center; font-weight: bold">
<span class="shake">👋</span>
<span class="jump-text1">Welcome</span>
<span class="jump-text2"> To </span>
<span class="jump-text3" style="color:#e99312">K</span>
<span class="jump-text4" style="color:#e99312">e</span>
<span class="jump-text5" style="color:#e99312">y</span>
<span class="jump-text6" style="color:#e99312">e</span>
<span class="jump-text7" style="color:#e99312">'</span>
<span class="jump-text8" style="color:#e99312">s </span>
<span class="jump-text9" style="color:#e99312">Blog</span>
</p>
</div>
<!-- 首页欢迎横幅 -->
<section class="article-list">
{{ range $index, $element := $pag.Pages }}
{{ partial "article-list/default" . }}
{{ end }}
</section>
{{- partial "pagination.html" . -}}
{{- partial "footer/footer" . -}}
{{ end }}
Waline 评论系统优化
// Waline 主题颜色变量
:root {
--waline-theme-color: var(--accent-color) !important;
--waline-active-color: var(--other-color) !important;
--waline-color: var(--card-text-color-secondary) !important;
}
// 移除评论面板外边距,实现无背景效果
.wl-panel {
margin: 0px !important;
}
响应式布局优化
调整页面三栏布局宽度
需求:在不同屏幕尺寸下优化左侧边栏、主内容区、右侧边栏的宽度比例。
方法:在 custom.scss 中覆盖布局样式
.container {
margin-left: auto;
margin-right: auto;
.left-sidebar {
order: -3;
max-width: var(--left-sidebar-max-width);
}
.right-sidebar {
order: -1;
max-width: var(--right-sidebar-max-width);
@include respond(lg) {
display: flex;
}
}
// 扩展布局(三栏)
&.extended {
@include respond(md) {
max-width: 1024px;
--left-sidebar-max-width: 25%;
--right-sidebar-max-width: 22% !important;
}
@include respond(lg) {
max-width: 1280px;
--left-sidebar-max-width: 20%;
--right-sidebar-max-width: 30%;
}
@include respond(xl) {
max-width: 1453px; // 自定义最大宽度
--left-sidebar-max-width: 15%;
--right-sidebar-max-width: 25%;
}
}
// 紧凑布局(两栏)
&.compact {
@include respond(md) {
--left-sidebar-max-width: 25%;
max-width: 768px;
}
@include respond(lg) {
max-width: 1024px;
--left-sidebar-max-width: 20%;
}
@include respond(xl) {
max-width: 1280px;
}
}
}
实现归档页面双栏布局
需求:在大屏幕上,归档页面使用网格布局显示为两栏。
方法:
@media (min-width: 1024px) {
.article-list--compact {
display: grid;
grid-template-columns: 1fr 1fr; // 两等宽列
background: none;
box-shadow: none;
gap: 1rem; // 列间距
article {
background: var(--card-background);
border: none;
box-shadow: var(--shadow-l2);
margin-bottom: 8px;
border-radius: 16px;
}
}
}
实现链接页面三栏布局
需求:友情链接页面在大屏幕上显示为三栏。
方法:
@media (min-width: 1024px) {
.article-list--compact.links { // 注意 .links 类名
display: grid;
grid-template-columns: 1fr 1fr 1fr; // 三等宽列
background: none;
box-shadow: none;
gap: 1rem;
article {
background: var(--card-background);
border: none;
box-shadow: var(--shadow-l2);
margin-bottom: 8px;
border-radius: var(--card-border-radius);
&:nth-child(odd) {
margin-right: 8px;
}
}
}
}
使用方法:
在友情链接页面的 Markdown 前言中添加:
---
title: "友情链接"
links: true # 启用 links 布局
layout: "archives" # 使用归档布局
---
优化移动端间距
方法:
.main-container {
min-height: 100vh;
align-items: flex-start;
padding: 0 15px; // 移动端较小边距
gap: var(--section-separation);
padding-top: var(--main-top-padding);
@include respond(md) {
padding: 0 37px; // 平板和桌面较大边距
}
}
维护和更新
更新主题
步骤 1:进入主题子模块目录
cd themes/hugo-theme-stack
步骤 2:拉取最新代码
git pull origin master
步骤 3:返回项目根目录并提交更新
cd ../..
git add themes/hugo-theme-stack
git commit -m "Update hugo-theme-stack theme"
注意事项:
- 更新前先备份自定义文件
- 查看主题的 CHANGELOG,了解重大变更
- 更新后测试网站功能是否正常
常见问题排查
问题 1:自定义样式不生效
# 清除 Hugo 缓存
hugo mod clean
# 重新构建
hugo server --disableFastRender
问题 2:图标不显示
检查:
- 文件路径是否正确(
assets/icons/图标名.svg) - SVG 文件是否有效
- 配置中的图标名是否与文件名匹配(不含
.svg后缀)
问题 3:代码块复制功能失效
检查:
- 是否使用 HTTPS 或 localhost(Clipboard API 要求)
- 浏览器控制台是否有 JavaScript 错误
main.ts是否正确编译
问题 4:评论系统不加载
检查:
- Waline 服务端是否正常运行
serverURL配置是否正确- 浏览器控制台是否有网络错误
- CDN 地址是否可访问
性能优化建议
1. 图片优化
# 使用 WebP 格式
# 使用图片压缩工具(TinyPNG、ImageOptim)
# 合理设置图片尺寸
2. CDN 配置
在 hugo.yaml 中配置 CDN:
params:
cdn:
# 使用七牛云、又拍云等 CDN 加速静态资源
3. 启用缓存
caches:
getjson:
maxAge: 24h
getcsv:
maxAge: 24h
images:
maxAge: 720h
版本控制最佳实践
提交信息规范:
# 功能添加
git commit -m "feat: add welcome banner animation"
# 样式修改
git commit -m "style: adjust article image border radius"
# 修复问题
git commit -m "fix: code copy button not working on mobile"
# 文档更新
git commit -m "docs: update theme modification guide"
分支管理:
# 开发新功能使用分支
git checkout -b feature/new-layout
# 测试通过后合并
git checkout main
git merge feature/new-layout
附录:快速参考
常用 CSS 变量
--card-background // 卡片背景色
--card-text-color-main // 主要文字颜色
--card-text-color-secondary // 次要文字颜色
--card-text-color-tertiary // 三级文字颜色
--accent-color // 主题强调色
--accent-color-darker // 深色强调色
--card-border-radius // 卡片圆角
--shadow-l1, --shadow-l2 // 阴影效果
--card-padding // 卡片内边距
响应式混入
@include respond(sm) { /* < 768px */ }
@include respond(md) { /* ≥ 768px */ }
@include respond(lg) { /* ≥ 1024px */ }
@include respond(xl) { /* ≥ 1280px */ }
常用 Hugo 模板函数
{{ .Title }} // 标题
{{ .Content }} // 内容
{{ .Params.custom }} // 自定义参数
{{ with .Site.Params.foo }} // 条件判断
{{ range .Pages }} // 循环页面
{{ partial "name" . }} // 引入局部模板
祝你打造出独特的个人博客!
