Hugo Stack 主题美化

全局配置

页面基本配色

  • /assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ---------------页面基本配色---------------
:root {
// 全局顶部边距
--main-top-padding: 30px;
// 全局卡片圆角
--card-border-radius: 25px;
// 标签云卡片圆角
--tag-border-radius: 8px;
// 卡片间距
--section-separation: 40px;
// 全局字体大小
--article-font-size: 1.8rem;
// 行内代码背景色
--code-background-color: #f8f8f8;
// 行内代码前景色
--code-text-color: #e96900;
// 暗色模式下样式
&[data-scheme="dark"] {
// 行内代码背景色
--code-background-color: #ff6d1b17;
// 行内代码前景色
--code-text-color: #e96900;
}
}

全局布局调整

  • ./assets/scss/custom.scss 中加入以下代码:
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
//---------------------------------------------------
// 全局页面布局间距调整
.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;
}
}

//--------------------------------------------------
//页面三栏宽度调整
.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);

/// Display right sidebar when min-width: lg
@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; //1536px;
--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;
}
}
}

//-------------------------------------------------------
//全局页面小图片样式微调
.article-list--compact article .article-image img {
width: var(--image-size);
height: var(--image-size);
object-fit: cover;
border-radius: 17%;
}

// --------------------------------
// 下拉菜单改圆角样式
.menu {
padding-left: 0;
list-style: none;
flex-direction: column;
overflow-x: hidden;
// overflow-y: scroll;
flex-grow: 1;
font-size: 1.6rem;
background-color: var(--card-background);

// box-shadow: var(--shadow-l2); // 手机端下拉菜单会有莫名小方块
box-shadow: none;
display: none;
margin: 0; //改为0
border-radius: 10px; //加个圆角
padding: 30px 30px;

@include respond(xl) {
padding: 15px 0;
}

&,
.menu-bottom-section {
gap: 30px;

@include respond(xl) {
gap: 25px;
}
}

&.show {
display: flex;
}

@include respond(md) {
align-items: flex-end;
display: flex;
background-color: transparent;
padding: 0;
box-shadow: none;
margin: 0;
}

li {
position: relative;
vertical-align: middle;
padding: 0;

@include respond(md) {
width: 100%;
}

svg {
stroke-width: 1.33;

width: 20px;
height: 20px;
}

a {
height: 100%;
display: inline-flex;
align-items: center;
color: var(--body-text-color);
gap: var(--menu-icon-separation);
}

span {
flex: 1;
}

&.current {
a {
color: var(--accent-color);
font-weight: bold;
}
}
}
}

/*手机模式下的菜单滚动条美化*/
.menu::-webkit-scrollbar {
display: none; //防止大屏幕时出现滚动条
}

.sidebar header .site-name {
margin: 8px;
font-size: 2rem; //字体大小
}

文章内容美化

文章内容基本美化

  • ./assets/scss/custom.scss 中加入以下代码:
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
//------------------------------------------------
// 文章内容引用块样式
.article-content {
blockquote {
border-left: 6px solid #358b9a1f !important;
background: #3a97431f;
}
}

// ---------------------------------------
// 代码块基础样式修改
.highlight {
max-width: 102% !important;
background-color: var(--pre-background-color);
padding: var(--card-padding);
position: relative;
border-radius: 20px;
margin-left: -7px !important;
margin-right: -12px;
box-shadow: var(--shadow-l1) !important;

&:hover {
.copyCodeButton {
opacity: 1;
}
}

// keep Codeblocks LTR
[dir="rtl"] & {
direction: ltr;
}

pre {
margin: initial;
padding: 0;
margin: 0;
width: auto;
}
}

//----------------------------------------------
// light模式下的代码块样式调整
[data-scheme="light"] .article-content .highlight {
background-color: #fff9f3;
}

[data-scheme="light"] .chroma {
color: #ff6f00;
background-color: #fff9f3cc;
}

//---------------------------------------------------
// 文章内容图片圆角阴影
.article-page .main-article .article-content {
img {
max-width: 96% !important;
height: auto !important;
border-radius: 8px;
}
}

//-------------------------------------------
// 设置选中字体的区域背景颜色
::selection {
color: #fff;
background: #001572;
}

a {
text-decoration: none;
color: var(--accent-color);

&:hover {
color: var(--accent-color-darker);
}

.link {
font-weight: 800; /* 字体粗细为700(加粗) */
padding: 0 2px; /* 内边距为左右各2px */
text-decoration: none; /* 取消默认的下划线 */
cursor: pointer; /* 鼠标指针为指针样式 */

/* 超链接默认颜色(明亮模式) */
color: #000000; /* 明亮模式下链接字体为黑色#000000 */

&:hover {
text-decoration: underline;
}
}

@media (prefers-color-scheme: dark) {
.link {
/* 超链接默认颜色(暗色模式) */
color: #FFFFFF; /* 暗色模式下链接字体为白色#FFFFFF */
}
}
}

//-------------------------------------------------
//文章封面高度更改
.article-list article .article-image img {
width: 100%;
height: 150px; // 设置图片的高度为 150px
object-fit: cover;

@include respond(md) {
height: 200px;
}

@include respond(xl) {
height: 305px;
}
}

//------------------------------------------------------
// 修复引用块内容窄页面显示问题
a {
word-break: break-all;
}

code {
word-break: break-all;
}

MD 引用块样式

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 文章内容引用块样式
.article-content {
blockquote {
border-left: 6px solid #004b28 !important;
background: #366e33;
}
}
```

### 使图床链接的图片居中
* 目前 Stack 默认只支持本地引用的图片居中,而在使用 url 图片链接时没有居中格式。在 `./assets/scss/partials/layout/article.scss` Line 256 处(同级任意位置)增加以下代码:

```scss
// 图床链接的图片居中
p > img {
display: block;
margin: 0 auto;
max-width: 100%;
height: auto;
}

统计站点文章数量和字数

  • ./layout/partials/footer/footer.html<section class="powerby"> 里边,加入代码:
1
2
3
4
5
6
7
{{ $articleCount := len .Site.RegularPages }}
{{ $totalWordCount := 0 }}
{{ range .Site.Pages }}
{{ $totalWordCount = add $totalWordCount .WordCount }}
{{ end }}

<p>发布了 {{ $articleCount }} 篇文章 | 共 {{$totalWordCount}} 字</p>

首页文章样式

  • ./assets/scss/custom.scss 加入代码:
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
/*主页文章图片样式*/
$image-scale: 1.2;
.article-list article .article-image img {
width: 100%;
height: 150px;
object-fit: cover;
//不同显示器(手机,小屏幕电脑,大屏幕电脑)显示的图片高度大小
@include respond(sm) {
height: 305px;
}

@include respond(md) {
height: 305px;
}
@include respond(xl) {
height: 325px;
}
}

/*主页文章图片圆角*/
.article-list article {
--card-border-radius: 24px;
}

/*文章标签圆角*/
.article-category a, .article-tags a {
border-radius: 11px;
}

/*鼠标移动到文章图片放大*/
.article-list article .article-image {
position: relative;
overflow: hidden; //不显示超出的部分
}

.article-list article .article-image img:hover {
transform: scale($image-scale); //放大尺寸
}

.article-list article .article-image img {
transition: transform 0.85s ease-in-out;//持续时间
}

文章内部图片样式

  • ./assets/scss/custom.scss 加入代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*文章内部-页脚-相关文章图片圆角*/
.article-list--compact article .article-image img {
border-radius: 17%;
}

/*文章内部-页脚-相关文章图片放大动画*/
.article-list--compact article > a {
transition: .6s ease;
}

.article-list--compact article > a:hover {
transform: scale(1.03, 1.03);
overflow: visible;
}

MacOS 风格代码块

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// MacOS 风格代码块
.article-content {
.highlight:before {
content: '';
display: block;
background: url(/code-header.svg);
height: 32px;
width: 100%;
background-size: 57px;
background-repeat: no-repeat;
margin-bottom: 5px;
background-position: -1px 2px;
}
}

// light模式下的代码块样式调整
[data-scheme="light"] .article-content .highlight {
background-color: #fdf4eb;
}

[data-scheme="light"] .chroma {
color: #ff6f00;
background-color: #fcf0e4cc;
}
  • ./static 文件夹下新建 code-header.svg写入以下代码:
1
2
3
4
5
6
// macOS 红绿灯图标
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="470px" height="130px">
<ellipse cx="65" cy="65" rx="50" ry="52" stroke="rgb(220,60,54)" stroke-width="2" fill="rgb(237,108,96)"/>
<ellipse cx="225" cy="65" rx="50" ry="52" stroke="rgb(218,151,33)" stroke-width="2" fill="rgb(247,193,81)"/>
<ellipse cx="385" cy="65" rx="50" ry="52" stroke="rgb(27,161,37)" stroke-width="2" fill="rgb(100,200,86)"/>
</svg>

修改代码块样式

  • 修改 .\assets\scss\partials\layout\article.scss,在文件尾添加:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// --------------------代码块样式------------------------
// * 修改边距
// * 背景框添加圆角
// * 调整 copy 按钮位置
.highlight {
margin-left: 0;
margin-right: 0;
width: calc(100%);
border-radius: var(--card-border-radius);
}

.copyCodeButton {
top: 6px;
right: 6px;
}

代码块高亮

  • hugo.yaml 中,添加 highlight 参数,我文章里的代码块配置是这样子的:
1
2
3
4
5
6
7
8
9
10
markup:
highlight:
noClasses: false
codeFences: true
guessSyntax: true
lineNoStart: 1
lineNos: true
lineNumbersInTable: true
tabWidth: 4
style: github-dark

关闭代码块语言显示

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
// 关闭代码块语言显示
.languageCodeButton {
display: none;
}

外部链接后面显示图标

  • 创建./layouts/_default/_markup/render-link.html文件之后增加如下代码:
1
2
3
4
5
6
7
8
9
10
11
<a class="link" href="{{ .Destination | safeURL }}" {{ with .Title }} title="{{ . }}" {{ end }} {{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener" {{ end }}>
<span style="display: inline-flex; align-items: center; gap: 0.5em;">
{{ .Text | safeHTML }}
{{ if strings.HasPrefix .Destination "http" }}
<svg width=".7em" height=".7em" viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg">
<path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" />
<path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z" fill="currentColor" />
</svg>
{{ end }}
</span>
</a>
  • 或者,创建./layouts/_default/_markup/render-link.html文件之后增加如下代码:
1
2
3
4
5
6
7
8
9
10
11
<a class="link" href="{{ .Destination | safeURL }}" {{ with .Title }} title="{{ . }}" {{ end }} {{ if strings.HasPrefix .Destination "http" }} target="_blank" rel="noopener" {{ end }}>
<span style="display: inline-flex; align-items: center; gap: 0.5em;">
<span>{{ .Text | safeHTML }}</span>
{{ if strings.HasPrefix .Destination "http" }}
<svg width=".7em" height=".7em" viewBox="0 0 21 21" xmlns="http://www.w3.org/2000/svg">
<path d="m13 3l3.293 3.293l-7 7l1.414 1.414l7-7L21 11V3z" fill="currentColor" />
<path d="M19 19H5V5h7l-2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2v-5l-2-2v7z" fill="currentColor" />
</svg>
{{ end }}
</span>
</a>

语言和复制按钮

  • 原本的复制按钮要指针移动到代码块上才出现的,把它固定在右上角,并显示代码的语言种类。
  • ./assets/ts/main.ts 中,第 66 行开始,改成以下代码
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
const highlights = document.querySelectorAll(".article-content div.highlight");
const copyText = `📄拷贝`,
copiedText = `已拷贝!`;

highlights.forEach((highlight) => {
const copyButton = document.createElement("button");
copyButton.innerHTML = copyText;
copyButton.classList.add("copyCodeButton");
highlight.appendChild(copyButton);

const codeBlock = highlight.querySelector("code[data-lang]");
// 获取语言
const lang = codeBlock.getAttribute("data-lang");
if (!codeBlock) return;

copyButton.addEventListener("click", () => {
navigator.clipboard
.writeText(codeBlock.textContent)
.then(() => {
copyButton.textContent = copiedText;

setTimeout(() => {
copyButton.textContent = copyText;
}, 1000);
})
.catch((err) => {
alert(err);
console.log("Something went wrong", err);
});
});

// Add language code button
const languageButton = document.createElement("button");
languageButton.innerHTML = lang.toUpperCase() + "&nbsp;&nbsp;";
languageButton.classList.add("languageCodeButton");

highlight.appendChild(languageButton);
});

new StackColorScheme(document.getElementById("dark-mode-toggle"));
  • ./assets/scss/custom.scss 中加入以下代码调整按钮位置(需要自己调整以下距离,因为每个人的大小不一样)
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
/* 复制按钮样式调整 */
.article-content .copyCodeButton {
position: absolute;
top: 10px;
right: 18px;
border-radius: 12px;
color: #ffffff;
background: #3d3c3c;
border: 1px solid #333;
padding: 5px 10px;
font-weight: 500;
text-shadow: 0 0 1px rgba(255, 255, 255, 0.5);
}

/* 注释语言代码框 */
/*
.article-content .languageCodeButton {
position: absolute;
top: 9px;
right: 100px;
border-radius: 12px;
color: #000;
background: #ffff00;
border: 1px solid #333;
padding: 5px 10px;
font-family: lato;
font-size: 1.5rem;
text-shadow: 0 0 1px rgba(255, 255, 255, 0.5);
}
*/

.article-content .copyCodeButton:hover {
background: #ffa500;
border-color: #000;
}

侧边栏美化

页面左右边栏宽度

  • /themes/hugo-theme-stack/assets/scss/grid.scss 的第 29、30 行,修改为:
1
2
--left-sidebar-max-width: 14%;
--right-sidebar-max-width: 22%;

右侧导航栏动画

  • ./assets/scss/custom.scss 中加入以下代码:
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
// //----------搜索文章后跳转文章会刷新页面所以弃用------------------
// /*------------------右侧导航栏动画--------------*/
// // 搜索菜单动画
// .search-form.widget {
// transition: transform 0.6s ease;
// }

// .search-form.widget:hover {
// transform: scale(1.1, 1.1);
// }

//------------------------------------------------------
//归档小图标放大动画
.widget.archives .widget-archive--list {
transition: transform .3s ease;
}

.widget.archives .widget-archive--list:hover {
transform: scale(1.05, 1.05);
}

//------------------------------------------------------
//右侧标签放大动画
.tagCloud .tagCloud-tags a {
border-radius: 10px;
font-size: 1.4rem;
transition: transform .3s ease;
}

.tagCloud .tagCloud-tags a:hover {
transform: scale(1.1, 1.1);
}

左侧导航栏美化

  • ./assets/scss/custom.scss 加入代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*--------------------左侧导航栏---------------*/
.left-sidebar {
--sidebar-avatar-size: 115px; //左侧头像大小
--sidebar-element-separation: 15px; //头像下方间距
--emoji-size: 40px; //emoji容器大小
--emoji-font-size: 25px; //emoji字体大小
}

/*社交菜单居中*/
.social-menu svg {
gap: 15px;
justify-content: center;
width: 30px;
height: 30px; //社交菜单大小
stroke: var(--body-text-color);
stroke-width: 1.33;
}

左侧导航栏动画

  • ./assets/scss/custom.scss 中加入以下代码:
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
//------------------------------------------------------
/* 左侧栏选项动画 */
#main-menu {
overflow: visible;
li {
a {
-webkit-font-smoothing: antialiased;
will-change: transform;
transition: transform 0.6s ease;
&:hover {
transform: scale(1.1, 1.1);
will-change: transform;
}
}
}
}

/* 归档和链接卡片动画 */
.article-list--compact {
overflow: visible;
}

.article-list--compact article {
transition: transform 0.6s ease;
-webkit-font-smoothing: antialiased;
will-change: transform;

&:hover {
transform: scale(1.05,1.05);
z-index: 4;
}
}

/* 分类页面动画 */
.article-list--tile article {
transition: 0.6s ease;
}

.article-list--tile article:hover {
transform: scale(1.05, 1.05);
will-change: transform;
}

社交 social

  • 自定义图标,iconfont 下载,颜色 #2c3e50,大小 24,格式 svg。下载后放到 .\assets\icons
  • 本主题自带了一些来自【Tabler Icons】的 SVG 图标。您可以在主题文件夹下找到它们 .\assets\icons
  • 注意:将下载的 img 中的 svg 的所有 #2c3e50 改成 currentColor,否则切换为黑色模式,图标颜色不能自动切换,因为优先使用内部定义的 color
  • 修改 hugo 主配置文件,修改下面的内容:
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
menu:
main: [] # 主菜单

social:
- identifier: bilibili # 标识符
name: Bilibili # 显示名称
url: https://space.bilibili.com/35158479 # 链接地址
weight: 100 # 项目的优先级,值越低,优先级越高。
params:
icon: brand-bilibili # 图标名称
newTab: true # 新标签页中打开此链接

- identifier: github # 标识符
name: GitHub # 显示名称
url: https://github.com/meimolihan # 链接地址
weight: 200 # 项目的优先级,值越低,优先级越高。
params:
icon: brand-github # 图标名称
newTab: true # 新标签页中打开此链接

- identifier: rss # 标识符
name: RSS # 显示名称
url: https://meimolihan.github.io/index.xml # 链接地址
weight: 300 # 项目的优先级,值越低,优先级越高。
params:
icon: brand-rss # 图标名称
newTab: true # 新标签页中打开此链接
  • 图标360度旋转动画.\assets\scss\custom.scss追加以下代码:
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
.icon-tabler-brand-bilibili {
transition: transform 1s ease-in-out;
}

/* 鼠标悬停时让 SVG 图标旋转 360 度 */
.icon-tabler-brand-bilibili:hover {
transform: rotate(360deg);
}

.icon-tabler-brand-github {
transition: transform 1s ease-in-out;
}

/* 鼠标悬停时让 SVG 图标旋转 360 度 */
.icon-tabler-brand-github:hover {
transform: rotate(360deg);

.icon-tabler-rss {
transition: transform 1s ease-in-out;
}

/* 鼠标悬停时让 SVG 图标旋转 360 度 */
.icon-tabler-rss:hover {
transform: rotate(360deg);
}

明亮模式,调整位置

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
// 明暗模式切换按钮,调整位置
#dark-mode-toggle {
margin-bottom: 100px; // 明暗模式,上下高度
// margin-left: 10px; // 明暗模式,左右调节
gap: 30px; // 明暗模式,横向宽度
}

手动修改左右侧边栏设置样式

  • /assets/scss/grid.scss 中修改 left-sidebarright-sidebar 的描述:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 为左右侧边栏设置样式,将左侧边栏的排列顺序设为 -3 并将最大宽度设为父容器的 10%,右侧边栏排列顺序设为 -1 且最大宽度为父容器的 20%,同时利用自定义响应式混合器,使右侧边栏在屏幕达到特定大尺寸(对应 lg)时以弹性布局显示。
.left-sidebar {
order: -3;
// max-width: var(--left-sidebar-max-width);
max-width: 10%;
}

.right-sidebar {
order: -1;
// max-width: var(--right-sidebar-max-width);
max-width: 20%;

/// Display right sidebar when min-width: lg
@include respond(lg) {
display: flex;
}
}

把正文的占比改到了 70%, 原来的只有 50% 左右

头像旋转

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
7
8
// ----------头像旋转动画--------------
.sidebar header .site-avatar .site-logo {
transition: transform 1.65s ease-in-out; // 旋转时间
}

.sidebar header .site-avatar .site-logo:hover {
transform: rotate(360deg); // 旋转角度为360度
}

友情链接+分类+标签+归档【三栏显示】

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//------------------------------------------------------
// 友情链接+分类+标签+归档【三栏显示】
@media (min-width: 1024px) {
.article-list--compact {
display: grid;
// 目前是三列,如需二列,则后面减去一个1fr,以此类推
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;
margin-right: 8px;
border-radius: 16px;
}
}
}

缩小归档页的分类卡片尺寸

  • 默认的卡片有些太大了, ./assets/scss/partials/layout/list.scss中加入以下代码:(并修改)
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
//---------------缩小归档页的分类卡片尺寸---------------
.subsection-list {
overflow-x: auto;

.article-list--tile {
display: flex;
padding-bottom: 0px;

article {
width: 230px;
height: 120px;
margin-right: 5px;
flex-shrink: 0;

.article-title {
margin: 0;
font-size: 1.8rem;
}

.article-details {
padding: 20px;
}
}
}
}

调整 TOC 目录间距

  • ./assets/scss/custom.scss 中加入以下代码:
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
// ----------------调整 TOC 目录间距------------------
// 主要解决了几个问题:
// 目录太高了,使得之前添加的返回顶部按钮可能会被顶出屏幕;
// 目录项前面的小黑点不太好看,隐去;
// 目录项之间的距离不够紧凑。
.widget--toc {
background-color: var(--card-background);
border-radius: var(--card-border-radius);
box-shadow: var(--shadow-l2); //修改阴影样式
display: flex;
flex-direction: column;
color: var(--card-text-color-main);
overflow: hidden;
display:inline-block; //根据内容调整宽度

#TableOfContents {
max-height: 65vh;

ol,
ul {
list-style-type: none;
}

li {
margin: 10px 10px;

& > ol,
& > ul {
margin-top: 10px;
padding-left: 10px;
margin-bottom: -5px;

& > li:last-child {
margin-bottom: 0;
}
}
}

& > ul {
padding: 0 1em;
}

li {
margin: 5px 20px; //第一个参数是行间距,第二个是卡片周边的宽度

padding: 6px; //控制内边距

& > ol,
& > ul {
margin-top: 10px;
padding-left: 10px;
margin-bottom: -5px;

& > li:last-child {
margin-bottom: 0;
}
}
}
}
}

鼠标悬停,超链接的显示

  • ./assets/scss/custom.scss 中加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ---------------------鼠标悬停,超链接的显示-------------------
a {
text-decoration: none;
color: var(--accent-color);

&:hover {
color: var(--accent-color-darker);
}

&.link {
// 鼠标未悬停时,超链接显示2px的高亮
box-shadow: 0px -2px 0px rgba(var(--link-background-color), var(--link-background-opacity-hover)) inset;
transition: all 0.3s ease;

&:hover {
// 鼠标悬停,高亮为18px
box-shadow: 0px -18px 0px rgba(var(--link-background-color), var(--link-background-opacity-hover)) inset;
}
}
}

其它小部件

添加站点统计信息与 i18n

展示格式:

  • 本博客已稳定运行 x 天 y 小时 z 分钟

  • 共发表 x 篇文章・总计 y k 字

  • 本站总访问量 x 次

  • 在根目录./layouts/partials/footer/footer.html 文件内添加如下代码:

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
<section class="count_info">
<div>
{{ T "footer.runtime1" }}
<span id="ds" class="running-days"></span>
{{ T "footer.runtime2" }}
<span id="hs" class="running-days"></span>
{{ T "footer.runtime3" }}
<span id="ms" class="running-days"></span>
{{ T "footer.runtime4" }}
</div>
<div>
{{$scratch := newScratch}}
{{ range (where .Site.Pages "Kind" "page" )}}
{{$scratch.Add "total" .WordCount}}
{{ end }}
{{ T "footer.count1" }} {{ len (where .Site.RegularPages "Section" "post") }} {{ T "footer.count2" }} {{ div ($scratch.Get "total") 1000.0 | lang.FormatNumber 2 }} k {{ T "footer.count3" }}
</div>
<div>
<span id="busuanzi_container_site_pv">{{ T "footer.pv1" }}<span id="busuanzi_value_site_pv"></span>{{ T "footer.pv2" }}</span>
</div>
</section>

<!-- Add blog running time -->
<script>
let s1 = '2023-6-18'; //website start date
s1 = new Date(s1.replace(/-/g, "/"));
let s2 = new Date();
let timeDifference = s2.getTime() - s1.getTime();

let days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
let hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
let minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
document.getElementById('ds').innerHTML = days;
document.getElementById('hs').innerHTML = hours;
document.getElementById('ms').innerHTML = minutes;

</script>
  • 在主题目录/i18n/zh-cn.yaml 下找到对应语言的文件,在属性 footer 下添加相应字段,结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
footer:
# 本博客已稳定运行1天2小时3分钟
runtime1:
other: 本博客已稳定运行
runtime2:
other: 天
runtime3:
other: 小时
runtime4:
other: 分钟

# 共发表x篇文章,总计y k字
count1:
other: 共发表
count2:
other: 篇文章 · 总计
count3:
other: 字

# 本站总访问量X次
pv1:
other: 本站总访问量
pv2:
other: 次

添加访客地图

  • 在根目录./layouts/partials/sidebar/right.html 添加后完整代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{{- $scope := default "homepage" .Scope -}}
{{- $context := .Context -}}
{{- with (index .Context.Site.Params.widgets $scope) -}}
<aside class="sidebar right-sidebar sticky">
{{ range $widget := . }}
{{ if templates.Exists (printf "partials/widget/%s.html" .type) }}
{{ partial (printf "widget/%s" .type) (dict "Context" $context "Params" .params) }}
{{ else }}
{{ warnf "Widget %s not found" .type }}
{{ end }}
{{ end }}
<div style="height: 30%;width: 30%">
<script type="text/javascript" id="clstr_globe" src="//clustrmaps.com/globe.js?d=xxxxx"></script>
</div>
</aside>
{{ end }}

鼠标样式

  • 准备好鼠标样式图片(默认,指针,文本…),图片大小建议控制在 32px 左右,将.png图片放入static/mouse文件夹下(文件夹自己创建)
    修改对应的图片名即可
  • 修改./assets/scss/custom.scss(文件不存在则自己创建),将以下代码复制进去,根据主题按实际情况填写对应的css选择器
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
// 【Stack主题鼠标样式写法】
// default光标图片
body,
html,
.article-content img {
cursor: url(../mouse/default.png),
auto !important;
}

// pointer光标图片
a:hover,
button:hover,
.copyCodeButton:hover,
#dark-mode-toggle {
cursor: url(../mouse/pointer.png),
auto;
}

// text光标图片
input:hover,
.site-description,
.article-subtitle,
.article-content span,
.article-content li,
.article-content p {
cursor: url(../mouse/text.png),
auto;
}

/*主页布局间距调整*/
.main-container {
gap: 50px; //文章宽度

@include respond(md) {
padding: 0 30px;
gap: 40px; //中等屏幕时的文章宽度
}
}

.related-contents {
overflow-x: visible; //显示隐藏的图标
padding-bottom: 15px;
}

首页欢迎横幅

  • ./layouts/index.html<section class="article-list"> 前添加以下代码:
1
2
3
4
5
6
7
8
9
10
11
<!-- 首页欢迎字幅 -->
<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">Xa</span><span class="jump-text4" style="color:#e99312">l</span><span class="jump-text5" style="color:#e99312">a</span><span class="jump-text6" style="color:#e99312">o</span><span class="jump-text7" style="color:#e99312">k</span><span class="jump-text8" style="color:#e99312">'s</span>
<span class="jump-text9" style="color:#e99312">Blog</span>
</p>
</div>
<!-- 首页欢迎字幅 -->
  • ./assets/scss/custom.scss 中加入以下代码:
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
// ----------------首页欢迎板块样式----------------
.welcome {
color: var(--card-text-color-main);
background: var(--card-background);
box-shadow: var(--shadow-l2);
border-radius: 30px;
display: inline-block;
}

// 👋emoji实现摆动效果
.shake {
display: inline-block;
animation: shake 1s;
animation-duration: 1s;
animation-timing-function: ease;
animation-delay: 0s;
animation-iteration-count: 1;
animation-direction: normal;
animation-fill-mode: none;
animation-play-state: running;
animation-name: shake;
animation-timeline: auto;
animation-range-start: normal;
animation-range-end: normal;
animation-delay: 2s;
@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);
}
}
}

// 实现字符跳动动画
.jump-text1 {
display: inline-block;
animation: jump 0.5s 1;
}

.jump-text2 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.1s;
}

.jump-text3 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.2s;
}

.jump-text4 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.3s;
}

.jump-text5 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.4s;
}

.jump-text6 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.5s;
}

.jump-text7 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.6s;
}

.jump-text8 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.7s;
}

.jump-text9 {
display: inline-block;
animation: jump 0.5s 1;
animation-delay: 0.9s;
}

@keyframes jump {
0% {
transform: translateY(0);
}
50% {
transform: translateY(-20px);
}
100% {
transform: translateY(0);
}
}

删除“使用 Hugo 构建 主题Stack由Jimmy设计”等字样

  • 删除掉./layout/partials/footer/footer.html 原先的代码,注意是
    里边的
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
{{- $ThemeVersion := "3.29.0" -}}
<footer class="site-footer">
<section class="copyright">
&copy;
{{ if and (.Site.Params.footer.since) (ne .Site.Params.footer.since (int (now.Format "2006"))) }}
{{ .Site.Params.footer.since }} -
{{ end }}
{{ now.Format "2006" }} {{ default .Site.Title .Site.Copyright }}
</section>

<!------------- 以下的删除掉 ------------->
<section class="powerby">
{{ with .Site.Params.footer.customText }}
{{ . | safeHTML }} <br/>
{{ end }}

{{- $Generator := `<a href="https://gohugo.io/" target="_blank" rel="noopener">Hugo</a>` -}}
{{- $Theme := printf `<b><a href="https://github.com/CaiJimmy/hugo-theme-stack" target="_blank" rel="noopener" data-version="%s">Stack</a></b>` $ThemeVersion -}}
{{- $DesignedBy := `<a href="https://jimmycai.com" target="_blank" rel="noopener">Jimmy</a>` -}}

{{ T "footer.builtWith" (dict "Generator" $Generator) | safeHTML }} <br />
{{ T "footer.designedBy" (dict "Theme" $Theme "DesignedBy" $DesignedBy) | safeHTML }}

{{ $articleCount := len .Site.RegularPages }}
{{ $totalWordCount := 0 }}
{{ range .Site.Pages }}
{{ $totalWordCount = add $totalWordCount .WordCount }}
{{ end }}

<p>发布了 {{ $articleCount }} 篇文章 | 共 {{$totalWordCount}} 字</p>
</section>
<!------------- 以上的删除掉 ------------->
</footer>

添加【返回顶部】按钮

    1. 返回顶部图片,复制以下代码保存为.svg文件,放到./assets/icons文件夹下(不存在则自行创建)
1
2
3
4
5
6
7
8
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 24 24" fill="none" stroke="#707070"
stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="icon icon-tabler icons-tabler-outline icon-tabler-square-rounded-arrow-up">
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
<path d="M16 12l-4 -4l-4 4"/>
<path d="M12 16v-8"/>
<path d="M12 3c7.2 0 9 1.8 9 9s-1.8 9 -9 9s-9 -1.8 -9 -9s1.8 -9 9 -9z"/>
</svg>
    1. 将以下代码复制到layouts/partials/footer/custom.html文件中(不存在则自行创建)
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
<!-- layouts/partials/footer/custom.html -->
<!-- 返回顶部按钮 -->
<style>
#backTopBtn {
display: none;
position: fixed;
bottom: 30px;
z-index: 99;
cursor: pointer;
width: 30px;
height: 30px;
background-image: url({{ (resources.Get "icons/backTop.svg").RelPermalink }});
/* 为 transform 属性添加过渡效果,持续时间 1 秒,过渡方式为缓入缓出 */
transition: transform 1s ease-in-out;
}

#backTopBtn:hover {
/* 悬停时360度旋转 */
transform: rotate(360deg);
}

</style>

<script>
/**
* 滚动回顶部初始化
*/
function initScrollTop() {
let rightSideBar = document.querySelector(".right-sidebar");
if (!rightSideBar) {
return;
}
// 添加返回顶部按钮到右侧边栏
let btn = document.createElement("div");
btn.id = "backTopBtn";
btn.onclick = backToTop
rightSideBar.appendChild(btn)
// 滚动监听
window.onscroll = function() {
// 当网页向下滑动 20px 出现"返回顶部" 按钮
if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) {
btn.style.display = "block";
} else {
btn.style.display = "none";
}
};
}

/**
* 返回顶部
*/
function backToTop(){
window.scrollTo({ top: 0, behavior: "smooth" })
}

initScrollTop();
</script>
    1. 我使用中的
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
<style>
#backTopBtn {
display: none;
position: fixed;
bottom: 100px;
/* 新增右侧定位 */
/* right: 480px; */
z-index: 99;
cursor: pointer;
width: 40px;
height: 40px;
background-image: url({{ (resources.Get "icons/backTop.svg").RelPermalink }});
/* 添加will-change优化渲染性能 */
will-change: transform;
transition: transform 1s ease-in-out;
}

#backTopBtn:hover {
transform: rotate(360deg);
}
</style>

<script>
/**
* 滚动回顶部初始化
*/
function initScrollTop() {
let rightSideBar = document.querySelector(".right-sidebar");
if (!rightSideBar) {
return;
}
// 添加返回顶部按钮到右侧边栏
let btn = document.createElement("div");
btn.id = "backTopBtn";
btn.onclick = backToTop
rightSideBar.appendChild(btn)
// 滚动监听
window.onscroll = function () {
// 统一获取页面滚动高度
let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
// 当网页向下滑动 20px 出现"返回顶部" 按钮
if (scrollTop > 20) {
btn.style.display = "block";
} else {
btn.style.display = "none";
}
};
}
/**
* 返回顶部
*/
function backToTop() {
window.scrollTo({ top: 0, behavior: "smooth" })
}

initScrollTop();
</script>
    1. 解决 PJAX 刷新问题
  • 编辑.\layouts\partials\footer\pjax.html文件 。pjax:complete 事件下,添加以下内容:
1
2
3
// 重新初始化返回顶部按钮
topbar.hide();
initScrollTop();

hugo 接入评论

1、GitHub 打开评论

  • 首先进入【GitHub】,hugo 博客项目主页–>>项目设置–>>找到Discussions Loading

2、giscus 配置

3、GitHub 博客项目接入 giscus

  • 随着官网的说明一步步配置下去。配置完成后便可在 启用 giscus 下找到需要的代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<script src="https://giscus.app/client.js"
data-repo="meimolihan/meimolihan.github.io"
data-repo-id="R_kgDONpRkKg"
data-category="Announcements"
data-category-id="DIC_kwDONpRkKs4CmwSa"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="bottom"
data-theme="dark"
data-lang="zh-CN"
crossorigin="anonymous"
async>
</script>

4、修改 hugo 主配置文件

  • 我使用的是Hugo的stack主题,需要在 config.yaml 中设置
1
2
3
comments:
enabled: true
provider: giscus

5、引入 giscus-js文件

  • 将stack主题./themes/hugo-theme-stack/layouts/partials/comments/provider/giscus.html文件拷贝至./layouts/partials/comments/provider/目录下 (需新建)
  • 然后将giscus-js代码放到下面的位置:

6、文章 index.md 打开评论

  • false 关闭评论,true 显示评论。
1
comments: true
  • 配置完成,hugo server -D启动hugo,在本地就可以看到效果。

Hugo Stack 预加载动画

1、新增组件

小组件放在layouts/partials/widget/preload.html 文件里,注意,这个文件是自己创建的:

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
{{ if .Site.Params.enablePreloadingAnim }}
<div id="loading-box">
<!-- 页面加载完成之后帷幕拉开的效果 -->
<div class="loading-left-bg"></div>
<div class="loading-right-bg"></div>
<!-- 旋转盒子动效 -->
<div class="spinner-box">
<div class="configure-border-1">
<div class="configure-core"></div>
</div>
<div class="configure-border-2">
<div class="configure-core"></div>
</div>
<div class="loading-word">加载中...</div>
</div>
</div>
<!-- 页面加载动画 -->
<script>
// 确保 jQuery 已加载
if (typeof $ !== 'function') {
console.error("jQuery is not loaded. Please ensure jQuery is included in your project.");
}

// 使用 window.onload 确保所有资源加载完成后隐藏动画
window.addEventListener("load", function () {
const loadingBox = document.getElementById('loading-box');
if (loadingBox) {
// 延时一段时间以确保动画有足够的时间展示
setTimeout(function () {
loadingBox.classList.add("loaded");
console.log("Preloader hidden after all resources are loaded.");
}, 500); // 延时 0.5 秒(可根据需要调整)
} else {
console.error("Preloader element not found!");
}
});

// 如果需要显示加载进度,可以添加以下逻辑(可选)
let loadedResources = 0;
const totalResources = document.images.length + document.styleSheets.length;

function checkResourceLoad() {
loadedResources++;
const progress = Math.round((loadedResources / totalResources) * 100);
const loadingWord = document.querySelector('.loading-word');
if (loadingWord) {
loadingWord.textContent = `加载中... ${progress}%`;
}
if (loadedResources >= totalResources) {
window.dispatchEvent(new Event('load')); // 手动触发 load 事件
}
}

// 监听图片加载
document.images.forEach(img => {
img.addEventListener('load', checkResourceLoad);
img.addEventListener('error', checkResourceLoad);
});

// 监听样式表加载
document.styleSheets.forEach(sheet => {
checkResourceLoad();
});
</script>
{{ end }}

2、组件样式

  • 找到 ./assets/scss/custom.scss 在文件里面追加 :
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
#loading-box .loading-left-bg,
#loading-box .loading-right-bg {
position: fixed;
z-index: 1000;
width: 50%;
height: 100%;
// 我在这里小改了一下颜色,
background-color: #b1c0c7;
transition: all 0.5s;
}

#loading-box .loading-right-bg {
right: 0;
}

#loading-box>.spinner-box {
position: fixed;
z-index: 1001;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100vh;
}

#loading-box .spinner-box .configure-border-1 {
position: absolute;
padding: 3px;
width: 115px;
height: 115px;
background: #ffab91;
animation: configure-clockwise 3s ease-in-out 0s infinite alternate;
}

#loading-box .spinner-box .configure-border-2 {
left: -115px;
padding: 3px;
width: 115px;
height: 115px;
background: rgb(63, 249, 220);
transform: rotate(45deg);
animation: configure-xclockwise 3s ease-in-out 0s infinite alternate;
}

#loading-box .spinner-box .loading-word {
position: absolute;
color: #ffffff;
// 我在这里小改了一下文字大小和字体,注意!
font-size: 1.8rem;
font-family: 'Zhi Mang Xing', cursive;
}

#loading-box .spinner-box .configure-core {
width: 100%;
height: 100%;
background-color: #37474f;
}

div.loaded div.loading-left-bg {
transform: translate(-100%, 0);
}

div.loaded div.loading-right-bg {
transform: translate(100%, 0);
}

div.loaded div.spinner-box {
// 你可以把这个注释掉,这样就能一直看那个动画的效果了!
display: none !important;
}

@keyframes configure-clockwise {
0% {
transform: rotate(0);
}

25% {
transform: rotate(90deg);
}

50% {
transform: rotate(180deg);
}

75% {
transform: rotate(270deg);
}

100% {
transform: rotate(360deg);
}
}

@keyframes configure-xclockwise {
0% {
transform: rotate(45deg);
}

25% {
transform: rotate(-45deg);
}

50% {
transform: rotate(-135deg);
}

75% {
transform: rotate(-225deg);
}

100% {
transform: rotate(-315deg);
}
}

3、配置文件

  • hugo配置文件params 栏目底下,加上 enablePreloadingAnim: true
1
2
params:
enablePreloadingAnim: true # 开屏动画,false为关闭,true为开启

Hugo 图片灯箱

  • 使用 Fancybox 实现图片灯箱/放大功能
  • Hugo 自带的图片渲染是没有灯箱效果的,所以我们需要自己添加。灯箱效果就是点击图片后,图片会放大显示。

修改 Hugo 配置文件

修改网站根目录下的 config.toml 或者 config.yaml 文件,我的配置文件为 yaml 格式,toml 需要自行调整格式,在 params参数下添加以下内容:

1
2
params
fancybox: true # 图片灯箱,false为关闭,true为开启

创建 render-image.html 文件

  • 在你的 Hugo 根目录下创建以下路径和文件:./layouts/_default/_markup/render-image.html
  • 编辑 render-image.html 添加以下内容:
1
2
3
4
5
6
7
{{if .Page.Site.Params.fancybox }}
<div class="post-img-view">
<a data-fancybox="gallery" href="{{ .Destination | safeURL }}">
<img src="{{ .Destination | safeURL }}" alt="{{ .Text }}" {{ with .Title}} title="{{ . }}"{{ end }} />
</a>
</div>
{{ end }}

复制 custom.html 文件

  • 从你主题目录 ./themes/stack/layouts/partials/footer/custom.html复制到 Hugo在你根目录 layouts/partials/footer/custom.html ,添加以下内容:
1
2
3
4
5
{{if .Page.Site.Params.fancybox }}
<script src="https://cdn.jsdelivr.net/npm/jquery@3.5.1/dist/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.css" />
<script src="https://cdn.jsdelivr.net/gh/fancyapps/fancybox@3.5.7/dist/jquery.fancybox.min.js"></script>
{{ end }}

接下来就可以直接 hugo server -D看看效果了。

引入动态背景(点线漂浮(particles.js))

1. 前往【配置页面】配置参数,参数按自己喜好即可,唯一注意要修改的参数是 detect_on,要改成 window

2. 下载配置文件,以及 particles.js 所需要的js文件

particlesjs-config.json】(Ctrl + S 保存),本博客的动态背景json配置,有需求的可直接下载

3. 把下载好的文件,解压并将以下两个文件放到assets/background文件夹下

  • particlesjs-config.json
  • particles.min.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id="particles-js"></div>

<script src={{ (resources.Get "background/particles.min.js").Permalink }}></script>
<script>
particlesJS.load('particles-js', {{ (resources.Get "background/particlesjs-config.json").Permalink }}, function() {
console.log('particles.js loaded - callback');
});
</script>

<style>
#particles-js {
position: fixed;
top: 0;
left: 0;
width: 100%;
z-index: -1;
}
</style>

【Hugo】博客文章浏览数统计

引入第三方组件,来给博客文章统计浏览数

教程

Hugo

前言:

  • 博客文章统计组件个人找到了两个,分别是不蒜子,以及vercount
  • 不蒜子比较老,但很稳定,到现在仍然可以使用,没有停服
  • vercount则比较新,并做了一些代码优化
  • 两种使用都基本一样,差别不大,看自己喜好,下面的教程是以vercount来举例,用不蒜子的话,就把对应的脚本和元素标签替换一下就好

1 基本引入

  • (1)修改layouts/partials/footer/custom.html(不存在则自行创建),引入脚本
1
<!-- vercount的脚本;若用不蒜子,则更换成不蒜子的脚本就好 --> <script defer src="https://cn.vercount.one/js"></script> 
  • (2)准备一张浏览量的icon(Ctrl+S保存),放到assets/icons文件夹下

  • (3)修改layouts/article/components/details.html,在合适的位置下加入以下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="article-details">
...
<footer class="article-time">
...
<!-- 浏览量统计 -->
<div id="viewCount">
{{ partial "helper/icon" "eye" }}
<time class="article-time--reading">
<!-- vercount统计当前页面浏览数的标签;若用不蒜子,更换成不蒜子对应的标签就好 -->
<span id="vercount_value_page_pv">loading... </span>
</time>
</div>
</footer>
...
</div>
  • (4)这样文章详情的开头就显示浏览数了

img

2 问题修复

  • 问题描述:
    • 博客首页的文章列表显示了浏览数,且只有第一篇文章才有浏览数,并且浏览数的数字不正确

img

  • 产生原因:

    • layouts/partials/article/components/details.html此html文件也被用在了博客首页的文章列表,所以也触发了vercount读取当前页面的浏览数
    • 因为读取的数据是当前页面的浏览数,也就是首页的浏览数,并非文章的浏览数,所以数据只加载一次,且不准确
  • 解决思路:

    • 由于vercount并未提供只查询文章浏览数的接口,只有一个文章浏览数+1,并且返回浏览数的接口,所以无法实现首页对每篇文章的浏览数的单独查询
    • 既然无法实现首页展示每篇文章的单独浏览数,那就直接隐藏就好了,等点入文章才看到具体的浏览数
  • 具体操作:

    • (1)修改layouts/partials/footer/custom.html,引入以下代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<script>
function showHideView() {
// 判断是否存在vercount标签
let viewCounts = document.querySelectorAll("#viewCount");
if (viewCounts) {
// 判断是否为文章页
let article = document.querySelector(".article-page");
if (!article) {
viewCounts.forEach(ele => {
ele.style.display = 'none';
});
}
}
}

showHideView();
</script>
  • 如果嫌麻烦,浏览数统计可以和更新时间一样,放到文章末尾就好,就不会显示到首页上了
  • 具体修改layouts/partials/article/footer.html就好,看个人喜好吧