基本原理
- Hugo的stack主题提供了自定义样式的接口,主要在
layouts/partials/footer/custom.html和assets/scss/custom.scss中
- Hugo的文件可以实现文件覆盖。只要文件位置与
themes文件夹中的相同,就会先加载自定义文件。
页面布局
首页文章样式
在/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
|
/*主页文章图片样式*/
$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文件,引入以下css样式代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
@media (min-width: 1024px) {
.article-list--compact {
display: grid;
// 目前是两列,如需三列,则后面再加一个1fr,以此类推
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;
margin-right: 8px;
border-radius: 16px;
}
}
}
|
代码块样式
代码块行标设置
在config.yaml中找到highlight部分:
1
2
3
4
5
6
7
8
|
highlight:
noClasses: false
codeFences: true
guessSyntax: true
lineNoStart: 1
lineNos: true # 是否显示行号
lineNumbersInTable: false # 行号是否独立成列
tabWidth: 4
|
MacOS风格图标
- 准备一张macOS代码块的红绿灯图片放到
static/icons文件夹下,或者将以下代码写入code-header.svg文件中:
1
2
3
4
5
|
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" x="0px" y="0px" width="450px" 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/custom.scss文件中。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
.highlight {
border-radius: var(--card-border-radius);
max-width: 100% !important;
margin: 0 !important;
box-shadow: var(--shadow-l1) !important;
}
.highlight:before {
content: "";
display: block;
// 这里填图片地址
background: url(../icons/macOS-code-header.svg) no-repeat 0;
background-size: contain;
height: 18px;
margin-top: -10px;
margin-bottom: 10px;
}
|
复制不显示行号
在assets/ts/main.ts中找到copyButton项,修改为以下内容:
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
|
copyButton.addEventListener('click', () => {
// 创建一个临时容器来克隆代码块的内容
const tempCodeBlock = codeBlock.cloneNode(true) as HTMLElement;
// 删除行号,行号的元素是 <span class="ln">
const lineNumbers = tempCodeBlock.querySelectorAll('.ln');
lineNumbers.forEach(lineNumber => lineNumber.remove());
// 获取没有行号的纯文本内容
const codeText = tempCodeBlock.textContent;
navigator.clipboard.writeText(codeText || '')
// navigator.clipboard.writeText(codeBlock.textContent)
.then(() => {
copyButton.textContent = copiedText;
setTimeout(() => {
copyButton.textContent = copyText;
}, 1000);
})
.catch(err => {
alert(err)
console.log('Something went wrong', err);
});
});
|
可视化加载条
-
下载【文件】,并将压缩包中的topbar.min.js移动至assets/js中。
-
在layouts/partials/footer/custom中加入以下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
{{ with resources.Get "js/topbar.min.js" }}
<!-- 引入本地JS脚本 -->
<script src={{ .Permalink }}></script>
{{ end }}
<script>
// 修改进度条颜色
topbar.config({
barColors: {
'0': 'rgba(255, 255, 255, 1)', // 进度0%白色
'1.0': 'rgba(0, 149, 234, 1)' // 进度100%蓝色
}
})
document.addEventListener('pjax:send', () => {
// 显示顶部进度条
topbar.show();
})
document.addEventListener('pjax:complete', () => {
// 隐藏顶部进度条
topbar.hide();
})
</script>
|
网页组件
若想在网页中加入自定义内容,一种方法是在模版中写入.html源码;另一种方法是将代码封装成组件(widget),再以链接的方式引入模板中。
后者可以方便地实现代码复用,对原模版的改动也最小。实际上,每个组件本质上就是一个网页文件(.html),然后放入模版文件中即可实现在网页上加载。
以下提供了几个示例,供您参考。
首页欢迎栏
- 在
/layouts/partial/widget/中新建文件welcome-bar.html,写入以下内容:
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">Wei Qi</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
|
//首页欢迎板块样式
.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-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);
}
}
|
实际上,这些css代码也可以直接写在welcome-bar.html的<style></style>标签中,在以下组件中同理。
随机文字卡片
随机效果
随机效果依赖javascript脚本:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 获取并展示文字内容
function showQuotes() {
// 随机文字
index = Math.floor(Math.random() * quotes.length);
const quote = quotes[index];
// 获取文字和作者信息
const textElement = document.querySelector(".quote-text");
const authorElement = document.querySelector(".quote-author");
textElement.innerText = quote.quote;
authorElement.innerText = `—— ${quote.author}`;
// 渲染数学公式(可选)
renderMathInElement(textElement, {
delimiters: [
{left: '$$', right: '$$', display: true},
{left: '$', right: '$', display: false},
{left: '\\[', right: '\\]', display: true},
{left: '\\(', right: '\\)', display: false}
]
});
};
|
完善实现事件还需要增加一个按钮,实现点击就能随机显示文字。
1
|
<button id="new-quote">Random</button>
|
然后赋予其点击事件:
1
2
3
|
<script>
document.querySelector("#new-quote").addEventListener("click", showQuotes);
</script>
|
设置配置文件
如果将文字内容写在.html文件内部,可配置性不佳,而且会使代码臃肿。因此,可以将随机文字的内容写入json文件并放入static/文件夹中。
为什么放入static文件夹?
static文件夹存放网页的静态内容,通俗点就是其中的内容就在站点目录之下。例如站点名为https://www.example.com,那么static/quotes.json就在https://www.example.com/quote.json处,在寻找时可以直接输入/quotes.json。
密码栏
在网页中显示组件
主页显示
在index.html中加入:
1
2
3
4
5
|
<section class="article-list">
...
{{ partial "widget/你的组件名.html" . }}
...
</section>
|
侧边栏
1
2
3
|
page:
- type: toc
- type: 你的组件名
|