Ananke主题美化—重写部分代码
盖力维
如果你部署了 Ananke 主题,就会发现它似乎只能在 Demo 上展现出好看的一面,在你自己的网站上怎么看怎么难看。
所以我们要动手改造它,重写(覆盖)部分模板代码并添加 CSS ,使得我们可以配置出符合自己审美的主题效果。
本文记录了我美化此网站的过程,是一种记录也是一种分享。
Ananke主题美化—重写部分代码
前提准备
为了便于用自己的配置和代码覆盖 Ananke 主题自带的内容,我复制 blog\themes\ananke\layouts 到 blog\layouts ,复制 server\blog\themes\ananke\assets 到 blog\assets\ananke 。
单文章页
文章内容宽度太窄了,右侧的 相关内容 区域占去了一大块,而我用不上 相关内容 里的 目录 功能,所以我打算把它放在文章底部,也就是标签下方、评论框上方。
将 blog\layouts\_default\single.html 改为:
1{{ define "header" }}
2 {{/* We can override any block in the baseof file by defining it in the template */}}
3 {{ partials.Include "page-header.html" . }}
4{{ end }}
5
6{{ define "main" }}
7 {{ $page := .}}
8 {{ $section := .Site.GetPage "section" .Section }}
9 <article class="flex-l mw8 center ph3 flex-wrap">
10 <header class="mt4 w-100">
11 <aside class="instapaper_ignoref b helvetica tracked ttu">
12 {{ .CurrentSection.Title }}
13 </aside>
14 {{- partials.IncludeCached "social/share.html" . . -}}
15 <h1 class="f1 athelas mt3 mb1">
16 {{- .Title -}}
17 </h1>
18 {{ with .Params.author | compare.Default .Site.Params.author }}
19 <p class="tracked">
20 {{- if compare.Eq $page.Language "de" "en" "es" "fr" "it" "no" "pt" -}}
21 {{- lang.Translate "by" -}}
22 {{ end -}} <strong>
23 {{- if reflect.IsSlice . -}}
24 {{ collections.Delimit . ", " | transform.Markdownify }}
25 {{- else -}}
26 {{ . | transform.Markdownify }}
27 {{- end -}}
28 </strong>
29 </p>
30 {{ end }}
31 {{ if not .Date.IsZero }}
32 <time class="f6 mv4 dib tracked" {{ fmt.Printf `datetime="%s"` (.Date.Format "2006-01-02T15:04:05Z07:00") | safe.HTMLAttr }}>
33 {{- .Date | time.Format (compare.Default "January 2, 2006" .Site.Params.date_format) -}}
34 </time>
35 {{ end }}
36 {{ if (or (compare.Eq (.Param "show_reading_time") true) (compare.Eq $section.Params.show_reading_time true) )}}
37 <span class="f6 mv4 dib tracked"> - {{ lang.Translate "readingTime" .ReadingTime }} </span>
38 <span class="f6 mv4 dib tracked"> - {{ lang.Translate "wordCount" .WordCount }} </span>
39 {{ end }}
40 </header>
41
42 <div class="nested-copy-line-height lh-copy w-100 f4 nested-links {{ $.Param "text_color" | compare.Default "mid-gray" }}">
43 {{- .Content -}}
44
45 {{/* 标签 */}}
46 {{- partials.Include "tags.html" . -}}
47
48 {{/* 相关内容,原来的 aside 移到这里 */}}
49 <div class="mt6">
50 {{- partials.Include "menu-contextual.html" . -}}
51 </div>
52
53 {{/* 评论框 */}}
54 <div class="mt6 instapaper_ignoref">
55 {{ if .Site.Config.Services.Disqus.Shortname }}
56 {{ template "_internal/disqus.html" . }}
57 {{ end }}
58 {{ if .Site.Params.commentoEnable }}
59 {{- partials.Include "commento.html" . -}}
60 {{ end }}
61 </div>
62 </div>
63 </article>
64{{ end }}
同时,我对 Hugo 本身的”相关文章“计算规则感到匪夷所思,因此我在 Font Matter 里添加一个 related 参数来手动指定”相关文章“,若无此参数则应用自动计算规则。
将 blog\layouts\partials\menu-contextual.html 改为:
1{{/* Use Hugo's native Table of contents feature. You must set `toc: true` in
2your parameters for this to show. https://gohugo.io/content-management/toc/ */}}
3{{- if .Params.toc -}}
4<div
5 class="bg-light-gray pa3 nested-list-reset nested-copy-line-height nested-links"
6>
7 <p class="f5 b mb3">{{ lang.Translate "whatsInThis" . }}</p>
8 {{ .TableOfContents }}
9</div>
10{{- end -}} {{/* Custom related content from front matter */}} {{ $custom :=
11.Params.related }} {{ if $custom }}
12<div
13 class="bg-light-gray pa3 nested-list-reset nested-copy-line-height nested-links"
14>
15 <p class="f5 b mb3">{{ lang.Translate "related" }}</p>
16 <ul class="pa0 list">
17 {{ range $custom }} {{ $page := $.Site.GetPage . }} {{ if $page }}
18 <li class="mb2">
19 <a href="{{ $page.RelPermalink }}">{{ $page.Title }}</a>
20 </li>
21 {{ end }} {{ end }}
22 </ul>
23</div>
24{{ else }} {{/* Hugo native related content */}} {{ $related :=
25.Site.RegularPages.Related . | collections.First 15 }} {{ with $related }}
26<div
27 class="bg-light-gray pa3 nested-list-reset nested-copy-line-height nested-links"
28>
29 <p class="f5 b mb3">{{ lang.Translate "related" }}</p>
30 <ul class="pa0 list">
31 {{ range . }}
32 <li class="mb2">
33 <a href="{{ .RelPermalink }}">{{- .Title -}}</a>
34 </li>
35 {{ end }}
36 </ul>
37</div>
38{{ end }} {{ end }}
实现完毕!
主页置顶
我想要实现:指定的文章按特定顺序置顶,其他 最近文章 受 hugo.toml 的 recent_posts_number 数量限制,按时间顺序排列在后面。
我在 Font Matter 里定义了一个 pin 参数,按升序排列置顶,无 pin 参数不置顶。
将 blog\layouts\index.html 改为:
1{{ define "main" }}
2<article class="intro">
3 {{/* 主页简介内容*/}}
4 {{ .Content }}
5</article>
6
7{{ $show_recent_posts := site.Params.ananke.show_recent_posts }}
8{{ $all := .Site.RegularPages }}
9{{ $count := len $all }}
10
11{{ if and $show_recent_posts (ge $count 1) }}
12<div class="pa3 pa4-ns w-100 w-70-ns center">
13 {{ $n_posts := $.Param "recent_posts_number" | default 7 }}
14
15 {{/* 置顶文章 */}}
16 {{ $pinned := sort (where $all "Params.pin" "gt" 0) "Params.pin" "asc" }}
17
18 {{/* 普通文章:pin 参数严格不写 */}}
19 {{ $normal := sort (where $all "Params.pin" "eq" nil) "Date" "desc" }}
20
21 <section class="w-100 mw8">
22
23 {{/* 显示所有置顶文章 */}}
24 {{ range $pinned }}
25 <div class="w-100 mb4 relative">
26 {{ .Render "summary-with-image" }}
27 </div>
28 {{ end }}
29
30 {{/* 显示 recent_posts_number 篇普通文章 */}}
31 {{ range first $n_posts $normal }}
32 <div class="w-100 mb4 relative">
33 {{ .Render "summary-with-image" }}
34 </div>
35 {{ end }}
36
37 </section>
38
39 {{/* 可选:更多普通文章列表 */}}
40 {{ if ge (len $normal) (add $n_posts 1) }}
41 <section class="w-100">
42 <h1 class="f3">{{ i18n "more" }}</h1>
43 {{ range first 4 (after $n_posts $normal) }}
44 <h2 class="f5 fw4 mb4 dib {{ if eq $.Site.Language.LanguageDirection "rtl" }}ml3{{ else }}mr3{{ end }}">
45 <a href="{{ .RelPermalink }}" class="link black dim">
46 {{ .Title }}
47 </a>
48 </h2>
49 {{ end }}
50 </section>
51 {{ end }}
52
53</div>
54{{ end }}
55{{ end }}
实现完毕!
字体美化
在 blog\layouts\partials\head-additions.html 中添加如下内容以自动从 Google fonts 拉取 Roboto、JetBrains Mono、Allura 三种字体:
1{{/* ========== 手动加载 Google Fonts ========== */}}
2<!-- Roboto 字体 (正文字体)-->
3<link
4 href="https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;600;700&display=swap"
5 rel="stylesheet"
6/>
7
8<!-- JetBrains Mono 字体(代码字体) -->
9<link
10 href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&display=swap"
11 rel="stylesheet"
12/>
13
14<!-- Allura 字体(大标题) -->
15<link
16 href="https://fonts.googleapis.com/css2?family=Allura:wght@400&display=swap"
17 rel="stylesheet"
18/>
优化文字、标题、代码块的字体和样式:
在 blog\assets\ananke\css\_style.css 中添加:
1@import "text_style";
新建 blog\assets\ananke\css\text_style.css ,添加如下内容:
1/* =======================
2 首页、Section页文章标题样式
3 ======================= */
4
5.article-title {
6 font-size: 2.2rem; /* 调大字体 */
7 font-weight: 700; /* 加粗 */
8 font-family:
9 /* 英文字体,标题用特殊的字体 */ 'Roboto', /* 中文字体 */ 'SimSun',
10 'PingFang SC', /* 英文备用字体 */ sans-serif;
11
12 color: #000000;
13 text-decoration: none; /* 去掉下划线 */
14 transition: color 0.5s; /* 悬停过渡效果 */
15}
16.article-title:hover {
17 color: #f32cfeb0; /* 悬停变蓝 */
18 /*text-decoration: underline;*/ /* 可选悬停下划线 */
19}
20
21/* =======================
22 标题样式
23 ======================= */
24
25h1,
26h2,
27h3 {
28 font-family:
29 /* 英文字体,标题用特殊的字体 */
30 "Roboto",
31 /* 中文字体 */
32 "Microsoft YaHei",
33 "PingFang SC",
34 sans-serif;
35 /* 英文备用字体 */
36}
37
38h1 {
39 font-size: 2.2rem;
40 line-height: 1.2;
41 margin: 2em 0 1em 0;
42}
43
44h2 {
45 font-size: 1.8rem;
46 line-height: 1.3;
47 margin: 1.8em 0 0.8em 0;
48}
49
50h3 {
51 font-size: 1.3rem;
52 line-height: 1.3;
53 margin: 1.5em 0 0.6em 0;
54}
55
56/* =======================
57 正文样式
58 ======================= */
59.nested-copy-line-height {
60 font-family:
61 /* 英文字体,优先 */
62 "Roboto",
63 /* 中文字体 */
64 "Microsoft YaHei",
65 "PingFang SC",
66 serif;
67 font-size: 1rem;
68 line-height: 1.8;
69 margin-bottom: 1.6em;
70 color: #333;
71}
72
73/* =======================
74 引用块样式
75 ======================= */
76.lh-copy blockquote {
77 display: block;
78 font-size: 0.9em;
79 margin: 2rem 0 2rem 2rem;
80 border-left: 4px solid #ccc;
81 padding-left: 1rem;
82 color: #555;
83 font-style: italic;
84 background-color: #f9f9f9;
85 padding: 1em 1.2em;
86 border-radius: 6px;
87}
88
89/* =======================
90 正文链接样式
91 ======================= */
92.nested-links a {
93 overflow-wrap: break-word;
94 color: #1a0dab;
95 text-decoration: underline;
96}
将 blog\assets\ananke\css\_code.css 改为:
1/* =======================
2 _code.css —— 高亮代码块
3 支持 noClasses=true(内联样式高亮)
4 单层背景,固定最小宽度,超长滚动
5 ======================= */
6
7/* ---------- 外层 pre ---------- */
8pre,
9pre.chroma,
10.highlight {
11 background-color: #f6e9fe !important;
12 /* 淡紫色背景 */
13 border-radius: 8px;
14 padding: 1em 1.2em;
15 min-width: 400px;
16 /* 最小宽度 */
17 max-width: 100%;
18 margin: 1em auto;
19 overflow-x: auto;
20 /* 超长代码滚动 */
21 overflow-y: hidden;
22}
23
24/* ---------- 内层 <code> ---------- */
25pre code,
26pre>code {
27 display: block;
28 background-color: transparent !important;
29 /* 背景由 pre 控制 */
30 color: inherit;
31 font-family: "JetBrains Mono", "Microsoft YaHei", "PingFang SC", monospace;
32 font-size: 0.95rem;
33 line-height: 1.5;
34 white-space: pre;
35 width: 100%;
36 min-width: inherit;
37 padding: 0;
38 /* 内边距由 pre 控制 */
39}
40
41/* ---------- 清除 token 背景 ---------- */
42pre span {
43 background-color: transparent !important;
44 /* 覆盖 Chroma 内联背景 */
45}
46
47/* ---------- 内联代码 ---------- */
48:not(pre)>code {
49 font-family: "JetBrains Mono", "Microsoft YaHei", "PingFang SC", monospace;
50 font-size: 0.95rem;
51 line-height: 1.4;
52 background-color: #f9f2fe;
53 /* 文中小段代码背景 */
54 padding: 0.2em 0.4em;
55 border-radius: 4px;
56}
将 blog\layouts\_default\summary-with-image.html 改为:(实际只改了标题的 class,来配合自定义的 CSS。)
1{{ $featured_image := partials.Include "func/GetFeaturedImage.html" . }}
2<article class="bb b--black-10">
3 <div class="db pv4 ph3 ph0-l dark-gray no-underline">
4 <div class="flex-column flex-row-ns flex">
5 {{ if $featured_image }}
6 {{/* Trimming the slash and adding absURL make sure the image works no matter collections.Where our site lives */}}
7 <div class="{{ compare.Conditional (compare.Eq $.Site.Language.LanguageDirection "rtl") "pl3-ns" "pr3-ns" }} mb4 mb0-ns w-100 w-40-ns">
8 <a href="{{.RelPermalink}}" class="db grow">
9 <img src="{{ $featured_image }}" class="img" alt="image from {{ .Title }}">
10 </a>
11 </div>
12 {{ end }}
13 <div class="blah w-100{{ if $featured_image }} w-60-ns {{ compare.Conditional (compare.Eq $.Site.Language.LanguageDirection "rtl") "pr3-ns" "pl3-ns" }}{{ end }}">
14 <h1 class="f3 fw1 athelas mt0 lh-title">
15 <a href="{{.RelPermalink}}" class="article-title">
16 {{ .Title }}
17 </a>
18 </h1>
19 <div class="f6 f5-l lh-copy nested-copy-line-height nested-links">
20 {{ .Summary }}
21 </div>
22 {{ with .Params.author | compare.Default .Site.Params.author }}
23 <p class="f6 lh-copy mv0">By {{ . }}</p>
24 {{- end -}}
25 <a href="{{.RelPermalink}}" class="ba b--moon-gray bg-light-gray br2 color-inherit dib f7 hover-bg-moon-gray link mt2 ph2 pv1">{{ $.Param "read_more_copy" | compare.Default (lang.Translate "readMore") }}</a>
26 </div>
27 </div>
28 </div>
29</article>
在 blog\hugo.toml 中添加:
1#代码块语法高亮——————————————————————————————————
2
3[markup]
4[markup.highlight]
5# 语法高亮风格
6style = "xcode"
7# 允许自定义CSS
8noClasses = true
9# 开启行号
10lineNos = true
11# ❌ 禁止使用 <table> 布局
12lineNumbersInTable = false
13
14
15#———————————————————————————————————————————————
实现完毕!
标题栏重写
裁剪主页背景图,露出那个”人“,效果比较好。
由于 Ananke 的源代码标题栏部分实现混乱,非常不利于配置,所以重写整个标题栏部分的模板代码,并引用我自定义的 CSS 。
将 blog\layouts\partials\site-header.html 改为:
1{{ $featured_image := partials.Include "func/GetFeaturedImage.html" . }}
2{{ if $featured_image }} {{/* 如果有封面图 */}}
3 <header class="hero-wrapper" style="background-image: url('{{ $featured_image }}');">
4
5 <!-- 黑色蒙版,只覆盖背景图 -->
6 <div class="hero-overlay {{ site.Params.cover_dimming_class | compare.Default "bg-black-60" }}"></div>
7
8 <!-- 导航栏 -->
9 {{ partials.Include "site-navigation.html" . }}
10
11 <!-- 居中标题 + 副标题 -->
12 <div class="hero-center">
13 <h1 class="hero-title">{{ .Title | compare.Default .Site.Title }}</h1>
14 {{ with .Params.description }}
15 <h2 class="hero-subtitle">{{ . }}</h2>
16 {{ end }}
17 </div>
18
19 </header>
20{{ else }} {{/* 如果没有封面图 */}}
21 <header class="hero-wrapper no-image">
22
23 <!-- 导航栏 -->
24 {{ partials.Include "site-navigation.html" . }}
25
26 <!-- 居中标题 + 副标题 -->
27 <div class="hero-center">
28 <h1 class="hero-title">{{ .Title | compare.Default .Site.Title }}</h1>
29 {{ with .Params.description }}
30 <h2 class="hero-subtitle">{{ . }}</h2>
31 {{ end }}
32 </div>
33
34 </header>
35{{ end }}
用 CSS 统一定义主页和 Section 页标题栏的样式。
在 blog\assets\ananke\css\_styles.css 添加如下内容:
1@import "header_style";
新建 server\blog\assets\ananke\css\header_style.css ,并添加如下内容:
1/* =======================
2 Hero 主标题容器
3 ======================= */
4
5/* site-header.html 中的标题 */
6
7/* header 固定高度,背景图 + 蒙版 */
8.hero-wrapper {
9 position: relative;
10 height: 80vh;
11 /* 占屏幕 4/5 */
12 background-size: cover;
13 background-position: center;
14 display: flex;
15 flex-direction: column;
16 justify-content: flex-start;
17}
18
19/* 蒙版,覆盖整个 header */
20.hero-overlay {
21 position: absolute;
22 inset: 0;
23 /* top/right/bottom/left 0 */
24 background: rgba(0, 0, 0, 0.6);
25 /* 半透明黑色 */
26 z-index: 1;
27 /* 在背景上 */
28}
29
30/* 导航栏和标题在蒙版上 */
31.hero-wrapper>nav,
32.hero-center {
33 position: relative;
34 z-index: 2;
35}
36
37/* 主副标题容器 */
38.hero-center {
39 position: relative;
40 z-index: 2;
41 display: flex;
42 flex-direction: column;
43 height: 100%;
44 /* 占满 header */
45 text-align: center;
46}
47
48/* flex 容器 */
49.hero-center {
50 position: relative;
51 z-index: 2;
52 display: flex;
53 flex-direction: column;
54 height: 100%;
55 align-items: center;
56 padding: 0;
57}
58
59/* 主标题容器 */
60.hero-title-wrapper {
61 display: flex;
62 flex-direction: column;
63 justify-content: flex-start;
64 /* 控制主标题垂直位置 */
65 height: 100%;
66}
67
68/* 主标题 */
69.hero-title {
70 position: absolute;
71 top: 40%;
72 /* 你想要中心在 header 的 2/5 处,40% */
73 left: 50%;
74 transform: translate(-50%, -50%);
75 /* 让文字中心对齐该点 */
76 font-family: "Allura", sans-serif;
77 font-weight: 400;
78 font-size: clamp(2rem, 8vw, 10rem);
79 color: #fff;
80 line-height: 1.1;
81 margin: 0;
82
83 white-space: nowrap;
84 /* 强制一行 */
85 max-width: 90%;
86 /* 避免超出屏幕 */
87 text-align: center;
88}
89
90/* 副标题 */
91.hero-subtitle {
92 position: absolute;
93 left: 50%;
94 z-index: 2;
95 font-weight: 300;
96 color: rgba(255, 255, 255, 0.8);
97 text-align: center;
98 font-size: clamp(1rem, 3vw, 1.8rem);
99 transform: translateX(-50%);
100 margin: 0;
101
102 /* 自动计算位置 */
103 top: calc(50% +
104 /* 主标题垂直中心线 */
105 (0.5 * var(--hero-title-height, 0px)) +
106 /* 主标题自身高度的一半(可用 JS 或 CSS 自定义属性计算) */
107 ((100% - (50% + var(--hero-title-height, 0px))) / 3*2)
108 /* 主标题底部到 wrapper 底部的下三分之一 */
109 );
110}
实现完毕!
Section页重写
现在,我发现主页的简介和 Section 页的简介效果不同,我们想要统一的效果。
进而,我发现 Ananke 主题的原生 Section 页模板非常敷衍,所以我们直接决定重写 Section 页模板,实现以下功能:
只显示本
Section内的文章如有文章被置顶,根据
pin升序排列可在
hugo.toml配置的分页功能
定义统一的 CSS (占屏幕的下 1/5 ,支持自定义字体字号行间距,水平垂直居中,保留 Markdown 中的换行,且保证不受外界元素影响)。
在 blog\assets\ananke\css\_style.css 中添加以下内容:
1@import "intro_style";
新建 blog\assets\ananke\css\intro_style.css ,并添加如下内容:
1/* 简介区域通用样式 */
2.intro {
3 display: flex;
4 flex-direction: column;
5 justify-content: center;
6 /* 垂直居中 */
7 align-items: center;
8 /* 水平居中 */
9 text-align: center;
10
11 /* 字体可控 */
12 font-family: "Microsoft YaHei", sans-serif;
13
14 /* 最小16px,首选4vw,最大28px */
15 font-size: 3vh;
16 font-weight: 400;
17 line-height: 1.8;
18
19
20 /* 保留 Markdown 换行 */
21 white-space: pre-wrap;
22
23 /* 保证各端一致 */
24 box-sizing: border-box;
25 height: 20vh;
26 /* 按需改,也可以 auto */
27 margin: 0;
28 padding: 0;
29}
30
31.intro p {
32 margin: 0;
33 /* 去掉默认段落 margin */
34 padding: 0;
35}
更改主页简介的模板代码。
更改 blog\layouts\index.html ,将 <article> 元素的 class 改为 intro 。
1{{ define "main" }}
2<article class="intro">
3 {{/* 主页简介内容*/}}
4 {{ .Content }}
5</article>
6
7......其余不变......
重写 Sention 页模板代码
将 blog\layouts\_default\list.html ,改为:
1{{ define "main" }}
2<article class="intro">{{/* Section简介内容 */}} {{ .Content }}</article>
3
4<section class="w-100 mw8 center">
5 {{ $all := .Paginator.Pages }} {{/* 置顶文章(本 Section 内) */}} {{ $pinned
6 := sort (where $all "Params.pin" "gt" 0) "Params.pin" "asc" }} {{/*
7 普通文章(本 Section 内,未置顶),按时间降序 */}} {{ $normal := sort (where
8 $all "Params.pin" "eq" nil) "Date" "desc" }} {{/* 显示置顶文章 */}} {{ range
9 $pinned }}
10 <div class="w-100 mb4 relative">{{ .Render "summary-with-image" }}</div>
11 {{ end }} {{/* 显示普通文章 */}} {{ range $normal }}
12 <div class="w-100 mb4 relative">{{ .Render "summary-with-image" }}</div>
13 {{ end }}
14</section>
15
16{{/* 分页 */}} {{ template "_internal/pagination.html" . }} {{ end }}