写在前面:
本篇教程由于作者很懒,部分内容可能是从别处CV过来的,可能与作者实际配置的有细微差别,如果发现有错误的地方导致你无法实现该功能先深表歉意,并且欢迎通过右下角的channel联系我~ 在我看到消息后会第一时间给你我实际的配置内容。
本次装修的环境
操作系统: MacOS Sonoma 14.0
Markdown编辑器: Typora
博客配置编辑器: VS Code
命令行工具: Git、Terminal
Hugo版本: hugo_extended_0.121.2_darwin-universal
Hugo主题: hugo-theme-stack
hugo博客的结构
因为不会写前端,也是第一次搭建hugo博客,在此写下我浅显的理解,如有错误,欢迎批评指正
本文通过 git submodule 方式安装的stack主题,不难发现,初始化后的主题目录结构为
1.
2├── archetypes
3├── assets
4├── config.yaml
5├── content
6├── data
7├── deploy.sh
8├── i18n
9├── img
10├── layouts
11├── public
12├── resources
13├── static
14└── themes
而themes/hugo-theme-stack目录下的主题为
1.
2├── LICENSE
3├── README.md
4├── archetypes
5├── assets
6├── config.yaml
7├── data
8├── debug.sh
9├── exampleSite
10├── go.mod
11├── i18n
12├── images
13├── layouts
14├── netlify.toml
15└── theme.toml
二者有很多相似之处(比如都有assets、layouts等目录),通过前端定位等测试发现,主目录下如果和hugo-theme-stack目录有相同的配置文件,则优先生效主目录下的文件(但似乎也有特殊情况,不过通常是这样的)。所以这里建议在assets创建一个名为scss的文件夹,然后在scss文件夹里创建一个名为custom.scss的文件,用于存放魔改代码。引用下面是页面概览:
整体自定义样式表文件
这里贴出我的整体样式表文件,需要可自取:
1// ~\blog\assets\scss\custom.scss
2
3// 页面基本配色
4:root {
5 // 全局顶部边距
6 --main-top-padding: 30px;
7 // 全局卡片圆角
8 --card-border-radius: 25px;
9 // 标签云卡片圆角
10 --tag-border-radius: 8px;
11 // 卡片间距
12 --section-separation: 40px;
13 // 全局字体大小
14 --article-font-size: 1.8rem;
15 // 行内代码背景色
16 --code-background-color: #f8f8f8;
17 // 行内代码前景色
18 --code-text-color: #e96900;
19 // 暗色模式下样式
20 &[data-scheme="dark"] {
21 // 行内代码背景色
22 --code-background-color: #ff6d1b17;
23 // 行内代码前景色
24 --code-text-color: #e96900;
25 }
26 }
27
28 //------------------------------------------------------
29 // 修复引用块内容窄页面显示问题
30 a {
31 word-break: break-all;
32 }
33
34 code {
35 word-break: break-all;
36 }
37
38 //--------------------------------------------------
39 // 文章封面高度
40 .article-list article .article-image img {
41 width: 100%;
42 height: 200px !important;
43 object-fit: cover;
44
45 @include respond(md) {
46 height: 250px !important;
47 }
48
49 @include respond(xl) {
50 height: 285px !important;
51 }
52 }
53
54 //---------------------------------------------------
55 // 文章内容图片圆角阴影
56 .article-page .main-article .article-content {
57 img {
58 max-width: 96% !important;
59 height: auto !important;
60 border-radius: 8px;
61 }
62 }
63
64 //------------------------------------------------
65 // 文章内容引用块样式
66 .article-content {
67 blockquote {
68 border-left: 6px solid #358b9a1f !important;
69 background: #3a97431f;
70 }
71 }
72 // ---------------------------------------
73 // 代码块基础样式修改
74 .highlight {
75 max-width: 102% !important;
76 background-color: var(--pre-background-color);
77 padding: var(--card-padding);
78 position: relative;
79 border-radius: 20px;
80 margin-left: -7px !important;
81 margin-right: -12px;
82 box-shadow: var(--shadow-l1) !important;
83
84 &:hover {
85 .copyCodeButton {
86 opacity: 1;
87 }
88 }
89
90 // keep Codeblocks LTR
91 [dir="rtl"] & {
92 direction: ltr;
93 }
94
95 pre {
96 margin: initial;
97 padding: 0;
98 margin: 0;
99 width: auto;
100 }
101 }
102
103 // light模式下的代码块样式调整
104 [data-scheme="light"] .article-content .highlight {
105 background-color: #fff9f3;
106 }
107
108 [data-scheme="light"] .chroma {
109 color: #ff6f00;
110 background-color: #fff9f3cc;
111 }
112
113 //-------------------------------------------
114 // 设置选中字体的区域背景颜色
115 //修改选中颜色
116 ::selection {
117 color: #fff;
118 background: #34495e;
119 }
120
121 a {
122 text-decoration: none;
123 color: var(--accent-color);
124
125 &:hover {
126 color: var(--accent-color-darker);
127 }
128
129 &.link {
130 color: #4288b9ad;
131 font-weight: 600;
132 padding: 0 2px;
133 text-decoration: none;
134 cursor: pointer;
135
136 &:hover {
137 text-decoration: underline;
138 }
139 }
140 }
141
142 //-------------------------------------------------
143 //文章封面高度更改
144 .article-list article .article-image img {
145 width: 100%;
146 height: 150px;
147 object-fit: cover;
148
149 @include respond(md) {
150 height: 200px;
151 }
152
153 @include respond(xl) {
154 height: 305px;
155 }
156 }
157
158 //---------------------------------------------------
159 // 全局页面布局间距调整
160 .main-container {
161 min-height: 100vh;
162 align-items: flex-start;
163 padding: 0 15px;
164 gap: var(--section-separation);
165 padding-top: var(--main-top-padding);
166
167 @include respond(md) {
168 padding: 0 37px;
169 }
170 }
171
172 //--------------------------------------------------
173 //页面三栏宽度调整
174 .container {
175 margin-left: auto;
176 margin-right: auto;
177
178 .left-sidebar {
179 order: -3;
180 max-width: var(--left-sidebar-max-width);
181 }
182
183 .right-sidebar {
184 order: -1;
185 max-width: var(--right-sidebar-max-width);
186
187 /// Display right sidebar when min-width: lg
188 @include respond(lg) {
189 display: flex;
190 }
191 }
192
193 &.extended {
194 @include respond(md) {
195 max-width: 1024px;
196 --left-sidebar-max-width: 25%;
197 --right-sidebar-max-width: 22% !important;
198 }
199
200 @include respond(lg) {
201 max-width: 1280px;
202 --left-sidebar-max-width: 20%;
203 --right-sidebar-max-width: 30%;
204 }
205
206 @include respond(xl) {
207 max-width: 1453px; //1536px;
208 --left-sidebar-max-width: 15%;
209 --right-sidebar-max-width: 25%;
210 }
211 }
212
213 &.compact {
214 @include respond(md) {
215 --left-sidebar-max-width: 25%;
216 max-width: 768px;
217 }
218
219 @include respond(lg) {
220 max-width: 1024px;
221 --left-sidebar-max-width: 20%;
222 }
223
224 @include respond(xl) {
225 max-width: 1280px;
226 }
227 }
228 }
229
230 //-------------------------------------------------------
231 //全局页面小图片样式微调
232 .article-list--compact article .article-image img {
233 width: var(--image-size);
234 height: var(--image-size);
235 object-fit: cover;
236 border-radius: 17%;
237 }
238
239 //----------------------------------------------------
240 //固定代码块的高度
241 .article-content {
242 .highlight {
243 padding: var(--card-padding);
244 pre {
245 width: auto;
246 max-height: 20em;
247 }
248 }
249 }
250
251// --------------------------------
252// 菜单栏样式
253// 下拉菜单改圆角样式
254.menu {
255 padding-left: 0;
256 list-style: none;
257 flex-direction: column;
258 overflow-x: hidden;
259 overflow-y: scroll;
260 flex-grow: 1;
261 font-size: 1.6rem;
262 background-color: var(--card-background);
263
264 box-shadow: var(--shadow-l2); //改个阴影
265 display: none;
266 margin: 0; //改为0
267 border-radius: 10px; //加个圆角
268 padding: 30px 30px;
269
270 @include respond(xl) {
271 padding: 15px 0;
272 }
273
274 &,
275 .menu-bottom-section {
276 gap: 30px;
277
278 @include respond(xl) {
279 gap: 25px;
280 }
281 }
282
283 &.show {
284 display: flex;
285 }
286
287 @include respond(md) {
288 align-items: flex-end;
289 display: flex;
290 background-color: transparent;
291 padding: 0;
292 box-shadow: none;
293 margin: 0;
294 }
295
296 li {
297 position: relative;
298 vertical-align: middle;
299 padding: 0;
300
301 @include respond(md) {
302 width: 100%;
303 }
304
305 svg {
306 stroke-width: 1.33;
307
308 width: 20px;
309 height: 20px;
310 }
311
312 a {
313 height: 100%;
314 display: inline-flex;
315 align-items: center;
316 color: var(--body-text-color);
317 gap: var(--menu-icon-separation);
318 }
319
320 span {
321 flex: 1;
322 }
323
324 &.current {
325 a {
326 color: var(--accent-color);
327 font-weight: bold;
328 }
329 }
330 }
331 }
332
333 // ~\blog\assets\scss\custom.scss
334
335//------------------------------------------------
336//将滚动条修改为圆角样式
337//菜单滚动条美化
338.menu::-webkit-scrollbar {
339 display: none;
340 }
341
342 // 全局滚动条美化
343 html {
344 ::-webkit-scrollbar {
345 width: 20px;
346 }
347
348 ::-webkit-scrollbar-track {
349 background-color: transparent;
350 }
351
352 ::-webkit-scrollbar-thumb {
353 background-color: #d6dee1;
354 border-radius: 20px;
355 border: 6px solid transparent;
356 background-clip: content-box;
357 }
358
359 ::-webkit-scrollbar-thumb:hover {
360 background-color: #a8bbbf;
361 }
362 }
363
364//--------------------------------------------------
365//归档页面双栏
366/* 归档页面两栏 */
367@media (min-width: 1024px) {
368 .article-list--compact {
369 display: grid;
370 grid-template-columns: 1fr 1fr;
371 background: none;
372 box-shadow: none;
373 gap: 1rem;
374
375 article {
376 background: var(--card-background);
377 border: none;
378 box-shadow: var(--shadow-l2);
379 margin-bottom: 8px;
380 border-radius: 16px;
381 }
382 }
383 }
384
385//--------------------------------------------------
386//链接三栏
387@media (min-width: 1024px) {
388 .article-list--compact.links {
389 display: grid;
390 grid-template-columns: 1fr 1fr 1fr; //三个1fr即为三栏,两个1fr则为双栏,以此类推即可.
391 background: none;
392 box-shadow: none;
393 gap: 1rem;
394
395 article {
396 background: var(--card-background);
397 border: none;
398 box-shadow: var(--shadow-l2);
399 margin-bottom: 8px;
400 border-radius: var(--card-border-radius);
401
402 &:nth-child(odd) {
403 margin-right: 8px;
404 }
405 }
406 }
407 }
408
409
410//---------------------------------------------------------
411//首页欢迎板块样式
412.welcome {
413 color: var(--card-text-color-main);
414 background: var(--card-background);
415 box-shadow: var(--shadow-l2);
416 border-radius: 30px;
417 display: inline-block;
418 }
419
420 // 👋emoji实现摆动效果
421 .shake {
422 display: inline-block;
423 animation: shake 1s;
424 animation-duration: 1s;
425 animation-timing-function: ease;
426 animation-delay: 0s;
427 animation-iteration-count: 1;
428 animation-direction: normal;
429 animation-fill-mode: none;
430 animation-play-state: running;
431 animation-name: shake;
432 animation-timeline: auto;
433 animation-range-start: normal;
434 animation-range-end: normal;
435 animation-delay: 2s;
436 @keyframes shake {
437 0% {
438 transform: rotate(0);
439 }
440 25% {
441 transform: rotate(45deg) scale(1.2);
442 }
443 50% {
444 transform: rotate(0) scale(1.2);
445 }
446 75% {
447 transform: rotate(45deg) scale(1.2);
448 }
449 100% {
450 transform: rotate(0);
451 }
452 }
453 }
454 // 实现字符跳动动画
455 .jump-text1 {
456 display: inline-block;
457 animation: jump 0.5s 1;
458 }
459
460 .jump-text2 {
461 display: inline-block;
462 animation: jump 0.5s 1;
463 animation-delay: 0.1s;
464 }
465
466 .jump-text3 {
467 display: inline-block;
468 animation: jump 0.5s 1;
469 animation-delay: 0.2s;
470 }
471
472 .jump-text4 {
473 display: inline-block;
474 animation: jump 0.5s 1;
475 animation-delay: 0.3s;
476 }
477
478 .jump-text5 {
479 display: inline-block;
480 animation: jump 0.5s 1;
481 animation-delay: 0.4s;
482 }
483
484 .jump-text6 {
485 display: inline-block;
486 animation: jump 0.5s 1;
487 animation-delay: 0.5s;
488 }
489
490 .jump-text7 {
491 display: inline-block;
492 animation: jump 0.5s 1;
493 animation-delay: 0.6s;
494 }
495
496 .jump-text8 {
497 display: inline-block;
498 animation: jump 0.5s 1;
499 animation-delay: 0.7s;
500 }
501
502 .jump-text9 {
503 display: inline-block;
504 animation: jump 0.5s 1;
505 animation-delay: 0.9s;
506 }
507
508 @keyframes jump {
509 0% {
510 transform: translateY(0);
511 }
512 50% {
513 transform: translateY(-20px);
514 }
515 100% {
516 transform: translateY(0);
517 }
518 }
519
520//--------------------------------------------------
521//引入左上角返回按钮
522.back-home {
523 background: var(--card-background);
524 border-radius: var(--tag-border-radius);
525 color: var(--card-text-color-tertiary);
526 margin-right: 0.1rem;
527 margin-top: 24px;
528 display: inline-flex;
529 align-items: center;
530 font-size: 1.4rem;
531 text-transform: uppercase;
532 padding: 10px 20px 10px 15px;
533 transition: box-shadow 0.3s ease;
534 box-shadow: var(--shadow-l3);
535
536 &:hover {
537 box-shadow: var(--shadow-l2);
538 }
539
540 svg {
541 margin-right: 5px;
542 width: 20px;
543 height: 20px;
544 }
545
546 span {
547 font-weight: 500;
548 white-space: nowrap;
549 }
550 }
551
552 .main-container .right-sidebar {
553 order: 2;
554 max-width: var(--right-sidebar-max-width);
555
556 /// Display right sidebar when min-width: lg
557 @include respond(lg) {
558 display: flex;
559 }
560 }
561
562 main.main {
563 order: 1;
564 min-width: 0;
565 max-width: 100%;
566 flex-grow: 1;
567 display: flex;
568 flex-direction: column;
569 gap: var(--section-separation);
570
571 @include respond(md) {
572 padding-top: var(--main-top-padding);
573 }
574 }
575
576//----------------------------------------------------------
577//为代码块顶部添加macos样式
578.article-content {
579 .highlight:before {
580 content: "";
581 display: block;
582 background: url(/img/code-header.svg);
583 height: 32px;
584 width: 100%;
585 background-size: 57px;
586 background-repeat: no-repeat;
587 margin-bottom: 5px;
588 background-position: -1px 2px;
589 }
590 }
591
592.tagCloud {
593 .tagCloud-count {
594 color: var(--body-text-color);
595 }
596}
597
598.copyCodeButton {
599 border-radius: var(--category-border-radius);
600}
601
602code {
603 border-radius: var(--category-border-radius);
604}
605
606.article-category {
607 display: flex;
608 flex-wrap: wrap;
609 gap: 10px;
610
611 a {
612 background: var(--card-background);
613 box-shadow: var(--shadow-l1);
614 border-radius: var(--category-border-radius);
615 padding: 8px 20px;
616 color: var(--card-text-color-main);
617 font-size: 1.4rem;
618 transition: box-shadow 0.3s ease;
619
620 &:hover {
621 box-shadow: var(--shadow-l2);
622 }
623 }
624}
625
626/* Category widget */
627.category {
628 .category-label {
629 display: flex;
630 flex-wrap: wrap;
631 gap: 10px;
632
633 a {
634 border-left: 6px solid;
635 background: var(--card-background);
636 box-shadow: var(--shadow-l1);
637 border-radius: var(--category-border-radius);
638 padding: 12px 20px;
639 color: var(--card-text-color-main);
640 font-size: 1.5rem;
641 transition: box-shadow 0.3s ease;
642
643 &:hover {
644 box-shadow: var(--shadow-l2);
645 }
646 }
647 }
648 .category-count {
649 color: var(--body-text-color);
650 }
651}
652
653.running-time {
654 color: var(--card-text-color-secondary);
655 font-weight: normal;
656
657 .running-days {
658 font-weight:bold;
659 color: var(--emphasize-text-color);
660 }
661}
662
663.totalcount {
664 color: var(--card-text-color-secondary);
665 font-weight: normal;
666 margin-bottom: 5px;
667 }
668
669code {
670 border-radius: var(--tag-border-radius);
671 font-size: 14px; // Add font size setting for code block
672 font-family: var(--code-font-family);
673}
674
675.article-subtitle {
676 margin-top: -5px;
677 font-size: 1.5rem;
678
679 @include respond(md) {
680 font-size: 1.6rem;
681 }
682}
683
684/*头像旋转动画*/
685.sidebar header .site-avatar .site-logo {
686 transition: transform 1.65s ease-in-out; //旋转时间
687
688}
689
690.sidebar header .site-avatar .site-logo:hover {
691 transform: rotate(360deg); //旋转角度为360度
692}
693
694/*社交菜单居中*/
695.social-menu svg {
696 gap: 15px;
697 justify-content: center;
698 width: 30px;
699 height: 25px; //社交菜单大小
700 stroke: var(--body-text-color);
701 stroke-width: 1.33;
702}
703
704/*页面加载动画部分*/
705#loading-box .loading-left-bg,
706#loading-box .loading-right-bg {
707 position: fixed;
708 z-index: 1000;
709 width: 50%;
710 height: 100%;
711 // 我在这里小改了一下颜色,
712 background-color: #b1c0c7;
713 transition: all 0.5s;
714}
715
716#loading-box .loading-right-bg {
717 right: 0;
718}
719
720#loading-box>.spinner-box {
721 position: fixed;
722 z-index: 1001;
723 display: flex;
724 justify-content: center;
725 align-items: center;
726 width: 100%;
727 height: 100vh;
728}
729
730#loading-box .spinner-box .configure-border-1 {
731 position: absolute;
732 padding: 3px;
733 width: 115px;
734 height: 115px;
735 background: #ffab91;
736 animation: configure-clockwise 3s ease-in-out 0s infinite alternate;
737}
738
739#loading-box .spinner-box .configure-border-2 {
740 left: -115px;
741 padding: 3px;
742 width: 115px;
743 height: 115px;
744 background: rgb(63, 249, 220);
745 transform: rotate(45deg);
746 animation: configure-xclockwise 3s ease-in-out 0s infinite alternate;
747}
748
749#loading-box .spinner-box .loading-word {
750 position: absolute;
751 color: #ffffff;
752 // 我在这里小改了一下文字大小和字体,注意!
753 font-size: 1.8rem;
754 font-family: 'Zhi Mang Xing', cursive;
755}
756
757#loading-box .spinner-box .configure-core {
758 width: 100%;
759 height: 100%;
760 background-color: #37474f;
761}
762
763div.loaded div.loading-left-bg {
764 transform: translate(-100%, 0);
765}
766
767div.loaded div.loading-right-bg {
768 transform: translate(100%, 0);
769}
770
771div.loaded div.spinner-box {
772 // 你可以把这个注释掉,这样就能一直看那个动画的效果了!
773 display: none !important;
774}
775
776@keyframes configure-clockwise {
777 0% {
778 transform: rotate(0);
779 }
780
781 25% {
782 transform: rotate(90deg);
783 }
784
785 50% {
786 transform: rotate(180deg);
787 }
788
789 75% {
790 transform: rotate(270deg);
791 }
792
793 100% {
794 transform: rotate(360deg);
795 }
796}
797
798@keyframes configure-xclockwise {
799 0% {
800 transform: rotate(45deg);
801 }
802
803 25% {
804 transform: rotate(-45deg);
805 }
806
807 50% {
808 transform: rotate(-135deg);
809 }
810
811 75% {
812 transform: rotate(-225deg);
813 }
814
815 100% {
816 transform: rotate(-315deg);
817 }
818}
动态纹理:蛛网、花瓣
蛛网特效在 /layouts/_default/baseof.html中间插入以下代码
<script type="text/javascript" src="https://demo.hellozwh.com/source/canvas-nest.min.js"></script>
花瓣特效只需要将src的地址换为https://cdn.jsdelivr.net/gh/Ukenn2112/UkennWeb@3.0/index/web.js
即可
修改主页侧边栏样式
修改头像及简介
将自己的头像存放在/assets/img/
目录下,之后打开主目录下的config.yaml文件,搜索sidebar,
subtitle代表简介
avatar的src路径为头像路径
改为如下代码
(local最好设置为true,不然头像修改不成功)
1sidebar:
2 compact: false
3 emoji: 🍥
4 subtitle: 行者不必言深,孤独本是常态。
5 avatar:
6 enabled: true
7 local: true
8 src: /img/avatar.jpg
修改社交栏
依然是在主目录下的config.yaml文件进行修改,搜索social,需要添加一个社交按钮则仿照原来的添加如下代码:
1- identifier: github
2 name: GitHub
3 url: https://github.com/Bla1n
4 params:
5 newTab: true
6 icon: brand-github
icon图标存储目录为~/blog/themes/hugo-theme-stack/assets/icons
修改栏目
icon存储目录同上,但要修改栏目名称则需要前往/content/page
目录
打开对应栏目文件夹,修改index.md文件
头像旋转😵💫
在assets\scss\custom.scss路径下添加如下代码
1/* 头像旋转 */
2.home .home-profile .home-avatar img {
3 width: 5rem;
4
5 /* 设置循环动画
6 [animation:
7 (play)动画名称
8 (2s)动画播放时长单位秒或微秒
9 (ease-out)动画播放的速度曲线为以低速结束
10 (1s)等待1秒然后开始动画
11 (1)动画播放次数(infinite为循环播放) ]*/
12
13 /* 鼠标经过头像旋转360度 */
14 -webkit-transition: -webkit-transform 1.0s ease-out;
15 -moz-transition: -moz-transform 1.0s ease-out;
16 transition: transform 1.0s ease-out;
17 &:hover {
18 /* 鼠标经过停止头像旋转
19 -webkit-animation-play-state:paused;
20 animation-play-state:paused;*/
21
22 /* 鼠标经过头像旋转360度 */
23 -webkit-transform: rotateZ(360deg);
24 -moz-transform: rotateZ(360deg);
25 transform: rotateZ(360deg);
26 }
27}
文章添加音乐
单首音乐效果如下
音乐列表效果如下
直接在文章中插入如下代码:
1单曲:(autoplay参数为是否自动播放音乐)
2{{< music server="netease" type="song" id="1372188635" autoplay="false" >}}
3列表:
4{{< music auto="https://music.163.com/playlist?id=6843891038">}}
修改底栏
博客运行时长
在layouts/partials/footer/custom.html
里添加以下JS代码,其中s1
是网站创建日期。代码参考自这里
,加上了小时和分钟的计算。
1<!-- Add blog running time -->
2<script>
3 let s1 = '2023-3-18'; //website start date
4 s1 = new Date(s1.replace(/-/g, "/"));
5 let s2 = new Date();
6 let timeDifference = s2.getTime() - s1.getTime();
7
8 let days = Math.floor(timeDifference / (1000 * 60 * 60 * 24));
9 let hours = Math.floor((timeDifference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
10 let minutes = Math.floor((timeDifference % (1000 * 60 * 60)) / (1000 * 60));
11
12 let result = days + "天" + hours + "小时" + minutes + "分钟";
13 document.getElementById('runningdays').innerHTML = result;
14</script>
再在layouts/partials/footer/footer.html
里添加以下代码:
1<!-- Add blog running time -->
2<section class="running-time">
3本博客已稳定运行
4<span id="runningdays" class="running-days"></span>
5</section>
在assets/scss/partials/footer.scss
里添加风格样式,这里单独把计时的部分加粗,并改了颜色。
1.running-time {
2 color: var(--card-text-color-secondary);
3 font-weight: normal;
4
5 .running-days {
6 font-weight:bold;
7 color: var(--emphasize-text-color);
8 }
9}
上面的计时部分设置成var(--emphasize-text-color)
,这样能比较方便地在assets/scss/variables.scss
里设置暗色模式的颜色
1 --accent-color-text: #fff;
2 --body-text-color: #b0b0b0;
3 --emphasize-text-color: #9e8f9f; // Add emphasize font color
4
5 &[data-scheme="dark"] {
6 --emphasize-text-color: #d5cfc4; // Add emphasize font color for dark scheme
7 }
文字统计
在layouts/partials/footer/footer.html
里增加以下代码,其中文章篇数统计参考了这篇
,字数统计的展示方式参考了小球飞鱼的博客
。
1<!-- Add total page and word count time -->
2<section class="totalcount">
3 {{$scratch := newScratch}}
4 {{ range (where .Site.Pages "Kind" "page" )}}
5 {{$scratch.Add "total" .WordCount}}
6 {{ end }}
7 发表了{{ len (where .Site.RegularPages "Section" "post") }}篇文章 ·
8 总计{{ div ($scratch.Get "total") 1000.0 | lang.FormatNumber 2 }}k字
9</section>
在assets/scss/partials/footer.scss
里修改风格:
1.totalcount {
2 color: var(--card-text-color-secondary);
3 font-weight: normal;
4 margin-bottom: 5px;
5 }
返回顶部按钮
在阅读长文章时,如果想返回顶部没有快捷按钮则是很不方便的,所以添加此按钮
在/layouts/partials/footer/custom.html
里面添加如下代码
1<!--返回顶部按钮 -->
2<a href="#" id="back-to-top" title="返回顶部"></a>
3
4<!--返回顶部CSS -->
5<style>
6 #back-to-top {
7 display: none;
8 position: fixed;
9 bottom: 20px;
10 right: 55px;
11 width: 55px;
12 height: 55px;
13 border-radius: 7px;
14 background-color: rgba(64, 158, 255, 0.5);
15 box-shadow: var(--shadow-l2);
16 font-size: 30px;
17 text-align: center;
18 line-height: 50px;
19 cursor: pointer;
20 }
21
22 #back-to-top:before {
23 content: ' ';
24 display: inline-block;
25 position: relative;
26 top: 0;
27 transform: rotate(135deg);
28 height: 10px;
29 width: 10px;
30 border-width: 0 0 2px 2px;
31 border-color: var(--back-to-top-color);
32 border-style: solid;
33 }
34
35 #back-to-top:hover:before {
36 border-color: #2674e0;
37 }
38
39 /* 在屏幕宽度小于 768 像素时,钮位置调整 */
40 @media screen and (max-width: 768px) {
41 #back-to-top {
42 bottom: 20px;
43 right: 20px;
44 width: 40px;
45 height: 40px;
46 font-size: 10px;
47 }
48 }
49
50 /* 在屏幕宽度大于等于 1024 像素时,按钮位置调整 */
51 @media screen and (min-width: 1024px) {
52 #back-to-top {
53 bottom: 20px;
54 right: 40px;
55 }
56 }
57
58 /* 在屏幕宽度大于等于 1280 像素时,按钮位置调整 */
59 @media screen and (min-width: 1280px) {
60 #back-to-top {
61 bottom: 20px;
62 right: 55px;
63 }
64 }
65
66 /* 目录显示时,隐藏按钮 */
67 @media screen and (min-width: 1536px) {
68 #back-to-top {
69 visibility: hidden;
70 }
71 }
72</style>
73
74<!--返回顶部JS -->
75<script>
76 function backToTop() {
77 document.documentElement.scrollIntoView({
78 behavior: 'smooth',
79 })
80 }
81
82 window.onload = function () {
83 let scrollTop =
84 this.document.documentElement.scrollTop || this.document.body.scrollTop
85 let totopBtn = this.document.getElementById('back-to-top')
86 if (scrollTop > 0) {
87 totopBtn.style.display = 'inline'
88 } else {
89 totopBtn.style.display = 'none'
90 }
91 }
92
93 window.onscroll = function () {
94 let scrollTop =
95 this.document.documentElement.scrollTop || this.document.body.scrollTop
96 let totopBtn = this.document.getElementById('back-to-top')
97 if (scrollTop < 200) {
98 totopBtn.style.display = 'none'
99 } else {
100 totopBtn.style.display = 'inline'
101 totopBtn.addEventListener('click', backToTop, false)
102 }
103 }
104</script>
在layouts/partials/footer/components/script.html
里可以修改按钮的颜色:
1#back-to-top {
2 background-color: var(--body-background);
3 }
4
5 #back-to-top:hover:before {
6 border-color: var(--accent-color);
7 }
去除归档页初始滤镜
具体可看此issue
用/* */
注释掉themes/hugo-theme-stack/assets/ts/main.ts
中的
1import { getColor } from 'ts/color';
2
3和
4
5 const articleTile = document.querySelector('.article-list--tile');
6 if (articleTile) {
7 let observer = new IntersectionObserver(async (entries, observer) => {
8 entries.forEach(entry => {
9 if (!entry.isIntersecting) return;
10 observer.unobserve(entry.target);
11
12 const articles = entry.target.querySelectorAll('article.has-image');
13 articles.forEach(async articles => {
14 const image = articles.querySelector('img'),
15 imageURL = image.src,
16 key = image.getAttribute('data-key'),
17 hash = image.getAttribute('data-hash'),
18 articleDetails: HTMLDivElement = articles.querySelector('.article-details');
19
20 const colors = await getColor(key, hash, imageURL);
21
22 articleDetails.style.background = `
23 linear-gradient(0deg,
24 rgba(${colors.DarkMuted.rgb[0]}, ${colors.DarkMuted.rgb[1]}, ${colors.DarkMuted.rgb[2]}, 0.5) 0%,
25 rgba(${colors.Vibrant.rgb[0]}, ${colors.Vibrant.rgb[1]}, ${colors.Vibrant.rgb[2]}, 0.75) 100%)`;
26 })
27 })
28 });
29
30 observer.observe(articleTile)
31 }
以及themes/hugo-theme-stack/layouts/partials/footer/components/script.html
中的
1{{- partial "helper/external" (dict "Context" . "Namespace" "Vibrant") -}}
添加相册功能
-
日常更新把图片(需按格式:日期 + 空格 + 图片名)丢到
/static/photos/
中即可。 -
/content/page/photos/index.md
创建一个 md,好让 Hugo 生成页面1title: 相册 | photos 2layout: "photos" 3slug: "photos" 4menu: 5 main: 6 weight: -50 7 params: 8 icon: photos 9comments: false
-
创建
/layouts/_default/photos.html
1{{ define "main" }} 2<div class="button-group"> 3 <button class="filter-button" data-category="-"> All </button> 4 <button class="filter-button" data-category="日常">#日常</button> 5 <button class="filter-button" data-category="风景">#风景</button> 6 <button class="filter-button" data-category="狗哥">#狗哥</button> 7 <button class="filter-button" data-category="赛">#赛</button> 8</div> 9<div class="gallery-photos page"> 10 {{ range (sort (readDir "./static/photos") "Name" "desc")}} 11 {{ if ( .Name | findRE "\\.(gif|jpg|jpeg|tiff|png|bmp|webp|avif|jxl)") }} 12 <div class="gallery-photo"> 13 <img class="photo-img" loading='lazy' decoding="async" src="/photos/{{ .Name }}" alt="{{ .Name }}" /> 14 <span class="photo-title">{{ .Name | replaceRE "^[0-9 -]+(.*)[.].*" "$1"}}</span><span class="photo-time">{{ .Name | replaceRE "^([0-9-]+).*[.].*" "$1" }}</span> 15 </div> 16 {{ end }} 17 {{ end }} 18</div> 19 20<style> 21.gallery-photos{width:100%;} 22.gallery-photo{width:24.9%;position: relative;visibility: hidden;overflow: hidden;} 23.gallery-photo.visible{visibility: visible;animation: fadeIn 2s;} 24.gallery-photo img{ 25 display: block; 26 width:100%; 27 border-radius:20px; 28 padding:4px; 29 animation: fadeIn 1s; 30 cursor: pointer; 31 transition: all .4s ease-in-out; 32} 33.gallery-photo span.photo-title,.gallery-photo span.photo-time{ 34 background: rgba(0, 0, 0, 0.3); 35 padding:0px 8px; 36 font-size:0.9rem; 37 color: #fff; 38 display:none; 39 animation: fadeIn 1s; 40} 41.gallery-photo span.photo-title{ 42 position:absolute; 43 bottom:4px; 44 left:4px; 45 border-radius:10px; 46 background-color: #a3dfff; 47 color: #000000; 48 font-size:1.2rem 49} 50.gallery-photo span.photo-time{position:absolute;top:4px;left:4px;font-size:0.8rem;} 51.gallery-photo:hover span.photo-title{display:block;} 52.gallery-photo:hover img{transform: scale(1.1);} 53.button-group { 54 display: flex; 55 flex-direction: row; 56 gap: 18px; 57 justify-content: center; 58 } 59 .filter-button { 60 padding: 8px 8px; 61 width: auto; 62 background-color: var(--card-background); 63 color: #57bd8f; 64 border: none; 65 border-radius: 5px; 66 cursor: pointer; 67 transition: background-color 0.3s ease; 68 } 69 .filter-button:hover { 70 color: #5e88f7; 71 } 72 .selected-button { 73 background-color: #CCE8CF; 74 color: #000000; 75 /* 选中项的颜色 */ 76 } 77@media screen and (max-width: 1280px) { 78 .gallery-photo{width:33.3%;} 79} 80@media screen and (max-width: 860px) { 81 .gallery-photo{width:49.9%;} 82} 83@media (max-width: 683px){ 84 .photo-time{display: none;} 85} 86@keyframes fadeIn{ 87 0% {opacity: 0;} 88 100% {opacity: 1;} 89} 90</style> 91<script src="https://immmmm.com/waterfall.min.js"></script> 92<script src="https://immmmm.com/imgStatus.min.js"></script> 93<script> 94document.addEventListener('DOMContentLoaded', () => { 95 imgStatus.watch('.photo-img', function(imgs) { 96 if(imgs.isDone()){ 97 waterfall('.gallery-photos'); 98 let pagePhoto = document.querySelectorAll('.gallery-photo'); 99 for(var i=0;i < pagePhoto.length;i++){pagePhoto[i].className += " visible"}; 100 } 101 }); 102 window.addEventListener('resize', function () { 103 waterfall('.gallery-photos'); 104 }); 105}); 106</script> 107<script src="https://immmmm.com/view-image.js"></script> 108<script src="https://immmmm.com/lately.min.js"></script> 109<script> 110 window.Lately && Lately.init({ target: '.photo-time'}); 111 window.ViewImage && ViewImage.init('.gallery-photo img') 112</script> 113<script> 114 document.addEventListener('DOMContentLoaded', () => { 115 const filterButtons = document.querySelectorAll('.filter-button'); 116 const galleryPhotos = document.querySelectorAll('.gallery-photo'); 117 filterButtons.forEach(button => { 118 button.addEventListener('click', () => { 119 const category = button.getAttribute('data-category'); 120 // 隐藏所有照片 121 galleryPhotos.forEach(photo => { 122 photo.style.visibility = 'hidden'; 123 }); 124 // 显示符合特定词语的照片 125 galleryPhotos.forEach(photo => { 126 const imageName = photo.querySelector('.photo-img').getAttribute('alt'); 127 if (imageName.includes(category)) { 128 photo.style.visibility = 'visible'; 129 } 130 }); 131 // 移除所有按钮的选中状态 132 filterButtons.forEach(btn => { 133 btn.classList.remove('selected-button'); 134 }); 135 // 将当前点击的按钮标记为选中状态 136 button.classList.add('selected-button'); 137 }); 138 }); 139}); 140</script> 141{{ end }}
这段代码同时添加了分类功能,只需在图片文件名中含有相应关键字即可分类
添加右下角联系小气泡按钮
效果图为:
请参考这两篇文章,两位博主写的非常详细,不难配置,在此不在赘述(懒了,hhh)