<rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>Hugo 博客折腾 - 系列 - 灿若星河 | 郝建锋</title><link>https://philohao.com/series/hugo-%E5%8D%9A%E5%AE%A2%E6%8A%98%E8%85%BE/</link><description>Hugo 博客折腾 - 系列 - 灿若星河 | 郝建锋</description><generator>Hugo -- gohugo.io</generator><language>zh-CN</language><managingEditor>haojianfeng1997@gmail.com (Jianfeng.Hao)</managingEditor><webMaster>haojianfeng1997@gmail.com (Jianfeng.Hao)</webMaster><lastBuildDate>Mon, 15 Sep 2025 19:01:17 +0800</lastBuildDate><atom:link href="https://philohao.com/series/hugo-%E5%8D%9A%E5%AE%A2%E6%8A%98%E8%85%BE/index.xml" rel="self" type="application/rss+xml"/><item><title>折腾 | Hugo 博客目录（TOC）样式改造</title><link>https://philohao.com/2025/09/20250915/</link><pubDate>Mon, 15 Sep 2025 19:01:17 +0800</pubDate><dc:creator>Jianfeng.Hao</dc:creator><author>haojianfeng1997@gmail.com (Jianfeng.Hao)</author><guid isPermaLink="true">https://philohao.com/2025/09/20250915/</guid><description>分享一次纯 CSS 驱动的 Hugo 博客目录（TOC）美化过程。本文详细记录如何通过增强层级感、添加交互反馈和优化布局等技巧，让博客目录焕然一新，提升读者体验。</description><content:encoded><![CDATA[<p>本文解决的是 Hugo 博客目录（TOC）层级不够清晰、交互反馈偏弱的问题：在不改 JavaScript 的前提下，通过 SCSS 调整标记点、引导线、悬停态和容器样式，让长文目录更好读也更好用。</p>
<h2 id="适用场景">适用场景</h2>
<p>适合已经启用 Hugo 文章目录、但默认 TOC 在长文中显得层级混乱或视觉过轻的博客。尤其是经常写技术教程、读书笔记这类多级标题文章时，目录样式的可读性会直接影响阅读体验。</p>
<h2 id="背景">背景</h2>
<p>最近在看自己的网站时，觉得文章右侧的目录（Table of Contents）样式有些单调。它虽然能用，但在视觉上还有很大的提升空间。</p>
<p><img
        class="lazyload"
        data-src="https://photos.philohao.com/picimpact/20250915203443489.png"
        data-srcset="https://photos.philohao.com/picimpact/20250915203443489.png, https://photos.philohao.com/picimpact/20250915203443489.png 1.5x, https://photos.philohao.com/picimpact/20250915203443489.png 2x"
        data-sizes="auto"
        alt="https://photos.philohao.com/picimpact/20250915203443489.png"
        title="https://photos.philohao.com/picimpact/20250915203443489.png"
    /></p>
<p>可以看到，它只用了简单的圆点和缩进，层级关系不够直观，交互感也比较弱。我的目标是：在不修改任何 JavaScript 的前提下，只通过 CSS (SCSS) 来让它变得更美观、更实用。</p>
<h2 id="核心步骤">核心步骤</h2>
<h3 id="第一版改造四大优化方向">第一版改造：四大优化方向</h3>
<p>经过分析，我确定了四个主要的优化方向，并进行了第一轮的样式修改。</p>
<h4 id="1-增强层级感">1. 增强层级感</h4>
<p>为了让目录结构一目了然，我做了两处关键改动：</p>
<ul>
<li><strong>区分标记点</strong>：用不同的符号来表示不同级别的标题。一级目录用实心圆 ●，二级目录用空心圆 ○，三级目录则用更细的 ◌。</li>
<li><strong>增加引导线</strong>：在次级目录的左侧，增加一条垂直的引导线。这条线能非常清晰地将子标题“收纳”在父标题之下，结构感瞬间增强。</li>
</ul>
<h4 id="2-增加交互反馈">2. 增加交互反馈</h4>
<p>一个好的界面应该能对用户的操作做出反馈，之前的目录，鼠标放上去没有任何变化。</p>
<ul>
<li><strong>悬停效果 (:hover)</strong>： 为每个目录链接添加了 :hover 伪类。当鼠标悬停在链接上时，会改变文字颜色并出现一个淡淡的背景色。这个简单的改动能明确告诉用户“这里可以点击”。</li>
</ul>
<h4 id="3-优化容器外观">3. 优化容器外观</h4>
<p>无论是浮动目录还是静态目录，我都想让它们看起来更像一个精心设计的“卡片”，而不是简单的文字列表。</p>
<ul>
<li>浮动目录 (#toc-auto)： 为其增加了半透明的背景和右侧的圆角。这样即使页面背景复杂，目录依然清晰可读。</li>
<li>静态目录 (#toc-static)： 将其从类似代码块的深色背景，改为了带有圆角和细边框的简洁样式，更好地融入文章内容。</li>
</ul>
<h4 id="4-调整布局方式">4. 调整布局方式</h4>
<p>放弃了原先 text-indent 的缩进方式，改用 position: relative 和 padding-left 来布局，这样能更精确地控制标记点和文字的位置，避免错位问题。</p>
<h3 id="第二版微调优化行间距">第二版微调：优化行间距</h3>
<p>第一版改造后，整体效果已经很不错了，但我发现一个细节问题：每一行的行间距似乎有点大，目录显得有些松散。</p>
<p>这个问题主要来源于我为了增加链接点击区域而在 a 标签上设置的 padding 值。</p>
<p>调整方法很简单：</p>
<p>找到 <code>.toc .toc-content ul a</code> 选择器，将其 padding 的垂直值从 4px 或 2px 直接改为 0。</p>
<p>修改前： <code>padding: 2px 0;</code></p>
<p>修改后： <code>padding: 0 0;</code></p>
<p>同时，也移除了层级之间 ul 的 margin 值，让整个列表更加紧凑。</p>
<h2 id="最终效果">最终效果</h2>
<p>改造后的目录用不同符号和缩进表达层级，用 hover 状态提示可点击区域，并让浮动目录、静态目录都更像页面中的信息卡片。视觉上不会喧宾夺主，但足够支撑长文快速跳转。</p>
<h2 id="最终代码展示">最终代码展示</h2>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">  1
</span><span class="lnt">  2
</span><span class="lnt">  3
</span><span class="lnt">  4
</span><span class="lnt">  5
</span><span class="lnt">  6
</span><span class="lnt">  7
</span><span class="lnt">  8
</span><span class="lnt">  9
</span><span class="lnt"> 10
</span><span class="lnt"> 11
</span><span class="lnt"> 12
</span><span class="lnt"> 13
</span><span class="lnt"> 14
</span><span class="lnt"> 15
</span><span class="lnt"> 16
</span><span class="lnt"> 17
</span><span class="lnt"> 18
</span><span class="lnt"> 19
</span><span class="lnt"> 20
</span><span class="lnt"> 21
</span><span class="lnt"> 22
</span><span class="lnt"> 23
</span><span class="lnt"> 24
</span><span class="lnt"> 25
</span><span class="lnt"> 26
</span><span class="lnt"> 27
</span><span class="lnt"> 28
</span><span class="lnt"> 29
</span><span class="lnt"> 30
</span><span class="lnt"> 31
</span><span class="lnt"> 32
</span><span class="lnt"> 33
</span><span class="lnt"> 34
</span><span class="lnt"> 35
</span><span class="lnt"> 36
</span><span class="lnt"> 37
</span><span class="lnt"> 38
</span><span class="lnt"> 39
</span><span class="lnt"> 40
</span><span class="lnt"> 41
</span><span class="lnt"> 42
</span><span class="lnt"> 43
</span><span class="lnt"> 44
</span><span class="lnt"> 45
</span><span class="lnt"> 46
</span><span class="lnt"> 47
</span><span class="lnt"> 48
</span><span class="lnt"> 49
</span><span class="lnt"> 50
</span><span class="lnt"> 51
</span><span class="lnt"> 52
</span><span class="lnt"> 53
</span><span class="lnt"> 54
</span><span class="lnt"> 55
</span><span class="lnt"> 56
</span><span class="lnt"> 57
</span><span class="lnt"> 58
</span><span class="lnt"> 59
</span><span class="lnt"> 60
</span><span class="lnt"> 61
</span><span class="lnt"> 62
</span><span class="lnt"> 63
</span><span class="lnt"> 64
</span><span class="lnt"> 65
</span><span class="lnt"> 66
</span><span class="lnt"> 67
</span><span class="lnt"> 68
</span><span class="lnt"> 69
</span><span class="lnt"> 70
</span><span class="lnt"> 71
</span><span class="lnt"> 72
</span><span class="lnt"> 73
</span><span class="lnt"> 74
</span><span class="lnt"> 75
</span><span class="lnt"> 76
</span><span class="lnt"> 77
</span><span class="lnt"> 78
</span><span class="lnt"> 79
</span><span class="lnt"> 80
</span><span class="lnt"> 81
</span><span class="lnt"> 82
</span><span class="lnt"> 83
</span><span class="lnt"> 84
</span><span class="lnt"> 85
</span><span class="lnt"> 86
</span><span class="lnt"> 87
</span><span class="lnt"> 88
</span><span class="lnt"> 89
</span><span class="lnt"> 90
</span><span class="lnt"> 91
</span><span class="lnt"> 92
</span><span class="lnt"> 93
</span><span class="lnt"> 94
</span><span class="lnt"> 95
</span><span class="lnt"> 96
</span><span class="lnt"> 97
</span><span class="lnt"> 98
</span><span class="lnt"> 99
</span><span class="lnt">100
</span><span class="lnt">101
</span><span class="lnt">102
</span><span class="lnt">103
</span><span class="lnt">104
</span><span class="lnt">105
</span><span class="lnt">106
</span><span class="lnt">107
</span><span class="lnt">108
</span><span class="lnt">109
</span><span class="lnt">110
</span><span class="lnt">111
</span><span class="lnt">112
</span><span class="lnt">113
</span><span class="lnt">114
</span><span class="lnt">115
</span><span class="lnt">116
</span><span class="lnt">117
</span><span class="lnt">118
</span><span class="lnt">119
</span><span class="lnt">120
</span><span class="lnt">121
</span><span class="lnt">122
</span><span class="lnt">123
</span><span class="lnt">124
</span><span class="lnt">125
</span><span class="lnt">126
</span><span class="lnt">127
</span><span class="lnt">128
</span><span class="lnt">129
</span><span class="lnt">130
</span><span class="lnt">131
</span><span class="lnt">132
</span><span class="lnt">133
</span><span class="lnt">134
</span><span class="lnt">135
</span><span class="lnt">136
</span><span class="lnt">137
</span><span class="lnt">138
</span><span class="lnt">139
</span><span class="lnt">140
</span><span class="lnt">141
</span><span class="lnt">142
</span><span class="lnt">143
</span><span class="lnt">144
</span><span class="lnt">145
</span><span class="lnt">146
</span><span class="lnt">147
</span><span class="lnt">148
</span><span class="lnt">149
</span><span class="lnt">150
</span><span class="lnt">151
</span><span class="lnt">152
</span><span class="lnt">153
</span><span class="lnt">154
</span><span class="lnt">155
</span><span class="lnt">156
</span><span class="lnt">157
</span><span class="lnt">158
</span><span class="lnt">159
</span><span class="lnt">160
</span><span class="lnt">161
</span><span class="lnt">162
</span><span class="lnt">163
</span><span class="lnt">164
</span><span class="lnt">165
</span><span class="lnt">166
</span><span class="lnt">167
</span><span class="lnt">168
</span><span class="lnt">169
</span><span class="lnt">170
</span><span class="lnt">171
</span><span class="lnt">172
</span><span class="lnt">173
</span><span class="lnt">174
</span><span class="lnt">175
</span><span class="lnt">176
</span><span class="lnt">177
</span><span class="lnt">178
</span><span class="lnt">179
</span><span class="lnt">180
</span><span class="lnt">181
</span><span class="lnt">182
</span><span class="lnt">183
</span><span class="lnt">184
</span><span class="lnt">185
</span><span class="lnt">186
</span><span class="lnt">187
</span><span class="lnt">188
</span><span class="lnt">189
</span><span class="lnt">190
</span><span class="lnt">191
</span><span class="lnt">192
</span><span class="lnt">193
</span><span class="lnt">194
</span><span class="lnt">195
</span><span class="lnt">196
</span><span class="lnt">197
</span><span class="lnt">198
</span><span class="lnt">199
</span><span class="lnt">200
</span><span class="lnt">201
</span><span class="lnt">202
</span><span class="lnt">203
</span><span class="lnt">204
</span><span class="lnt">205
</span><span class="lnt">206
</span><span class="lnt">207
</span><span class="lnt">208
</span><span class="lnt">209
</span><span class="lnt">210
</span><span class="lnt">211
</span><span class="lnt">212
</span><span class="lnt">213
</span><span class="lnt">214
</span><span class="lnt">215
</span><span class="lnt">216
</span><span class="lnt">217
</span><span class="lnt">218
</span><span class="lnt">219
</span><span class="lnt">220
</span><span class="lnt">221
</span><span class="lnt">222
</span><span class="lnt">223
</span><span class="lnt">224
</span><span class="lnt">225
</span><span class="lnt">226
</span><span class="lnt">227
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-scss" data-lang="scss"><span class="line"><span class="cl"><span class="c1">// --- 变量定义 (假设这些变量已在别处定义) ---
</span></span></span><span class="line"><span class="cl"><span class="c1">// $toc-title-font-size: 1.1em;
</span></span></span><span class="line"><span class="cl"><span class="c1">// $toc-content-font-size: 0.9em;
</span></span></span><span class="line"><span class="cl"><span class="c1">// $single-link-color: #333;
</span></span></span><span class="line"><span class="cl"><span class="c1">// $single-link-hover-color: #007bff;
</span></span></span><span class="line"><span class="cl"><span class="c1">// $global-border-color: #eee;
</span></span></span><span class="line"><span class="cl"><span class="c1">// ... 以及对应的 dark 和 black 主题变量
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="c1">// --- 通用 TOC 基础样式 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nc">.toc</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nc">.toc-title</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">font-size</span><span class="o">:</span> <span class="nv">$toc-title-font-size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">font-weight</span><span class="o">:</span> <span class="ni">bold</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">text-transform</span><span class="o">:</span> <span class="ni">uppercase</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nc">.toc-content</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">font-size</span><span class="o">:</span> <span class="nv">$toc-content-font-size</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="c1">// --- 移除 text-indent, 使用更现代的 Flexbox/Grid 或伪元素布局 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">padding-left</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 重置内边距, 在 a 标签上控制
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="na">list-style</span><span class="o">:</span> <span class="ni">none</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nt">a</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="c1">// --- 优化: 将 a 标签设为块级或行内块, 方便添加 padding 和 hover 背景 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="na">display</span><span class="o">:</span> <span class="ni">block</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">padding</span><span class="o">:</span> <span class="mi">0</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// --- 调整这里 (1): 减小链接的上下内边距来缩小行距 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="na">position</span><span class="o">:</span> <span class="ni">relative</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">padding-left</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.35</span><span class="kt">rem</span><span class="p">;</span> <span class="c1">// 为伪元素留出空间
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="na">text-decoration</span><span class="o">:</span> <span class="ni">none</span><span class="p">;</span> <span class="c1">// 确保没有下划线
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="na">transition</span><span class="o">:</span> <span class="ni">color</span> <span class="mi">0</span><span class="mf">.2</span><span class="kt">s</span><span class="o">,</span> <span class="n">background-color</span> <span class="mi">0</span><span class="mf">.2</span><span class="kt">s</span><span class="p">;</span> <span class="c1">// 平滑过渡
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">        <span class="c1">// --- 新增: 鼠标悬停效果 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="k">&amp;</span><span class="nd">:hover</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="na">background-color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="nv">$global-border-color</span><span class="o">,</span> <span class="mi">0</span><span class="mf">.5</span><span class="p">);</span> <span class="c1">// 添加一个淡淡的背景色
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>          <span class="na">border-radius</span><span class="o">:</span> <span class="mi">4</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">          <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color-dark</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="na">background-color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="nv">$global-border-color-dark</span><span class="o">,</span> <span class="mi">0</span><span class="mf">.2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color-black</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">            <span class="na">background-color</span><span class="o">:</span> <span class="nf">rgba</span><span class="p">(</span><span class="nv">$global-border-color-black</span><span class="o">,</span> <span class="mi">0</span><span class="mf">.2</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="c1">// --- 优化: 使用 &gt; 选择器区分层级 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="c1">// Level 1
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="o">&gt;</span> <span class="nt">li</span> <span class="o">&gt;</span> <span class="nt">a</span><span class="nd">::before</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">content</span><span class="o">:</span> <span class="s2">&#34;●&#34;</span><span class="p">;</span> <span class="c1">// 使用实心圆点作为一级标记
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="na">font-weight</span><span class="o">:</span> <span class="ni">bolder</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">position</span><span class="o">:</span> <span class="ni">absolute</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">left</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">top</span><span class="o">:</span> <span class="mi">50</span><span class="kt">%</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">transform</span><span class="o">:</span> <span class="nf">translateY</span><span class="p">(</span><span class="o">-</span><span class="mi">50</span><span class="kt">%</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">        <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-color-dark</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-color-black</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">padding-left</span><span class="o">:</span> <span class="mi">1</span><span class="kt">rem</span><span class="p">;</span> <span class="c1">// 子列表的缩进
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// --- 调整这里 (2): 减小层级之间的垂直间距 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// margin-top: 0.1rem;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="c1">// margin-bottom: 0.1rem;
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">        <span class="c1">// --- 新增: 视觉引导线 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="na">position</span><span class="o">:</span> <span class="ni">relative</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="k">&amp;</span><span class="nd">::before</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="na">content</span><span class="o">:</span> <span class="s1">&#39;&#39;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="na">position</span><span class="o">:</span> <span class="ni">absolute</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="na">left</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.35</span><span class="kt">rem</span><span class="p">;</span> <span class="c1">// 调整线的位置
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>          <span class="na">top</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="na">bottom</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="na">width</span><span class="o">:</span> <span class="mi">1</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="na">background-color</span><span class="o">:</span> <span class="nv">$global-border-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">background-color</span><span class="o">:</span> <span class="nv">$global-border-color-dark</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">background-color</span><span class="o">:</span> <span class="nv">$global-border-color-black</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// Level 2
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="o">&gt;</span> <span class="nt">li</span> <span class="o">&gt;</span> <span class="nt">a</span><span class="nd">::before</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="na">content</span><span class="o">:</span> <span class="s2">&#34;○&#34;</span><span class="p">;</span> <span class="c1">// 使用空心圆点
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="c1">// Level 3 (如果需要)
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="nt">ul</span> <span class="o">&gt;</span> <span class="nt">li</span> <span class="o">&gt;</span> <span class="nt">a</span><span class="nd">::before</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="na">content</span><span class="o">:</span> <span class="s2">&#34;◌&#34;</span><span class="p">;</span> <span class="c1">// 使用更小的空心圆点
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// --- ruby 样式 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="nt">ruby</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">background</span><span class="o">:</span> <span class="nv">$code-background-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="nt">rt</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">color</span><span class="o">:</span> <span class="nv">$global-font-secondary-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">background</span><span class="o">:</span> <span class="nv">$code-background-color-dark</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nt">rt</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">color</span><span class="o">:</span> <span class="nv">$global-font-secondary-color-dark</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">background</span><span class="o">:</span> <span class="nv">$code-background-color-black</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nt">rt</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">color</span><span class="o">:</span> <span class="nv">$global-font-secondary-color-black</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// --- 浮动目录 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nn">#toc-auto</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="na">display</span><span class="o">:</span> <span class="ni">block</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">position</span><span class="o">:</span> <span class="ni">absolute</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">width</span><span class="o">:</span> <span class="nv">$MAX_LENGTH</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">max-width</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="c1">// --- 优化: 增加内边距, 让内容有呼吸空间 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="na">padding</span><span class="o">:</span> <span class="mi">0</span> <span class="mi">1</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">border-left</span><span class="o">:</span> <span class="mi">3</span><span class="kt">px</span> <span class="ni">solid</span> <span class="nv">$global-border-color</span><span class="p">;</span> <span class="c1">// 边框稍微细一点
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="k">@include</span><span class="nd"> overflow-wrap</span><span class="p">(</span><span class="ni">break-word</span><span class="p">);</span>
</span></span><span class="line"><span class="cl">  <span class="na">box-sizing</span><span class="o">:</span> <span class="ni">border-box</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">top</span><span class="o">:</span> <span class="mi">10</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">left</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">visibility</span><span class="o">:</span> <span class="ni">hidden</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="c1">// --- 新增: 半透明背景, 提升可读性 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="na">border-radius</span><span class="o">:</span> <span class="mi">0</span> <span class="mi">8</span><span class="kt">px</span> <span class="mi">8</span><span class="kt">px</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 右侧添加圆角
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="k">@include</span><span class="nd"> blur</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">border-left-color</span><span class="o">:</span> <span class="nv">$global-border-color-dark</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">border-left-color</span><span class="o">:</span> <span class="nv">$global-border-color-black</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="o">[</span><span class="nt">header-desktop</span><span class="o">=</span><span class="nt">normal</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">top</span><span class="o">:</span> <span class="mi">5</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nc">.toc-title</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">margin</span><span class="o">:</span> <span class="mi">1</span><span class="kt">rem</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nc">.toc-content</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="c1">// --- 优化: 为 active 状态的伪元素也应用高亮颜色 ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>      <span class="nt">a</span><span class="nc">.active</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">font-weight</span><span class="o">:</span> <span class="ni">bold</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color</span><span class="p">;</span> <span class="c1">// 使用 hover 颜色以示强调
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>        <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color-dark</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color-black</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">        <span class="k">&amp;</span><span class="nd">::before</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color-dark</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">          <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">color</span><span class="o">:</span> <span class="nv">$single-link-hover-color-black</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nc">.has-active</span> <span class="o">&gt;</span> <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">display</span><span class="o">:</span> <span class="ni">block</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">      <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="na">display</span><span class="o">:</span> <span class="ni">none</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="k">&amp;</span><span class="nc">.always-active</span> <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">display</span><span class="o">:</span> <span class="ni">block</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">    <span class="o">&gt;</span> <span class="nt">nav</span> <span class="o">&gt;</span> <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">margin</span><span class="o">:</span> <span class="mf">.625</span><span class="kt">rem</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// --- 静态目录 (页面内) ---
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="nn">#toc-static</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="na">display</span><span class="o">:</span> <span class="ni">none</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">margin</span><span class="o">:</span> <span class="mi">1</span><span class="mf">.5</span><span class="kt">rem</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">// 增加上下边距
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="na">border</span><span class="o">:</span> <span class="mi">1</span><span class="kt">px</span> <span class="ni">solid</span> <span class="nv">$global-border-color</span><span class="p">;</span> <span class="c1">// --- 优化: 使用边框代替背景色, 更简洁
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>  <span class="na">border-radius</span><span class="o">:</span> <span class="mi">8</span><span class="kt">px</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="na">overflow</span><span class="o">:</span> <span class="ni">hidden</span><span class="p">;</span> <span class="c1">// 配合圆角
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">  <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">border-color</span><span class="o">:</span> <span class="nv">$global-border-color-dark</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">border-color</span><span class="o">:</span> <span class="nv">$global-border-color-black</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="k">&amp;</span><span class="o">[</span><span class="nt">kept</span><span class="o">=</span><span class="nt">true</span><span class="o">]</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">display</span><span class="o">:</span> <span class="ni">block</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nc">.toc-title</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">display</span><span class="o">:</span> <span class="ni">flex</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">justify-content</span><span class="o">:</span> <span class="ni">space-between</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">line-height</span><span class="o">:</span> <span class="mi">2</span><span class="kt">em</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">padding</span><span class="o">:</span> <span class="mi">0</span><span class="mf">.5</span><span class="kt">rem</span> <span class="mi">1</span><span class="kt">rem</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">background</span><span class="o">:</span> <span class="nv">$code-background-color</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="na">cursor</span><span class="o">:</span> <span class="ni">pointer</span><span class="p">;</span> <span class="c1">// --- 新增: 表明标题可点击
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">    <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">dark</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">background</span><span class="o">:</span> <span class="nv">$code-background-color-dark</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="o">[</span><span class="nt">theme</span><span class="o">=</span><span class="nt">black</span><span class="o">]</span> <span class="k">&amp;</span> <span class="p">{</span> <span class="na">background</span><span class="o">:</span> <span class="nv">$code-background-color-black</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  <span class="nc">.toc-content</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="na">background-color</span><span class="o">:</span> <span class="ni">transparent</span><span class="p">;</span> <span class="c1">// --- 优化: 移除背景色, 使其与文章背景一致
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl">    <span class="o">&gt;</span> <span class="nt">nav</span> <span class="o">&gt;</span> <span class="nt">ul</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="na">margin</span><span class="o">:</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">      <span class="na">padding</span><span class="o">:</span> <span class="mf">.8</span><span class="kt">rem</span> <span class="mi">1</span><span class="kt">rem</span> <span class="mf">.8</span><span class="kt">rem</span> <span class="mi">1</span><span class="kt">rem</span><span class="p">;</span> <span class="c1">// 统一内边距
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></td></tr></table>
</div>
</div><h2 id="小结">小结</h2>
<p>最终方案是保留 Hugo 原有 TOC 生成逻辑，只在 SCSS 层做视觉增强。这样风险较低，不会影响目录锚点和滚动定位；取舍是样式对主题变量依赖较强，迁移到其他主题时需要重新适配。后续可以继续优化移动端折叠、当前阅读位置高亮，以及多级标题过深时的显示策略。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://gohugo.io/methods/page/tableofcontents/" target="_blank" rel="noopener noreffer">Hugo Table of Contents</a></li>
<li><a href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/:hover" target="_blank" rel="noopener noreffer">CSS <code>:hover</code> 伪类</a></li>
</ul>
<p>（2025-09-15@深圳）</p>
]]></content:encoded></item><item><title>折腾 | 用数据文件优化短代码的使用</title><link>https://philohao.com/2025/08/20250828/</link><pubDate>Thu, 28 Aug 2025 19:01:17 +0800</pubDate><dc:creator>Jianfeng.Hao</dc:creator><author>haojianfeng1997@gmail.com (Jianfeng.Hao)</author><guid isPermaLink="true">https://philohao.com/2025/08/20250828/</guid><description>之前网站的书影记录页面，数据和代码都写在 markdown 文件里，内容一多就很难维护。本文记录了通过 Hugo 的数据文件（Data Files）功能，将数据和内容分离开，从而优化维护体验的过程。</description><content:encoded><![CDATA[<p>本文解决的是 Hugo 页面里结构化书影音记录难维护的问题：把原本塞在 Markdown 里的 Shortcode 参数迁移到 Data Files 中，让内容数据、页面结构和展示代码分离，后续新增记录时只改 YAML 数据即可。</p>
<h2 id="适用场景">适用场景</h2>
<p>适合在 Hugo 中维护书单、影单、友链、项目列表等重复卡片内容的页面。只要内容条目字段相对固定、数量会持续增加，就可以考虑用 Data Files 替代一条条手写 Shortcode。</p>
<h2 id="背景">背景</h2>
<p>网站上有一个<a href="https://philohao.com/pages/mentalfood/" rel="">阅览</a>页面，用来记录我看过的书和电影。之前为了显示效果，自定义了一个叫 <code>mediacard</code> 的 Shortcode，可以在页面上生成卡片。</p>
<p>在 Markdown 文件里，每条记录都是一次 Shortcode 调用，像这样：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="nt">mediacard</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;大唐双龙传&#34;</span> 
</span></span><span class="line"><span class="cl">    <span class="na">coverurl</span><span class="o">=</span><span class="s">&#34;...&#34;</span> <span class="na">link</span><span class="o">=</span><span class="s">&#34;...&#34;</span> 
</span></span><span class="line"><span class="cl">    <span class="na">author</span><span class="o">=</span><span class="s">&#34;黄易&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;24-01&#34;</span> 
</span></span><span class="line"><span class="cl">    <span class="na">starscore</span><span class="o">=</span><span class="s">&#34;★★★&#34;</span> <span class="na">greystar</span><span class="o">=</span><span class="s">&#34;☆☆&#34;</span> 
</span></span><span class="line"><span class="cl">    <span class="na">intro</span><span class="o">=</span><span class="s">&#34;...&#34;</span> 
</span></span><span class="line"><span class="cl"><span class="p">&gt;</span>}}
</span></span></code></pre></td></tr></table>
</div>
</div><p>刚开始记录不多的时候，这个方法还行。但后来东西越来越多，整个 Markdown 文件就变得特别长，每次想加一条新记录，都要在文件里找很久，维护起来很麻烦。</p>
<h2 id="核心步骤">核心步骤</h2>
<h3 id="解决方法">解决方法</h3>
<p>主要思路就是把<strong>数据</strong>和<strong>页面</strong>分开。</p>
<p>Hugo 本身提供了 Data Files 功能，允许在 <code>/data</code> 目录下存放 YAML、JSON 或 TOML 格式的数据文件。这样，Markdown 文件就只负责页面结构和展示逻辑，而具体的书影条目数据，则统一放到数据文件里，方便管理。</p>
<h3 id="具体步骤">具体步骤</h3>
<h4 id="1-把数据转移到-data-文件夹">1. 把数据转移到 <code>data</code> 文件夹</h4>
<p>第一步是把之前写在 Markdown 文件里的所有条目数据，都整理出来，放到 <code>/data</code> 文件夹下，这种脏活累活当然是交给 AI 来完成啦！</p>
<p>我新建了 <code>books.yaml</code> 和 <code>movies.yaml</code> 两个文件。</p>
<p><strong>修改前 (在 <code>.md</code> 文件里):</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="nt">mediacard</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;法师故事&#34;</span> <span class="na">coverurl</span><span class="o">=</span><span class="s">&#34;...&#34;</span> <span class="na">author</span><span class="o">=</span><span class="s">&#34;索斯&#34;</span> <span class="na">type</span><span class="o">=</span><span class="s">&#34;24-08&#34;</span> <span class="err">...</span> <span class="p">&gt;</span>}}
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>修改后 (在 <code>data/books.yaml</code> 文件里):</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span><span class="lnt">7
</span><span class="lnt">8
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl">- <span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;法师故事&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">coverurl</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[https://bookcover.yuewen.com/qdbimg/349573/57821/600.webp](https://bookcover.yuewen.com/qdbimg/349573/57821/600.webp)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">link</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;[https://www.qidian.com/book/57821/](https://www.qidian.com/book/57821/)&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">author</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;索斯&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;24-08&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">starscore</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;★★★★&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">greystar</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;☆&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">intro</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;魔兽践踏，巨龙咆哮，巫师诅咒，魔法璀璨之光照耀知识灯塔！&#34;</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div><p>这样一来，所有的数据都集中管理了，之后增删改查也只用编辑这两个 <code>.yaml</code> 文件就行。</p>
<h4 id="2-写一个新的-shortcode">2. 写一个新的 Shortcode</h4>
<p>因为数据存放的位置变了，所以需要一个新的 Shortcode 来读取这些数据并显示出来。</p>
<p>我在 <code>layouts/shortcodes/</code> 目录下新建了一个 <code>medialist.html</code> 文件。这个 Shortcode 接收两个参数：第一个是数据文件名（比如 &ldquo;books&rdquo;），第二个是年份（比如 &ldquo;24&rdquo;），用来筛选对应年份的数据。</p>
<p>代码如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span><span class="lnt">21
</span><span class="lnt">22
</span><span class="lnt">23
</span><span class="lnt">24
</span><span class="lnt">25
</span><span class="lnt">26
</span><span class="lnt">27
</span><span class="lnt">28
</span><span class="lnt">29
</span><span class="lnt">30
</span><span class="lnt">31
</span><span class="lnt">32
</span><span class="lnt">33
</span><span class="lnt">34
</span><span class="lnt">35
</span><span class="lnt">36
</span><span class="lnt">37
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl">{{- $dataFile := .Get 0 -}}
</span></span><span class="line"><span class="cl">{{- $yearPrefix := .Get 1 -}}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{- if not $dataFile -}}
</span></span><span class="line"><span class="cl">  {{- errorf &#34;medialist shortcode in %s: 缺少第一个参数 (数据文件名)。&#34; .Page.Path -}}
</span></span><span class="line"><span class="cl">{{- end -}}
</span></span><span class="line"><span class="cl">{{- if not $yearPrefix -}}
</span></span><span class="line"><span class="cl">  {{- errorf &#34;medialist shortcode in %s: 缺少第二个参数 (年份)。&#34; .Page.Path -}}
</span></span><span class="line"><span class="cl">{{- end -}}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{- $mediaData := index site.Data $dataFile -}}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">{{- if $mediaData -}}
</span></span><span class="line"><span class="cl">  {{- $count := 0 -}}
</span></span><span class="line"><span class="cl">  {{- range $mediaData -}}
</span></span><span class="line"><span class="cl">    {{- if (hasPrefix .type $yearPrefix) -}}
</span></span><span class="line"><span class="cl">      {{- $count = add $count 1 -}}
</span></span><span class="line"><span class="cl">      <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;media&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;media-cover&#34;</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;background-image:url(\{\{ .coverurl \}\})&#34;</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;media-meta&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;media-meta-item title&#34;</span><span class="p">&gt;&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;\{\{ .link \}\}&#34;</span> <span class="na">target</span><span class="o">=</span><span class="s">&#34;_blank&#34;</span> <span class="na">rel</span><span class="o">=</span><span class="s">&#34;noopener noreferrer&#34;</span><span class="p">&gt;</span>\{\{ .title \}\}<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;&lt;</span><span class="nt">span</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;float:right;font-weight:400&#34;</span><span class="p">&gt;</span>\{\{ .type \}\}<span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;media-meta-item&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;author&#34;</span><span class="p">&gt;</span>\{\{ .author \}\}<span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">            <span class="p">&lt;</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;star-score&#34;</span><span class="p">&gt;</span>\{\{ .starscore \}\}<span class="p">&lt;</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;grey-star&#34;</span><span class="p">&gt;</span>\{\{ .greystar \}\}<span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;&lt;/</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">          <span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&#34;media-meta-item intro&#34;</span><span class="p">&gt;</span>\{\{ .intro | safeHTML \}\}<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">        <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">      <span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    {{- end -}}
</span></span><span class="line"><span class="cl">  {{- end -}}
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">  {{- if eq $count 0 -}}
</span></span><span class="line"><span class="cl">    <span class="p">&lt;</span><span class="nt">p</span> <span class="na">style</span><span class="o">=</span><span class="s">&#34;text-align: center; color: #888;&#34;</span><span class="p">&gt;</span>本年度暂无记录。<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  {{- end -}}
</span></span><span class="line"><span class="cl">{{- else -}}
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">p</span><span class="p">&gt;</span>警告：找不到数据文件 data/\{\{ $dataFile \}\}.yaml (或 .json/.toml)<span class="p">&lt;/</span><span class="nt">p</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">{{- end -}}
</span></span></code></pre></td></tr></table>
</div>
</div><p>这个 shortcode 的工作原理：</p>
<ol>
<li><code>{{ $dataFile := .Get 0 }}</code> 获取第一个参数<code>（&quot;books&quot;）</code></li>
<li><code>{{ $yearPrefix := .Get 1 }}</code> 获取第二个参数<code>（&quot;24&quot;）</code></li>
<li><code>{{ range $mediaData }}</code> 遍历数据文件中的所有条目</li>
<li><code>{{ if (hasPrefix .type $yearPrefix) }}</code> 是最关键的一行，它检查每个条目的 type 字段（如 <code>&quot;24-01&quot;</code>）是否以我们传入的年份前缀（<code>&quot;24&quot;</code>）开头，只有匹配的条目才会被渲染成 HTML</li>
<li>还增加了一个计数器，如果某一年份下没有任何记录，会显示“本年度暂无记录”</li>
</ol>
<h4 id="3-修改-markdown-文件">3. 修改 Markdown 文件</h4>
<p>最后一步，就是把原来的 Markdown 文件里大段的 <code>mediacard</code> 调用，换成新的 <code>medialist</code>。</p>
<p><strong>修改前 (2024年影剧部分):</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="nt">admonition</span> <span class="na">type</span><span class="o">=</span><span class="s">tip</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;影剧（20部）&#34;</span> <span class="na">open</span><span class="o">=</span><span class="s">false</span> <span class="p">&gt;</span>}}
</span></span><span class="line"><span class="cl">  {{<span class="p">&lt;</span> <span class="nt">mediacard</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;非诚勿扰3 (2023)&#34;</span> <span class="err">...</span> <span class="p">&gt;</span>}}
</span></span><span class="line"><span class="cl">  {{<span class="p">&lt;</span> <span class="nt">mediacard</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;葬送的芙莉莲 (2023)&#34;</span> <span class="err">...</span> <span class="p">&gt;</span>}}
</span></span><span class="line"><span class="cl">  ... (还有很多条)
</span></span><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="p">/</span><span class="nt">admonition</span> <span class="p">&gt;</span>}}
</span></span></code></pre></td></tr></table>
</div>
</div><p><strong>修改后:</strong></p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-markdown" data-lang="markdown"><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="nt">admonition</span> <span class="na">type</span><span class="o">=</span><span class="s">tip</span> <span class="na">title</span><span class="o">=</span><span class="s">&#34;影剧&#34;</span> <span class="na">open</span><span class="o">=</span><span class="s">false</span> <span class="p">&gt;</span>}}
</span></span><span class="line"><span class="cl">  {{<span class="p">&lt;</span> <span class="nt">medialist</span> <span class="err">&#34;</span><span class="na">movies</span><span class="err">&#34;</span> <span class="err">&#34;</span><span class="na">24</span><span class="err">&#34;</span> <span class="p">&gt;</span>}}
</span></span><span class="line"><span class="cl">{{<span class="p">&lt;</span> <span class="p">/</span><span class="nt">admonition</span> <span class="p">&gt;</span>}}
</span></span></code></pre></td></tr></table>
</div>
</div><p>原来几十行的内容，现在一行就够了，整个 Markdown 文件清爽了很多。</p>
<h2 id="最终效果">最终效果</h2>
<p>这么修改之后，解决了之前维护困难的问题。</p>
<ul>
<li><strong>Markdown 文件变干净了</strong>，只负责页面结构，不再包含具体数据。</li>
<li><strong>数据管理方便</strong>，所有条目都在 <code>.yaml</code> 文件里，一目了然。</li>
<li><strong>之后扩展也容易</strong>，这些数据可以很方便地在网站其他地方复用。</li>
</ul>
<p>总的来说，对 Hugo 这种需要管理大量结构化数据的情况，用 Data Files 功能是个不错的选择。</p>
<h2 id="小结">小结</h2>
<p>最终方案是用 <code>data/books.yaml</code>、<code>data/movies.yaml</code> 承载条目数据，再用 <code>medialist</code> Shortcode 按年份筛选并渲染。它牺牲了一点模板复杂度，换来了 Markdown 页面更清爽、数据更易批量维护的收益。后续可优化的方向，是继续抽象评分、分类和封面字段，并为数据文件增加更稳定的校验规则。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://gohugo.io/templates/data-templates/" target="_blank" rel="noopener noreffer">Hugo Data Templates</a></li>
<li><a href="https://gohugo.io/content-management/shortcodes/" target="_blank" rel="noopener noreffer">Hugo Shortcodes</a></li>
</ul>
<p>（2025-08-28@深圳）</p>
]]></content:encoded></item><item><title>折腾 | 博文热力图</title><link>https://philohao.com/2024/01/20240110/</link><pubDate>Wed, 10 Jan 2024 03:01:17 +0800</pubDate><dc:creator>Jianfeng.Hao</dc:creator><author>haojianfeng1997@gmail.com (Jianfeng.Hao)</author><guid isPermaLink="true">https://philohao.com/2024/01/20240110/</guid><description>博文热力图折腾记录，介绍用 Hugo Shortcode 和 ECharts 展示发文节奏。</description><content:encoded><![CDATA[<p>本文解决的是归档页缺少直观写作节奏的问题：借助 Hugo Shortcode 引入 ECharts 热力图，把每天的发文数量转换成日历小方块，方便回看写作频率和内容沉淀。</p>
<h2 id="适用场景">适用场景</h2>
<p>适合有持续写作习惯、希望在归档页展示产出节奏的 Hugo 博客。它也适合需要把站点数据做成轻量可视化模块的场景，比如文章数量、阅读记录或照片更新频率。</p>
<h2 id="核心步骤">核心步骤</h2>
<p>最近看到<a href="https://blog.douchi.space/hugo-blog-heatmap/#115-%E6%9B%B4%E6%96%B0---%E6%AF%8F%E5%A4%A9%E5%A4%9A%E7%AF%87%E6%96%87%E7%AB%A0" target="_blank" rel="noopener noreffer">椒盐豆豉</a>更新文章给博客增加了文章热力图，直接被种草。这种展现方式能直接的显示最近的产量（没眼看没眼看🤣），一方面能够作为催更动力让我别太懒，另一方面如果坚持写作贴满小瓷砖的话也能提供满满成就感。不过我最看重的一点是它使我回顾以往的文章更加容易也更有 feel，我可太爱循着日历回看文章这种形式了！</p>
<ul>
<li><i class="far fa-check-square fa-fw"></i> 我是用 shortcodes 形式<a href="https://github.com/DivinerHJF/hugo-theme-Aether/commit/0f3df8c716da8838beeda84b0d7a7bad9df1b2c3" target="_blank" rel="noopener noreffer">引入的代码</a>，这样子在想引入的页面直接嵌入短代码即可，目前把成品放在了 <a href="https://philohao.com/posts/" rel="">归档</a> 页面了。</li>
<li><i class="far fa-check-square fa-fw"></i> 我按着 Echart 官方文档和其他博主的样式教程修改了一些显示样式，使这个热力图控件和我的博客风格更搭，同时也调整了一下颜色控制部分的代码，使 Echart 图表自带的自动适配暗色模式的特性可以生效。</li>
</ul>
<h2 id="最终效果">最终效果</h2>
<p>热力图被放在归档页，作为文章列表之前的总览入口。它既能展示某段时间的写作密度，也能提醒自己哪些阶段断更较久，回看时比单纯的年月列表更有时间感。</p>
<h2 id="小结">小结</h2>
<p>最终方案选择 Shortcode 封装 ECharts 配置，优点是复用方便、页面嵌入简单；取舍是需要维护一段图表配置代码，并关注主题暗色模式下的颜色表现。后续可以继续优化移动端显示、年份切换，以及多篇文章同日发布时的提示信息。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://blog.douchi.space/hugo-blog-heatmap/#115-%E6%9B%B4%E6%96%B0---%E6%AF%8F%E5%A4%A9%E5%A4%9A%E7%AF%87%E6%96%87%E7%AB%A0" target="_blank" rel="noopener noreffer">椒盐豆豉：Hugo 博客热力图</a></li>
<li><a href="https://github.com/DivinerHJF/hugo-theme-Aether/commit/0f3df8c716da8838beeda84b0d7a7bad9df1b2c3" target="_blank" rel="noopener noreffer">引入热力图的主题提交</a></li>
</ul>
<p>（2024-01-10@广州）</p>
]]></content:encoded></item><item><title>折腾 | 图片瀑布流</title><link>https://philohao.com/2024/01/20240107/</link><pubDate>Sun, 07 Jan 2024 11:43:07 +0800</pubDate><dc:creator>Jianfeng.Hao</dc:creator><author>haojianfeng1997@gmail.com (Jianfeng.Hao)</author><guid isPermaLink="true">https://philohao.com/2024/01/20240107/</guid><description>图片瀑布流折腾记录，介绍 Hugo 文章中多图展示和相册化排版的实现思路。</description><content:encoded><![CDATA[<p>本文解决的是博客多图展示占用空间大、排版不够相册化的问题：在不引入复杂组件的前提下，用 Hugo 内容组织配合 CSS 多列布局，让照片在文章和相册页面里以瀑布流形式展示。</p>
<h2 id="适用场景">适用场景</h2>
<p>适合需要在 Hugo 文章中集中展示多张照片、游记配图或作品集的页面。它的目标不是做完整图片管理系统，而是用尽量轻量的样式，让图片阅读更紧凑、更美观。</p>
<h2 id="核心步骤">核心步骤</h2>
<p>最近在给一系列博文配图，随着添加的图片多了之后，一直想实现的「图片瀑布流」的心思又活络起来了。Google 大法好，最终找到了<a href="https://immmmm.com/hi-waterfall-js/" target="_blank" rel="noopener noreffer">图片瀑布流折腾记</a>、<a href="https://immmmm.com/about-images-gird/" target="_blank" rel="noopener noreffer">Hugo 多图排版这样来</a> 这两篇文章，两种不同的方法都很简单，都可以实现我想要的效果，感恩！</p>
<p>目前我主要在网站的两个地方进行应用，第一种是在文章中大量展示自己拍的照片时达到类似相册效果，这样既美观又省网页空间；另一种是专门的「<a href="https://philohao.com/pages/album/" rel="">回忆</a>」页面，不断添加我自己拍的较为满意的照片，相当于照片画廊。</p>
<p>目前对网站图片进行了以下操作：</p>
<ul>
<li><i class="far fa-check-square fa-fw"></i> 圆角处理：<code>border-radius: 5px;</code></li>
<li><i class="far fa-check-square fa-fw"></i> 阴影效果：<code>box-shadow: 0px 0px 5px rgba(0,0,0,0.3);</code></li>
<li><i class="far fa-check-square fa-fw"></i> 滑过放大：<code>img:hover</code> 和 <code>transform</code> 的<a href="https://www.cnblogs.com/chervehong/p/10286961.html" target="_blank" rel="noopener noreffer">纯 CSS 方案</a></li>
<li><i class="far fa-check-square fa-fw"></i> 多图排版：<code>column-count</code> 和 <code>p:has(&gt; img:nth-child)</code> 的<a href="https://immmmm.com/about-images-gird/" target="_blank" rel="noopener noreffer">纯 CSS 方案</a></li>
</ul>
<h2 id="最终效果">最终效果</h2>
<p><img
        class="lazyload"
        data-src="https://image.philohao.com/images/retouch_2023122421225662.jpg"
        data-srcset="https://image.philohao.com/images/retouch_2023122421225662.jpg, https://image.philohao.com/images/retouch_2023122421225662.jpg 1.5x, https://image.philohao.com/images/retouch_2023122421225662.jpg 2x"
        data-sizes="auto"
        alt="https://image.philohao.com/images/retouch_2023122421225662.jpg"
        title="https://image.philohao.com/images/retouch_2023122421225662.jpg"
    />
<img
        class="lazyload"
        data-src="https://image.philohao.com/images/retouch_2023122421215472.jpg"
        data-srcset="https://image.philohao.com/images/retouch_2023122421215472.jpg, https://image.philohao.com/images/retouch_2023122421215472.jpg 1.5x, https://image.philohao.com/images/retouch_2023122421215472.jpg 2x"
        data-sizes="auto"
        alt="https://image.philohao.com/images/retouch_2023122421215472.jpg"
        title="https://image.philohao.com/images/retouch_2023122421215472.jpg"
    />
<img
        class="lazyload"
        data-src="https://image.philohao.com/images/20231224123258_IMG_1435.JPG"
        data-srcset="https://image.philohao.com/images/20231224123258_IMG_1435.JPG, https://image.philohao.com/images/20231224123258_IMG_1435.JPG 1.5x, https://image.philohao.com/images/20231224123258_IMG_1435.JPG 2x"
        data-sizes="auto"
        alt="https://image.philohao.com/images/20231224123258_IMG_1435.JPG"
        title="https://image.philohao.com/images/20231224123258_IMG_1435.JPG"
    /></p>
<h2 id="小结">小结</h2>
<p>最终方案倾向于纯 CSS 实现，优点是简单、无需额外 JavaScript，和 Hugo 原本的 Markdown 图片写法也比较兼容；取舍是瀑布流控制能力不如专门图库组件精细。后续可以继续优化懒加载、移动端列数和图片说明文字，让相册页面在性能和可读性之间更平衡。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://immmmm.com/hi-waterfall-js/" target="_blank" rel="noopener noreffer">图片瀑布流折腾记</a></li>
<li><a href="https://immmmm.com/about-images-gird/" target="_blank" rel="noopener noreffer">Hugo 多图排版这样来</a></li>
<li><a href="https://www.cnblogs.com/chervehong/p/10286961.html" target="_blank" rel="noopener noreffer">CSS3 图片 Hover 放大效果</a></li>
</ul>
<p>（2023-12-16@广州）</p>
]]></content:encoded></item><item><title>折腾 | 博客字体变更记</title><link>https://philohao.com/2023/11/20231130/</link><pubDate>Thu, 30 Nov 2023 20:39:12 +0800</pubDate><dc:creator>Jianfeng.Hao</dc:creator><author>haojianfeng1997@gmail.com (Jianfeng.Hao)</author><guid isPermaLink="true">https://philohao.com/2023/11/20231130/</guid><description>博客字体变更记录，说明中文阅读体验、字体选择和样式调整过程。</description><content:encoded><![CDATA[<p>本文解决的是博客中文阅读体验不够统一的问题：通过更换正文字体、调整背景色、选中文本、对齐方式和标题样式，让 Hugo 博客在长文阅读时更沉静、更清晰，也更符合当前的内容气质。</p>
<h2 id="适用场景">适用场景</h2>
<p>如果博客以中文长文为主，并且希望通过较小的 CSS 改动提升阅读质感，可以参考这次折腾。它尤其适合已经有稳定主题、但觉得默认字体和标题层级略显松散的 Hugo 站点。</p>
<h2 id="核心步骤">核心步骤</h2>
<p>今天更换了新的博客字体 ——「<a href="https://chinese-font.netlify.app/fonts/jhlst/%E4%BA%AC%E8%8F%AF%E8%80%81%E5%AE%8B%E4%BD%93v1_007/" target="_blank" rel="noopener noreffer">京华老宋体</a>」，用的是<a href="https://chinese-font.netlify.app/" target="_blank" rel="noopener noreffer">中文网字计划</a>提供的 CDN 分发，引入十分方便。配合字体也对博客的相关方面进行了修缮，使调性更加统一，处女座强迫症哈哈哈。</p>
<p>这里罗列一下具体做的改变：</p>
<ul>
<li><i class="far fa-check-square fa-fw"></i> 字体改为「京华老宋体」，博客的文字看起来既有美感韵律又不缺辨识区分度，还莫名添了几分思考的力量，读起来很有感觉！</li>
<li><i class="far fa-check-square fa-fw"></i> 默认白色背景下字体显得发虚有点儿累眼，于是做旧了博客主体背景色，调性立马出来了，整体看下来更像是一方用文字记录想法的小天地了，给人的感觉是沉静、稳重，我很喜欢😊。</li>
<li><i class="far fa-check-square fa-fw"></i> 还把选中文字的显示效果也改了，不同于之前的淡蓝底让配色显得嘈杂，黑底白字更显简洁有力！</li>
<li><i class="far fa-check-square fa-fw"></i> 文本对齐方式改成两端对齐，这样子即使是大段文字看起来也更加整洁了，不会给人参差错落的视觉印象。</li>
<li><i class="far fa-check-square fa-fw"></i> 标题格式方面，仅保留二级标题的「<strong>#</strong>」前缀，并将前缀向左平移不占用文字区域空间，使文字区域从标题到内容的缩进保持一致。</li>
</ul>
<h2 id="最终效果">最终效果</h2>
<p>整体效果是文字区域更像一个安静的阅读容器：字体有辨识度，背景和选中态降低了视觉噪音，标题缩进也更稳定。谈到标题，为了避免滥用标题以及保持文章结构的简洁性，之后写文章也打算尽量保持一篇文章的主标题作为一级标题，最多用到三级标题。</p>
<h2 id="小结">小结</h2>
<p>最终方案选择了外部中文字体 CDN 加少量 CSS 微调，优点是改动成本低、视觉收益明显；取舍是需要接受字体资源对外部服务的依赖。后续可优化的方向，是继续梳理正文、代码块、引用块等细节样式，让中文排版规则在更多内容类型里保持一致。</p>
<h2 id="参考资料">参考资料</h2>
<ul>
<li><a href="https://chinese-font.netlify.app/fonts/jhlst/%E4%BA%AC%E8%8F%AF%E8%80%81%E5%AE%8B%E4%BD%93v1_007/" target="_blank" rel="noopener noreffer">京华老宋体</a></li>
<li><a href="https://chinese-font.netlify.app/" target="_blank" rel="noopener noreffer">中文网字计划</a></li>
</ul>
<p>（2023-11-30@广州）</p>
]]></content:encoded></item><item><title>Hugo 操作纪要-个人向</title><link>https://philohao.com/2019/09/20190917/</link><pubDate>Tue, 17 Sep 2019 14:28:00 +0800</pubDate><dc:creator>Jianfeng.Hao</dc:creator><author>haojianfeng1997@gmail.com (Jianfeng.Hao)</author><guid isPermaLink="true">https://philohao.com/2019/09/20190917/</guid><description>个人 Hugo 操作纪要，记录新建内容、本地预览和常用维护命令。</description><content:encoded><![CDATA[<h2 id="基本使用">基本使用</h2>
<h3 id="hugo-命令">hugo 命令</h3>
<p>一般的 hugo 命令包括 <strong>命令</strong> 及 <strong>参数</strong> 两项，作为个人博主日常主要使用 <code>生成新内容</code> 和 <code>本地运行</code> 两个命令，具体的使用方法如下：</p>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span><span class="lnt">16
</span><span class="lnt">17
</span><span class="lnt">18
</span><span class="lnt">19
</span><span class="lnt">20
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">使用方法:
</span></span><span class="line"><span class="cl">  hugo
</span></span><span class="line"><span class="cl">  hugo [flags]
</span></span><span class="line"><span class="cl">  hugo [command]
</span></span><span class="line"><span class="cl">  hugo [command] [flags]
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">节选的 command:
</span></span><span class="line"><span class="cl">  new         为你的站点创建新的内容
</span></span><span class="line"><span class="cl">  server      一个高性能的 web 服务器
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">节选的 flags:
</span></span><span class="line"><span class="cl">  -D, --buildDrafts                包括被标记为 draft 的文章
</span></span><span class="line"><span class="cl">  -E, --buildExpired               包括已过期的文章
</span></span><span class="line"><span class="cl">  -F, --buildFuture                包括将在未来发布的文章
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">举几个栗子:
</span></span><span class="line"><span class="cl">  hugo -D                          生成静态文件并包括 draft 为 true 的文章
</span></span><span class="line"><span class="cl">  hugo new post/new-content.md     新建一篇文章
</span></span><span class="line"><span class="cl">  hugo new site mysite             新建一个称为 mysite 的站点
</span></span><span class="line"><span class="cl">  hugo server -E                   启动服务器并包括已过期的文章
</span></span></code></pre></td></tr></table>
</div>
</div><p>更多的 hugo 命令可以参考 <a href="https://gohugo.io/getting-started/usage/" target="_blank" rel="noopener noreffer">官方文档</a>。</p>
<h3 id="目录结构">目录结构</h3>
<ol>
<li>站点目录结构</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">~/blog $ tree -L 1
</span></span><span class="line"><span class="cl">.                   # 对比             Hexo
</span></span><span class="line"><span class="cl">├── archetypes/     # 文章模板          scaffolds/
</span></span><span class="line"><span class="cl">├── content/        # 文章目录          source/_posts/
</span></span><span class="line"><span class="cl">├── data/           # Hugo 数据文件     source/_data/
</span></span><span class="line"><span class="cl">├── layouts/        # 布局模板
</span></span><span class="line"><span class="cl">├── public/         # 生成的静态文件     public/
</span></span><span class="line"><span class="cl">├── resources/      # Hugo 缓存
</span></span><span class="line"><span class="cl">├── static/         # 网站的静态文件     source/
</span></span><span class="line"><span class="cl">├── themes/         # 主题目录          themes/
</span></span><span class="line"><span class="cl">└── config.toml     # 配置文件          _config.yml
</span></span></code></pre></td></tr></table>
</div>
</div><ol start="2">
<li>主题目录结构</li>
</ol>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt">1
</span><span class="lnt">2
</span><span class="lnt">3
</span><span class="lnt">4
</span><span class="lnt">5
</span><span class="lnt">6
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-fallback" data-lang="fallback"><span class="line"><span class="cl">~/blog/themes/divine $ tree -L 1
</span></span><span class="line"><span class="cl">.
</span></span><span class="line"><span class="cl">├── archetypes/
</span></span><span class="line"><span class="cl">├── images/
</span></span><span class="line"><span class="cl">├── layouts/
</span></span><span class="line"><span class="cl">└── static/
</span></span></code></pre></td></tr></table>
</div>
</div><p>站点目录下的文件可以覆盖主题目录下的相应文件——这意味着可以在不修改主题文件的前提下方便地定制主题。在 Hugo 中，如果想要定制主题，只需在站点目录下新建相应的文件即可。这是非常利于主题的维护的，只需使用 Git 的 submodule 的方式安装 Hugo 的主题，然后更新时只需直接在站点根目录下敲一条命令回车即可，非常方便！</p>
<h2 id="文章设置">文章设置</h2>
<h3 id="文章模板">文章模板</h3>
<div class="highlight"><div class="chroma">
<table class="lntable"><tr><td class="lntd">
<pre tabindex="0" class="chroma"><code><span class="lnt"> 1
</span><span class="lnt"> 2
</span><span class="lnt"> 3
</span><span class="lnt"> 4
</span><span class="lnt"> 5
</span><span class="lnt"> 6
</span><span class="lnt"> 7
</span><span class="lnt"> 8
</span><span class="lnt"> 9
</span><span class="lnt">10
</span><span class="lnt">11
</span><span class="lnt">12
</span><span class="lnt">13
</span><span class="lnt">14
</span><span class="lnt">15
</span></code></pre></td>
<td class="lntd">
<pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">title</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;{{ replace .Name &#34;</span>-<span class="s2">&#34; &#34;</span><span class="w"> </span><span class="s2">&#34; | title }}&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">date</span><span class="p">:</span><span class="w"> </span>{{<span class="w"> </span><span class="l">.Date }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">categories</span><span class="p">:</span><span class="w"> </span><span class="l">Diary, Reading, Studying</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">tags</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">x</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">xx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">xxx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">type</span><span class="p">:</span><span class="w"> </span><span class="s2">&#34;home&#34;</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">toc</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">mathjax</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">codes</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">bash, diff, markdown, python, r]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">comments</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">vertical</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">image</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">draft</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="w">
</span></span></span></code></pre></td></tr></table>
</div>
</div>]]></content:encoded></item></channel></rss>