Featured image of post Hugo网站美化

Hugo网站美化

对网站做简单的更改和美化,使网站功能更加完善。

网站美化

评论区配置

giscus是利用Github仓库的Discussions来实现的,完全免费。

使用方法

  1. 进入官网,giscus官方网站:https://github.com/giscus/giscus
image-20260127134306559

点击右侧giscus.app,到下面配置界面,先点击最上面giscus,进入安装界面

image-20260127135113976 image-20260127134724442

可以选择安装到所有仓库,或者之前创建的静态页面仓库,建议安装在静态页面仓库

image-20260127134905278
  1. 返回到配置界面,往下找到配置项
image-20260127135304951

将静态仓库名按照要求填进去

  1. 页面与discussion映射关系:只选择第一个,默认已选择,不用改
  2. Discussion按照推荐选择
image-20260127135712053
  1. 特性选择建议
image-20260127135806959
  1. 主题自定义

  2. 启用giscus

image-20260127135909049

上面配置好的信息会出现在这里,下面配置hugo.yaml网站配置文件

  1. hugo.yaml中找到comments->provider,填上giscus,然后找到下面giscus,按照上图中的参数,找到对应名字填进去就行,比如data-repo<->repodata-repo-id<->repoID,需要说明的是配置中有两个主题lightThemedarkTheme,这个参数对应data-theme,可以通过第6步中主题自定义更改这个参数。
1
2
lightTheme: "light_protanopia"
darkTheme: "dark_high_contrast"
  1. 先到静态仓库页面,点击settings,右侧向下滑动,找到Features,勾选Discussions
image-20260127141326332 image-20260127141449632
  1. 提交代码,评论区配置完成。

网站页脚更改

网站页脚的html文件在以下路径:D:\Dev\MyBlog\blog\themes\hugo-theme-stack\layouts\partials\footer

image-20260127142332785

复制footer.html,放到D:\Dev\MyBlog\blog\layouts\partials\footer文件夹下(前面说过不能改themes内的文件,要把对应文件复制到blog文件夹下进行更改),打开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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
{{- $ThemeVersion := "3.33.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="custom-footer-text">
        <p style="text-align: left; font-size: 1.1em; margin: 0.5em 0;">
            [ 天天熬夜 <span class="heartbeat">❤️</span> 迟早猝死 ]
        </p>
        <p id="blog-runtime" style="text-align: left; font-size: 0.9em; margin: 0.5em 0; color: #888;">
            这个网站已经运行了: <span id="runtime-value">Loading...</span>
            <span class="floating-end">ღゝ◡╹)ノ♡</span>
        </p>
    </section>

</footer>

<style>
    .custom-footer-text {
        font-family: 'ZCOOL QingKe HuangYou', cursive, sans-serif;
    }

    .custom-footer-text p:first-child {
        font-size: 1.2em;
        /* 可选:加粗 */
        /* font-weight: bold; */
    }

    .heartbeat {
        display: inline-block;
        animation: heartbeat 1.5s ease-in-out infinite;
        color: #e74c3c; /* 红色 */
    }

    @keyframes heartbeat {
        0% { transform: scale(1); }
        15% { transform: scale(1.1); }
        30% { transform: scale(1); }
        45% { transform: scale(1.1); }
        60% { transform: scale(1); }
        75% { transform: scale(1.1); }
        100% { transform: scale(1); }
    }
     
    .floating-end {
        display: inline-block;
        animation: float 3s ease-in-out infinite;
    }

    @keyframes float {
        0%, 100% { transform: translateY(0); }
        50% { transform: translateY(-3px); }
    }
</style>

<script>
    document.addEventListener('DOMContentLoaded', function() {
        // 设置博客开始时间 (请替换为你的实际建站日期)
        const startDate = new Date("2022-06-18T00:00:00Z"); 

        function updateRuntime() {
            const now = new Date();
            const diffMs = now - startDate;
            const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
            const diffHours = Math.floor((diffMs % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
            const diffMinutes = Math.floor((diffMs % (1000 * 60 * 60)) / (1000 * 60));
            const diffSeconds = Math.floor((diffMs % (1000 * 60)) / 1000);

            const runtimeStr = `${diffDays}  ${diffHours} 小时 ${diffMinutes} 分钟 ${diffSeconds} 秒`;
            document.getElementById('runtime-value').textContent = runtimeStr;
        }

        updateRuntime();
        setInterval(updateRuntime, 1000);
    });
</script>

滚动事件

在页面右下角添加回到顶端滚动到底部两个按钮。

首先在D:\Dev\MyBlog\blog\static\js路径下新建scroll-button.js,将下面代码复制进去

  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
document.addEventListener('DOMContentLoaded', function() {
    // 创建按钮容器
    const btnContainer = document.createElement('div');
    btnContainer.id = 'scrollButtons';
    btnContainer.style.cssText = `
        position: fixed;
        right: 1.5rem;
        bottom: 1.5rem;
        z-index: 9999;
        display: flex;
        flex-direction: column;
        gap: 0.75rem;
        pointer-events: none;
    `;

    // 创建「到顶部」按钮
    const topBtn = document.createElement('button');
    topBtn.id = 'scrollToTop';
    topBtn.title = '回到顶部';
    topBtn.innerHTML = `
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M12 19V5M5 12l7-7 7 7"/>
        </svg>
    `;
    topBtn.style.cssText = `
        width: 44px;
        height: 44px;
        border-radius: 50%;
        background: var(--card-background);
        color: var(--card-font-color);
        border: none;
        box-shadow: 0 2px 8px rgba(0,0,0,0.15);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s ease;
        pointer-events: auto;
    `;
    topBtn.onmouseover = () => {
        topBtn.style.transform = 'translateY(-2px)';
        topBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
        topBtn.style.background = 'var(--theme-color)';
        topBtn.style.color = 'white';
    };
    topBtn.onmouseout = () => {
        topBtn.style.transform = 'translateY(0)';
        topBtn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';
        topBtn.style.background = 'var(--card-background)';
        topBtn.style.color = 'var(--card-font-color)';
    };
    topBtn.onclick = (e) => {
        e.preventDefault();
        window.scrollTo({ top: 0, behavior: 'smooth' });
    };

    // 创建「到底部」按钮
    const bottomBtn = document.createElement('button');
    bottomBtn.id = 'scrollToBottom';
    bottomBtn.title = '滚动到底部';
    bottomBtn.innerHTML = `
        <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
            <path d="M12 5v14M5 12l7 7 7-7"/>
        </svg>
    `;
    bottomBtn.style.cssText = `
        width: 44px;
        height: 44px;
        border-radius: 50%;
        background: var(--card-background);
        color: var(--card-font-color);
        border: none;
        box-shadow: 0 2px 8px rgba(0,0,0,0.15);
        cursor: pointer;
        display: flex;
        align-items: center;
        justify-content: center;
        transition: all 0.3s ease;
        pointer-events: auto;
    `;
    bottomBtn.onmouseover = () => {
        bottomBtn.style.transform = 'translateY(2px)';
        bottomBtn.style.boxShadow = '0 4px 12px rgba(0,0,0,0.2)';
        bottomBtn.style.background = 'var(--theme-color)';
        bottomBtn.style.color = 'white';
    };
    bottomBtn.onmouseout = () => {
        bottomBtn.style.transform = 'translateY(0)';
        bottomBtn.style.boxShadow = '0 2px 8px rgba(0,0,0,0.15)';
        bottomBtn.style.background = 'var(--card-background)';
        bottomBtn.style.color = 'var(--card-font-color)';
    };
    bottomBtn.onclick = (e) => {
        e.preventDefault();
        window.scrollTo({ top: document.documentElement.scrollHeight, behavior: 'smooth' });
    };

    // 组装
    btnContainer.appendChild(topBtn);
    btnContainer.appendChild(bottomBtn);
    document.body.appendChild(btnContainer);

    // 滚动时动态显示/隐藏(滚动 > 300px 显示)
    window.addEventListener('scroll', () => {
        const show = window.pageYOffset > 300;
        topBtn.style.opacity = show ? '1' : '0';
        topBtn.style.visibility = show ? 'visible' : 'hidden';
        bottomBtn.style.opacity = show ? '1' : '0';
        bottomBtn.style.visibility = show ? 'visible' : 'hidden';
    });

    // 接近底部时隐藏「到底部」按钮
    window.addEventListener('scroll', () => {
        const nearBottom = window.innerHeight + window.scrollY >= document.documentElement.scrollHeight - 200;
        bottomBtn.style.opacity = nearBottom ? '0' : '1';
        bottomBtn.style.visibility = nearBottom ? 'hidden' : 'visible';
    });
});

然后再页脚的html文件里引入这个js文件

D:\Dev\MyBlog\blog\layouts\partials\footer路径下的footer.html最下面添加下面一行代码

1
<script src="{{ "js/scroll-buttons.js" | relURL }}"></script>

动态背景

引入点线漂浮的动态背景

(1)前往官网particles.js下载Js文件

image-20260128110739756

(2)前往配置界面微调参数,并下载配置Json文件

image-20260128110913745 image-20260128111056767

detect_on设置为window,其余按照自己喜好设置,然后Download。

(3)将上面下载的两个文件放到D:\Dev\MyBlog\blog\assets\background文件夹下

(4)将themes里的custom.html复制到D:\Dev\MyBlog\blog\layouts\partials\footer下,并添加以下代码

 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>

修改默认字体

(1)自行百度谷歌喜欢的字体,然后下载xxx.ttf格式的文件

(2)把字体文件放到D:\Dev\MyBlog\blog\assets\font文件夹下,没有的新建文件夹

image-20260128120620662

(3)修改D:\Dev\MyBlog\blog\layouts\partials\footer路径下的custom.html文件,加入下面代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<style>
  @font-face {
    font-family: '字体名';
    src: url('{{ (resources.Get "font/XXX.ttf").Permalink }}') format('truetype');
  }

  :root {
    --base-font-family: '字体名';
    --code-font-family: '字体名';
  }
</style>

字体名:随便起个,统一即可

XXX.ttf:替换为实际的文件名,带后缀

自动更改文章最后修改时间

之前写文章,如果要显示最后更新时间,需要在front matter上显示定义lastmod,并且每次改完文章后还需要手动改这个时间,现提供自动更改方案

image-20260128145230535

(1)更改配置文件hugo.yaml,在最下面加入下面代码,注意缩进问题

1
2
3
4
5
6
7
8
# 更新时间:优先读取git时间 -> git时间不存在,就读取本地文件修改时间
frontmatter:
  lastmod:
    - :git
    - :fileModTime

# 允许获取Git信息		
enableGitInfo: true

(2)修改主文件夹下.github/workflows/xxx.yaml文件,在运行 hugo -D 命令的step前加入以下配置

1
2
3
4
5
6
7
8
9
jobs:
  deploy:
    steps:
      - name: Git Configuration
        run: |
          git config --global core.quotePath false
          git config --global core.autocrlf false
          git config --global core.safecrlf true
          git config --global core.ignorecase false          
image-20260128145604095

(3)更改文章时,会读取git提交时间,或者本地更改时间。

友链、归档多列显示

修改主文件夹下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;
    }
  }
}

macOS风格代码块

(1) 准备一张macOS代码块的图片, 放到主文件夹下的static/icons文件夹下

macOS-code-header

(2) 将以下代码复制进assets/scss/custom.scss文件中(不存在则自行创建)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
.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;
}

代码块折叠

(1) 准备一张向下展开图片,放到assets/icons目录下

codeMore

(2) 将以下代码复制进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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<style>
    .highlight {
        /* 你可以根据需要调整这个高度 */
        max-height: 400px;
        overflow: hidden;
    }

    .code-show {
        max-height: none !important;
    }

    .code-more-box {
        width: 100%;
        padding-top: 78px;
        background-image: -webkit-gradient(linear, left top, left bottom, from(rgba(255, 255, 255, 0)), to(#fff));
        position: absolute;
        left: 0;
        right: 0;
        bottom: 0;
        z-index: 1;
    }

    .code-more-btn {
        display: block;
        margin: auto;
        width: 44px;
        height: 22px;
        background: #f0f0f5;
        border-top-left-radius: 8px;
        border-top-right-radius: 8px;
        padding-top: 6px;
        cursor: pointer;
    }

    .code-more-img {
        cursor: pointer !important;
        display: block;
        margin: auto;
        width: 22px;
        height: 16px;
    }
</style>

<script>
  function initCodeMoreBox() {
    let codeBlocks = document.querySelectorAll(".highlight");
    if (!codeBlocks) {
      return;
    }
    codeBlocks.forEach(codeBlock => {
      // 校验是否overflow
      if (codeBlock.scrollHeight <= codeBlock.clientHeight) {
        return;
      }
      // 元素初始化
      // codeMoreBox
      let codeMoreBox = document.createElement('div');
      codeMoreBox.classList.add('code-more-box');
      // codeMoreBtn
      let codeMoreBtn = document.createElement('span');
      codeMoreBtn.classList.add('code-more-btn');
      codeMoreBtn.addEventListener('click', () => {
        codeBlock.classList.add('code-show');
        codeMoreBox.style.display = 'none';
        // 触发resize事件,重新计算目录位置
        window.dispatchEvent(new Event('resize'))
      })
      // img
      let img = document.createElement('img');
      img.classList.add('code-more-img');
      img.src = '{{ (resources.Get "icons/codeMore.png").Permalink }}'
      // 元素添加
      codeMoreBtn.appendChild(img);
      codeMoreBox.appendChild(codeMoreBtn);
      codeBlock.appendChild(codeMoreBox)
    })
  }
  
  initCodeMoreBox();
</script>

本文美化功能大多参考网络上的方法和代码,主要参考美化文章,可以在友链里找到。

统计浏览数

本网站使用Vercount作为计数器,具体官方源码为Github

页脚添加总浏览数

更改D:\Dev\MyBlog\blog\layouts\partials\footer下的footer.html,在最后一行先添加JS引用

1
2
<!-- vercount计数 -->
<script defer src="https://events.vercount.one/js"></script>

然后在footer标签内添加下面代码

1
2
3
4
5
6
7
8
9
<!-- ========== 新增的自定义文本区域 ========== -->
<section class="custom-footer-text">
    ...
    <p style="font-size: 0.9em;">
        本站总访问量 <span id="vercount_value_site_pv">Loading...</span> 次
        总访客数 <span id="vercount_value_site_uv">Loading...</span> 人
    </p>
    ...   
</section>

单篇文章显示阅读量

先在D:\Dev\MyBlog\blog\assets\icons下添加下面图标,命名eye.svg

eye

然后更改D:\Dev\MyBlog\blog\layouts\partials\article\components下的footer.html,如果没有就去themes对应文件复制过来,然后在footer标签内添加下面代码

1
2
3
4
5
6
7
8
<!-- 浏览量统计 -->
<section>
    {{ partial "helper/icon" "eye" }}
    <time class="article-time--reading">
        <!-- vercount统计当前页面浏览数的标签 -->
        <span id="vercount_value_page_pv">loading... </span>
    </time>
</section>