Featured image of post Hugo-Stack主题装饰

Hugo-Stack主题装饰

基本原理

  1. Hugo的stack主题提供了自定义样式的接口,主要在layouts/partials/footer/custom.htmlassets/scss/custom.scss
  2. 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风格图标

  1. 准备一张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>
  1. 将以下代码复制进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);
        });
});

可视化加载条

  1. 下载【文件】,并将压缩包中的topbar.min.js移动至assets/js中。

  2. 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),然后放入模版文件中即可实现在网页上加载。

以下提供了几个示例,供您参考。

首页欢迎栏

  1. /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>
<!-- 首页欢迎字幅 -->
  1. /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: 你的组件名
网站总访客数:Loading

使用 Hugo 构建
主题 StackJimmy 设计