Hugo博客Book主题装修小记第三辑。没想到新的一期来得这么快,这次主要针对阅读体验进行了一些样式变更。主要包括注脚样式、Twikoo样式和功能、目录样式和功能等。
更好的移动端体验 #
针对多媒体卡片和代码块做了一些移动端的适应,在小屏幕上更易阅读,具体为:
- 各类媒体卡片宽度适应为100%,简介字号缩小为
$font-size-12
,简介框高度缩小4rem
; - 代码高度适应为
6em
,约4行。
这里,代码块高度设置的比较小(几乎折叠了),主要考虑到读者几乎不会在移动端进行代码的复制或阅读。但是以单行为主的Shell命令仍能完整显示。实现比较简单,直接通过布局断点进行判断,覆盖默认值。


/* /themes/hugo-book/assets/_custom.scss */
@media screen and (max-width: $mobile-breakpoint) {
img,
.db-card,
.post-preview,
.video-container {
width: 100% !important;
}
pre {
max-height: 6em !important;
}
.db-card-abstract,
.db-card-comment {
font-size: $font-size-12 !important;
max-height: 4rem !important;
}
}
注脚标记 #
给引用的角标做个填色样式,更加显眼,也更易于点击。看我右上角1。
/* /themes/hugo-book/assets/_custom.scss */
.footnote-ref {
background-color: var(--color-link);
color: var(--body-background) !important;
padding: 0px 4px;
border-radius: 4px;
font-size: $font-size-10;
margin: 0 2px;
}
注脚悬浮显示 #
在网页上上下跳跃阅读脚注体验不佳,即便是提供了必要的锚点链接。鼠标悬浮直接预览注脚内容,会有更好的阅读体验,我也可以放心大胆地用注脚而不是在句子的末尾添加括号说明。原想尝试不依赖Javascript,在Hugo构建时直接嵌入注脚内容,但对Hugo不熟,没能成功。还是暂时用以下方案吧。
<!-- /themes/hugo-book/layouts/partials/docs/inject/body.html -->
<script>
document.addEventListener("DOMContentLoaded", function () {
const container = document.querySelector('.footnotes');
if (!container) return;
const footnotes = {};
container.querySelectorAll('li[id^="fn:"]').forEach(li => {
const id = li.id.slice(3);
let text = li.textContent.trim();
if (text.endsWith('↩︎')) text = text.slice(0, -2).trim();
footnotes[id] = text;
});
document.querySelectorAll('sup[id^="fnref:"]').forEach(sup => {
const id = sup.id.slice(6);
const content = footnotes[id];
if (content) sup.setAttribute('data-footnote', content);
});
});
</script>
/* /themes/hugo-book/assets/_custom.scss */
sup[id^="fnref:"] {
position: relative;
cursor: help;
font-size: $font-size-12;
vertical-align: super;
line-height: 1.5;
}
sup[id^="fnref:"]::after {
content: attr(data-footnote);
position: absolute;
bottom: calc(100% + 0.5em);
left: 50%;
transform: translateX(-50%);
background: var(--color-link);
color: var(--body-background);
padding: 0.25em 0.5em;
border-radius: $border-radius;
box-shadow: 0 2px 6px var(--body-font-color);
white-space: normal;
width: max-content;
max-width: 20rem;
font-size: $font-size-12;
text-align: left;
word-break: break-word;
opacity: 0;
pointer-events: none;
z-index: 100;
transition: opacity 0.2s ease-in-out;
}
sup[id^="fnref:"]:hover::after {
opacity: 1;
}
还有一种高颜值方案是旁注234,无奈现在我使用的是三栏样式,且我认为目录的优先级更高。在没想好如何美观地兼容旁注和目录之前,还是暂时用上述的方案。
外链标识 #
博文中插入链接时,外站链接和博客内部链接没有区分,给外链加上一个小图标,以便快速区分。标识仅在博文正文中显示。效果对比,如站内博文 低成本的自动化家务管理,站外链接 GitHub - osnsyc/chores-automation。
<!-- /themes/hugo-book/layouts/_default/_markup/render-link.html -->
{{- if .Page.Site.Params.BookPortableLinks -}}
{{- template "portable-link" . -}}
{{- else -}}
{{- $href := .Destination -}}
{{- $isExternal := or (strings.HasPrefix $href "http://") (strings.HasPrefix $href "https://") -}}
<a href="{{ $href | safeURL }}"{{ with .Title }} title="{{ . }}"{{ end }}{{ if $isExternal }} target="_blank" rel="noopener noreferrer"{{ end }}>
{{ .Text | safeHTML }}
{{- if $isExternal -}}
<svg class="external-link-icon" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M 18 13.001953 L 18 19.001953 C 18 20.103516 17.103516 21 16.001953 21 L 4.998047 21 C 3.896484 21 3 20.103516 3 19.001953 L 3 7.998047 C 3 6.896484 3.896484 6 4.998047 6 L 10.998047 6" transform="matrix(0.666667,0,0,0.666667,0,0)"/>
<path d="M 15 3 L 21 3 L 21 9" transform="matrix(0.666667,0,0,0.666667,0,0)"/>
<path d="M 10.001953 13.998047 L 21 3" transform="matrix(0.666667,0,0,0.666667,0,0)"/>
</svg>
{{- end -}}
</a>
{{- end -}}
/* /themes/hugo-book/assets/_custom.scss */
.external-link-icon {
display: inline-block;
width: 1em;
height: 1em;
margin-left: 0.125em;
vertical-align: -0.15em;
stroke: currentColor;
}
Twikoo主题颜色适应 #
注意到Twikoo的默认主题色(浅蓝)有些别扭,跟博客主题颜色不一致,修改CSS来覆盖默认颜色,自适应亮暗主题。
/* /themes/hugo-book/assets/_custom.scss */
.twikoo .el-button--default {
color: var(--color-link) !important;
border-color: var(--color-link) !important;
}
.twikoo .el-button--primary {
color: var(--body-background) !important;
background-color: var(--color-link) !important;
border-color: transparent;
}
.twikoo .tk-icon,
.twikoo .tk-action-icon,
.twikoo .tk-action-icon.tk-action-icon-solid,
.twikoo .tk-action-count,
.twikoo .tk-avatar-img {
color: var(--color-link) !important;
}
新增Twikoo表情包 #
删除了颜文字表情包,增加了自选的Blob表情包,可以在这个网站选取自己喜欢的表情:
Slackmojis,原图大多是120px
的PNG格式文件,显然不符合网站图像的最佳实践(参考本站博文
图片智能压缩与高效写作发布流)。将表情包下载至本地,转换成宽度64px
的Webp文件,并上传至CloudFlare的R2存储桶,压缩后平均每个表情文件大小3KB(压缩前约10KB)。
关于owo.json
的托管可以查看上一篇装修博文
hugo博客装修小记之二,修改owo.json
文件如下
// /themes/hugo-book/static/owo.json
{
"Blob": {
"type": "image",
"container": [
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_smiley.webp\">", "text": "blob_smiley" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_sunglasses.webp\">", "text": "blob_sunglasses" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_joy.webp\">", "text": "blob_joy" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_okhand.webp\">", "text": "blob_okhand" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_kir.webp\">", "text": "blob_kir" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_hearteyes.webp\">", "text": "blob_hearteyes" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_pray.webp\">", "text": "blob_pray" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_thinking_eyes.webp\">", "text": "blob_thinking_eyes" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_sad.webp\">", "text": "blob_sad" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_oohoocry.webp\">", "text": "blob_oohoocry" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_fearful.webp\">", "text": "blob_fearful" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_angry.webp\">", "text": "blob_angry" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_hi.webp\">", "text": "blob_hi" },
{ "icon": "<img src=\"https://img.osnsyc.top/emoji/blob_yes.webp\">", "text": "blob_yes" }
]
},
"Emoji": {
"type": "emoji",
"container": [
{ "icon": "😂", "text": "" },
{ "icon": "😀", "text": "" },
{ "icon": "😅", "text": "" },
{ "icon": "😊", "text": "" },
{ "icon": "🙂", "text": "" },
{ "icon": "🙃", "text": "" },
{ "icon": "😌", "text": "" },
{ "icon": "😍", "text": "" },
{ "icon": "😘 ", "text": "" },
{ "icon": "😜", "text": "" },
{ "icon": "😝", "text": "" },
{ "icon": "😏", "text": "" },
{ "icon": "😒", "text": "" },
{ "icon": "🙄", "text": "" },
{ "icon": "😳 ", "text": "" },
{ "icon": "😡", "text": "" },
{ "icon": "😔", "text": "" },
{ "icon": "😫", "text": "" },
{ "icon": "😱", "text": "" },
{ "icon": "😭", "text": "" },
{ "icon": "💩", "text": "" },
{ "icon": "👻", "text": "" },
{ "icon": "🙌", "text": "" },
{ "icon": "🖕", "text": "" },
{ "icon": "👍", "text": "" },
{ "icon": "👫", "text": "" },
{ "icon": "👬", "text": "" },
{ "icon": "👭", "text": "" },
{ "icon": "🌚", "text": "" },
{ "icon": "🌝", "text": "" },
{ "icon": "🙈", "text": "" },
{ "icon": "💊", "text": "" },
{ "icon": "😶", "text": "" },
{ "icon": "🙏", "text": "" },
{ "icon": "🍦", "text": "" },
{ "icon": "🍉", "text": "" },
{ "icon": "😣", "text": "" }
]
}
}
修改样式,确保表情与文字在同一行,大小为2rem
,即32px
,原图64px
足以保证在高分屏(DPR=2)上清晰显示。
/* /themes/hugo-book/assets/_custom.scss */
.tk-content img, .tk-preview-container img {
display: inline;
max-width: 2rem !important;
vertical-align: bottom !important;
}
解决APlayer导致的中文目录无法跳转问题 #
偶然发现如果页面加载了APlayer播放器,中文目录跳转会失效,搜了下问题所在,居然是陈年未解决的Bug。参考
滑翔闪和
韶华尐沐的博文,原因是APlayer下的smoothscroll插件在处理跳转连接的hash时只对英文处理有效,而中文会转成Unicode码,无法处理,所以跳转就会失效。解决办法是修改APlayer.min.js
,定位到defaultPrevented
,替换成以下代码(decodeURIComponent处理)。
if (!e.defaultPrevented) {
e.preventDefault(), decodeURIComponent(location.hash) !== decodeURIComponent(this.hash) && window.history.pushState(null, null, decodeURIComponent(this.hash));
var n = document.getElementById(decodeURIComponent(this.hash).substring(1));
if (!n) return;
t(n, 500, function(e) {
location.replace("#" + e.id)
})
}
目录跟随高亮 #
Hugo-Book主题的右侧边目录,没有随内容自动高亮的功能。在阅读长文时这项功能还是有帮助的,参考 砖瓦匠杜重的博文进行了配置,高亮颜色为主题色,左侧加主题色条进行强调,效果如下。
<!-- /themes/hugo-book/layouts/partials/docs/inject/body.html -->
<script src="https://cdn.jsdelivr.net/gh/cferdinandi/[email protected]/dist/gumshoe.polyfills.min.js"></script>
<script>new Gumshoe('.book-toc a', { nested: true });</script>
也可以将js下载并置于/themes/hugo-book/static
文件夹内:
<!-- /themes/hugo-book/layouts/partials/docs/inject/body.html -->
<script src="https://osnsyc.top/gumshoe.polyfills.min.js"></script>
修改目录样式,如果没有定义var(--gray-1000)
,$padding-32
请在/themes/hugo-book/assets/_defaults.scss
中自行配置。
/* /themes/hugo-book/assets/_custom.scss */
.book-toc li,
.book-toc ul {
list-style-type: none;
padding-left: 0px;
}
.book-toc li > a {
display: block;
padding-left: $padding-16;
color: var(--gray-1000);
}
.book-toc li > a:hover,
.book-toc li > a:focus {
padding-left: $padding-16;
color: var(--color-link);
border-left: 1px solid var(--color-link);
}
.book-toc li.active > a,
.book-toc li.active > a:hover,
.book-toc li.active > a:focus {
padding-left: $padding-16;
font-weight: bold;
color: var(--color-link);
border-left: 2px solid var(--color-link);
}
.book-toc li li > a {
padding-left: $padding-32;
}
.book-toc li li > a:hover,
.book-toc li li > a:focus {
padding-left: $padding-32;
}
.book-toc li li.active > a,
.book-toc li li.active > a:hover,
.book-toc li li.active > a:focus {
padding-left: $padding-32;
}
.book-toc .nav-link.active + ul {
display: block;
}
Tag标签样式优化 #
Tag标签和目录都在侧栏受.book-toc
控制,刚才修改了目录,索性也将标签样式改一改。Book主题默认的标签样式中,计数离标签文字太远了,翻了好多博客,没找到适合此主题的好看样式,凭着感觉先撸一个吧,以后看到好的样式再抄过来,哈哈哈。修改完后,样式为圆角矩形,按计数降序排列。
<!-- /themes/hugo-book/layouts/partials/docs/taxonomy.html -->
<nav>
<ul>
{{ range $term, $_ := .Site.Taxonomies }}
{{ with $.Site.GetPage (printf "/%s" $term | urlize) }}
<li class="book-section-flat">
<h3><strong>{{ .Title | title }}</strong></h3>
<ul>
{{ range sort .Pages "Pages" "desc" }}
<a class="toc-tag" href="{{ .RelPermalink }}">
<span class="toc-tag-title">{{ .Title }}</span>
<span class="toc-tag-count">{{ len .Pages }}</span>
</a>
{{ end }}
</ul>
</li>
{{ end }}
{{ end }}
</ul>
</nav>
/* /themes/hugo-book/assets/_custom.scss */
.toc-tag {
display: inline-flex;
align-items: center;
margin: $padding-4;
font-size: $font-size-12;
color: var(--body-font-color);
line-height: 1.5;
border-radius: $border-radius;
border: 1px solid var(--color-link);
overflow: hidden;
text-decoration: none;
cursor: pointer;
padding: 0;
.toc-tag-title {
display: inline-block;
padding: $padding-2 $padding-4;
white-space: nowrap;
}
.toc-tag-count {
display: inline-block;
padding: $padding-2 $padding-4;
color: var(--color-link);
font-weight: bold;
border-left: 1px solid var(--color-link);
white-space: nowrap;
}
&:hover {
color: var(--body-background);
border: 1px solid var(--body-font-color);
background: var(--color-link);
}
&:hover .toc-tag-count {
color: var(--body-background);
border-left: 1px solid var(--body-background);
background: var(--color-link);
}
}