默认的 Categories 模板:
自定义后的 类别 模板:
hugo 默认的类别页面是和 标签页面共用一个模板:themes\PaperMod\layouts\_default\terms.html
复制一份到 layouts\_default\terms.html
修改如下:
原来的 tag 从 <ul class="terms-tags">
开始
定义分类元数据
如何给每一个分类设置一个分类描述属性
在 Hugo 中,为每个分类(category)设置描述属性需要在每个分类的索引页面中添加元数据。以下是详细步骤:
创建分类索引页面: 对于每个分类,你需要在 content 目录下创建一个对应的文件夹,并在该文件夹中创建一个 _index.md 文件。例如,如果你有一个名为"Technology"的分类,你需要在 content/categories/technology/_index.md 中添加描述。
添加描述元数据: 在 _index.md 文件的 front matter 中,你可以添加描述属性。例如:
---
title: "Book"
description: "All about the latest book trends and news."
image: "https://daoyuc.oss-cn-hangzhou.aliyuncs.com/imgs/20241119192511.png" # 封面图片路径
alt: "Book Category Cover" # 封面图片的替代文本
caption: "A brief description of the image" # 封面图片的标题或描述
---
This is the book category page.
在这里,description 字段就是分类的描述。我还加了 image 和 alt 属性,用于可选的为类别设定一个 背景图片。 配置模板以显示描述:
遍历分类元数据
在你的列表模板中,你可以通过 .Site.GetPage 函数获取分类页面,并访问其 Params 来获取描述。你可以在分类模板(通常是 layouts/categories/terms.html )中添加以下代码:
<ul>
{{ range .Site.Taxonomies.categories.Alphabetical }}
<li>
<a href="{{ .Page.RelPermalink }}">{{ .Page.Title }}</a>
{{ with .Page.Params.description }}
- <span>{{ . }}</span>
{{ end }}
</li>
{{ end }}
</ul>
这段代码会遍历所有的分类,对于每个分类,它会输出分类的标题和一个链接。如果分类有描述,它也会显示这个描述。
使用 with 进行安全调用: with 关键字在模板中用于安全地调用可能不存在的变量。如果 .Page.Params.description 存在,它将输出描述,否则不会输出任何内容。
应用分类文章数量
由于我选择的类别模板有 css3 实现的纸张叠加效果,所以需要根据类别下的文章数量 循环出堆叠 div (设置最大纸张数量为5)
{{- $count := .Count }}
{{- $maxCount := 5 }}
{{ $actualCount := 0 }}
{{ if lt $count $maxCount }}
{{ $actualCount = $count }}
{{ else }}
{{ $actualCount = $maxCount }}
{{ end }}
...
{{ range seq 1 $actualCount }}
<div class="child"></div>
{{ end }}
完整实现
以下是具体的实现方案:
{{ if eq .Type "categories" }}
<div class="container">
{{- $type := .Type }}
{{- range $key, $value := .Data.Terms.Alphabetical }}
{{- $name := .Name }}
{{- $count := .Count }}
{{- $maxCount := 5 }}
{{ $actualCount := 0 }}
{{ if lt $count $maxCount }}
{{ $actualCount = $count }}
{{ else }}
{{ $actualCount = $maxCount }}
{{ end }}
{{- with $.Site.GetPage (printf "/%s/%s" $type $name) }}
<a href="{{ .Permalink }}">
<div class="card" style="--cards:{{ $count }};">
<div class="child">
<h2>{{ .Name }}</h2>
{{ with .Page.Params.description }}
<span>{{ . }}</span>
{{ end }}
<p>{{ $count }} articles</p>
{{ if .Page.Params.image }}
<img src="{{ .Page.Params.image | relURL }}" alt="{{ .Page.Params.alt }}" />
{{ end }}
</div>
{{ range seq 1 $actualCount }}
<div class="child"></div>
{{ end }}
</div>
</a>
{{- end }}
{{- end }}
</div>
{{ else if eq .Type "tags" }}
<ul class="terms-tags">
{{- $type := .Type }}
{{- range $key, $value := .Data.Terms.Alphabetical }}
{{- $name := .Name }}
{{- $count := .Count }}
{{- with site.GetPage (printf "/%s/%s" $type $name) }}
<li>
<a href="{{ .Permalink }}">{{ .Name }} <sup><strong><sup>{{ $count }}</sup></strong></sup> </a>
</li>
{{- end }}
{{- end }}
</ul>
{{ endif}}
<style>
.container {
max-width: 900px;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(160px, 1fr));
grid-gap: 48px;
margin: 0 auto;
}
.card {
cursor: pointer;
position: relative;
height: 0;
padding-bottom: 120%;
--offset-multiplier: 4px;
transition: -webkit-transform 0.6s ease;
transition: transform 0.6s ease;
transition: transform 0.6s ease, -webkit-transform 0.6s ease;
--translate: 0;
-webkit-transform: translate(var(--translate), var(--translate));
transform: translate(var(--translate), var(--translate));
}
.card:hover {
--offset-multiplier: 6px;
}
.card:hover {
--translate: calc(-1px * (var(--cards) - 1));
transition: -webkit-transform 0.3s ease;
transition: transform 0.3s ease;
transition: transform 0.3s ease, -webkit-transform 0.3s ease;
}
.child {
position: absolute;
width: 100%;
height: 100%;
padding: 0 16px;
box-sizing: border-box;
background: var(--entry);
box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1), 0px -4px 8px rgba(255, 255, 255, 0.8);
border-radius: 6px;
transition: inherit;
--translate: calc(var(--offset) * var(--offset-multiplier));
-webkit-transform: translate(var(--translate), var(--translate));
transform: translate(var(--translate), var(--translate));
z-index: 5;
}
.child p {
bottom: 1rem;
right: 1rem;
position: absolute;
}
.child img {
position: absolute;
left: 0.5rem;
bottom: 0.5rem;
width: 8rem;
z-index: -100;
opacity: 0.5;
}
.child:nth-child(1) {
--offset: 0;
z-index: 4;
}
.child:nth-child(2) {
--offset: 1;
z-index: 3;
}
.child:nth-child(3) {
--offset: 2;
z-index: 2;
}
.child:nth-child(4) {
--offset: 3;
z-index: 1;
}
.child:nth-child(5) {
--offset: 4;
z-index: 0;
}
.child:nth-child(6) {
--offset: 5;
z-index: -1;
}
.child:nth-child(7) {
--offset: 6;
z-index: -2;
}
.child:nth-child(8) {
--offset: 7;
z-index: -3;
}
.child:nth-child(9) {
--offset: 8;
z-index: -4;
}
.child:nth-child(10) {
--offset: 9;
z-index: -5;
}
</style>
如果你也自定义了类别
页面,欢迎在评论区交流 👇
扩展阅读
Terms.Alphabetical 包含哪些属性
在 Hugo 中,Data.Terms.Alphabetical
是一个特殊的变量,它提供了按字母顺序排序的分类法(taxonomy terms)。以下是Data.Terms.Alphabetical
中包含的一些属性:
- .Count:分配给此术语的内容数量。
- .Page:返回此术语的页面引用。
- .Pages:返回包含术语被分配给的
Page
对象的Pages
对象,按分类权重排序。 - .Term:返回术语名称。
- .WeightedPages:返回一个加权页面切片,其中包含术语被分配到的页面,按分类权重排序。
这些属性可以在模板中用来显示和操作分类法数据。例如,你可以使用.Count
来显示每个术语有多少内容与之关联,或者使用.Pages
来列出与特定术语相关联的所有页面。.Term
属性允许你获取当前迭代的术语名称,而.WeightedPages
则提供了一个页面列表,这些页面根据它们与术语的关联权重进行了排序。
增加分类文章字数统计
需要用到上一节提到的 .Pages 对象, 累加 Pages里的每一个 .WordCount
{{ $wordCount := 0 }}
{{ range .Pages }}
{{ $wordCount = add $wordCount .WordCount }}
{{ end }}
...
<p>{{ $count }} 篇</p>
<i>{{ $wordCount }} 字</i>
...
.child p {
color:var(--secondary);
bottom: 2.5rem;
right: 1rem;
font-style: italic;
position: absolute;
}
.child i {
color:var(--secondary);
bottom: 1rem;
right: 1rem;
position: absolute;
}
模板中的变量根据情况重置值
在 Hugo 模板中,你不能直接在 if 语句中给变量赋值。不过,你可以通过定义一个新的变量来实现这个逻辑。
{{ $maxCount := 5 }}
{{ $actualCount := 0 }}
{{ if lt $count $maxCount }}
{{ $actualCount = $count }}
{{ else }}
{{ $actualCount = $maxCount }}
{{ end }}