快轉到主要內容
  1. 全部文章/

Hugo Blowfish主題|外觀功能修改日誌

··4776 字·10 分鐘
目錄
Hugo Blowfish 主題客製化 - 本文屬於一個選集。
§ 1: 本文

前言
#

這裡記錄了一些我的網站微調及設定,主題是使用「Blowfish 」。


網站外觀
#

首頁簡介
#

參考本網站首頁,作者名下方有幾行介紹文字。

先到/config/_default/languages.toml中找到[params.author],在下面插入

welcomeMessage = "你的介紹" # 要用 HTML 寫,非 Markdown

接著看你是用什麼主頁佈局(Layout),將/themes/blowfish/layouts/partials/home底下的對應範本複製到/layouts/partials中,並在想要的位置插入:

{{ with .Site.Params.Author.welcomeMessage }}
  <div class="max-w-2xl text-xs leading-relaxed text-neutral-700 dark:text-neutral-300" style="margin: 0.5rem 0 0.25rem 0;">
    {{ . | markdownify }}
  </div>

我是將它插在下面這段Author Headline的下方

{{ with .Site.Params.Author.headline }}
  <h2 class="mt-0 mb-0 text-xl text-neutral-800 dark:text-neutral-300">
    {{ . | markdownify }}
  </h2>
{{ end }}

Header 網站標題響應式隱藏
#

我的主網站Yoz Music 鼓手柚子 因網站標題較長,在手機上可能會在手機上可能會跟 Header 中的 Navbar 物件衝突導致換行。
Blowfish 預設只能單純隱藏網站標題文字,並沒有響應式設定,於是我在custom.css中增加以下設定,讓手機上不顯示標題文字。

@media screen and (max-width: 768px) {
  nav.flex.space-x-3 > a {
    display: none !important;
  }
}

主頁作者名換行機制
#

herobackground 佈局(Layout)如果有設定作者便會在首頁顯示「作者頭貼」與「名字」,預設則是網站名,可參考本站首頁
在我的主網站Yoz Music 鼓手柚子 與個人部落格「YoZ Blog」中,作者名為DrummerYoZ 鼓手柚子,因字數較長,在手機上必定會換行,而原始的換行機制單純,顯示的效果不太美觀,類似於:

Drummeryoz 鼓手
     柚子

我讓它透過空格將DrummerYoZ鼓手柚子識別為兩個部分,強制需要換行時,直接將鼓手柚子換到下一行,像是下面顯示的樣式:

DrummerYoZ
  鼓手柚子

我複製了/themes/blowfish/layouts/partials/home/background.html/layouts/partials/home/background.html,並編輯將:

<h1 class="mb-2 text-4xl font-extrabold text-neutral-800 dark:text-neutral-200">
  {{ .Site.Params.Author.name | default .Site.Title }}
</h1>

改為:

{{ $name := .Site.Params.Author.name | default .Site.Title }}
{{ $parts := split $name " " }}
<h1 class="text-4xl font-extrabold flex flex-wrap justify-center w-full mb-0">
  <span class="whitespace-nowrap">{{ index $parts 0 }}</span>&nbsp;<span class="whitespace-nowrap">{{ index $parts 1 }}</span>
</h1>

Header 多語言網站切換按鈕隱藏文字
#

樣式請直接參考本站 Header。 將/themes/blowfish/layouts/partials路徑下的translations.html複製到/layouts/partials編輯,並將下面這段直接刪除,或是註記起來。

<div
  class="text-sm font-medium text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"
  title="{{ .Title }}">
  {{- i18n "global.language" | markdownify -}}
</div>

我直接把它註記起來了,免得之後需要時又要重寫。

<!--
<div
  class="text-sm font-medium text-gray-500 hover:text-primary-600 dark:hover:text-primary-400"
  title="{{ .Title }}">
  {{- i18n "global.language" | markdownify -}}
</div>
-->

3D網格加代碼瀑布風格
#

本網站背景。參考Hugo 動畫背景|3D網格加代碼瀑布風格


列表 Card View 分類與標籤分別顯示
#

首先在 /config/_default/params.toml 中添加:

[article]
  # 其他既有參數...
  showTaxonomies = true  # 必須為 true 才能顯示分類和標籤
  showCategoryAndTagSeperate = true  # 控制是否分開顯示分類和標籤

接著修改 Partial 模板,將/themes/blowfish/layouts/partials/article-meta路徑下的basic.html複製到/layouts/partials/article-meta並編輯:

{{ if .Params.showTaxonomies | default (.Site.Params.article.showTaxonomies | default false) }}
  {{ if .Params.showCategoryAndTagSeperate | default (.Site.Params.article.showCategoryAndTagSeperate | default false) }}
    {{/* 分開顯示 categories 和 tags */}}
    {{ with (.GetTerms "categories") }}
      <div class="flex flex-row flex-wrap items-center">
        <span class="mr-2 font-medium">{{ i18n "categories" | title }}: </span>
        {{ range . }}
          <a class="relative mt-1 mr-2" href="{{ .RelPermalink }}">
            {{ partial "badge.html" .LinkTitle }}
          </a>
        {{ end }}
      </div>
    {{ end }}

    {{ with (.GetTerms "tags") }}
      <div class="flex flex-row flex-wrap items-center {{ if not (eq (len ($context.GetTerms "categories")) 0) }}mt-1{{ end }}">
        <span class="mr-2 font-medium">{{ i18n "tags" | title }}: </span>
        {{ range . }}
          <a class="relative mt-1 mr-2" href="{{ .RelPermalink }}">
            {{ partial "badge.html" .LinkTitle }}
          </a>
        {{ end }}
      </div>
    {{ end }}
  {{ else }}
    {{/* 原始顯示方式 */}}
    <div class="flex flex-row flex-wrap items-center">
      {{ range $taxonomy, $terms := .Site.Taxonomies }}
        {{ if and (not (eq $taxonomy "authors")) (not (eq $taxonomy "series")) }}
          {{ if (gt (len ($context.GetTerms $taxonomy)) 0) }}
            {{ range $context.GetTerms $taxonomy }}
              <a class="relative mt-1 mr-2" href="{{ .RelPermalink }}">
                {{ partial "badge.html" .LinkTitle }}
              </a>
            {{ end }}
          {{ end }}
        {{ end }}
      {{ end }}
    </div>
  {{ end }}
{{ end }}

如要為多語言網站設定翻譯,在對應的 i18n 文件(如 /i18n/zh-tw.yaml)中加入:

categories: "分類"
tags: "標籤"

也可透過 front matter 為個別文章設定:

---
title: "文章標題"
date: 2025-10-30
showCategoryAndTagSeperate: true  
  # 覆蓋預設設置,預設為 true 則在此改為 false 讓這篇文章的分類與標籤在 card view 中混合顯示;預設為 false 則設為 true 只讓這篇文章的分類與標籤在 card view 中分開顯示
---

分類頁標籤
#

我是直接用 Blowfish 預設的 Shortcode Button ,但是連續使用時,預設會長下面這樣:

A B C

我把它改成:

A B C

要改成這個樣式的話,將/themes/blowfish/layouts/shortcodes路徑下的button.html複製到/layouts/shortcodes並編輯,在role="button"下行加入:

style="display: inline-block; margin-right: 5px; margin-bottom: 8px;"

Footer 區塊 #

橫向三區塊
#

原先 Blowfish 主題的 Footer 只有簡單橫向 Menu,請參考其官方網站
我將Footer 分為橫向三個區塊,左邊為文字區塊;中間區塊顯示原先設定的 Menu 內容,只是改成垂直排列;右邊區塊放置聯絡表單,請直接參考本網站最下方 Footer 部分。


版權聲明
#

Copyright © 2025-2026 yoz.log. All rights reserved.
本網站全站文章禁止全文轉載,可分享除內文特別標明禁止使用任何形式分享之文章,引用請註明網站名稱及文章網址,並遵守【姓名標示-非商業性-禁止改作 4.0 國際】授權條款。如需商業使用請來信詢問。

/config/_default/languages.toml中找到[params]段落下的copyright = "Copy, _right?_ :thinking_face:",改為:
copyright = "Copyright &copy; 網站創建年份-{ year } 部落格名. All rights reserved."

如果要加入像上面一樣的第二行版權聲明詳細內容,到/layouts/partials/footer.html中(如使用主題預設的,直接複製一份過來),找到:

<div class="flex items-center justify-between">
  {{/* Copyright */}}
  {{ if .Site.Params.footer.showCopyright | default true }}
    <p class="text-sm text-neutral-500 dark:text-neutral-400">
      {{- with replace .Site.Params.copyright "{ year }" now.Year }}
        {{ . | markdownify }}
      {{- else }}
        &copy;
        {{ now.Format "2006" }}
        {{ .Site.Params.Author.name | markdownify }}
      {{- end }}
    </p>
  {{ end }}

</p>下行加入:

<p class="text-center text-sm text-neutral-500 dark:text-neutral-400">
  輸入版權聲明詳細內容
</p>

網站運作時間統計
#

本網站已穩定運作 1年2個月3天

參考自Hugo Stack 主题装修笔记 Part 3 ,該文章中的方法在我這不能用,且我還增加了多語言翻譯功能,改成像下方這樣:

上一段提到的footer.html最後一行{{ end }}下方插入:

<!-- 網站運作時間顯示區域 -->
<section class="text-center mt-4 text-xs text-neutral-600 dark:text-neutral-400">
  本網站已穩定運作
  <span id="runningdays" class="font-bold text-primary-500 dark:text-primary-400"></span>
</section>
<!-- 引用 js/running-time.js 檔案 -->
<script src="{{ "js/running-time.js" | relURL }}"></script>

接著創建在/static/js建立running-time.js並編輯:

(function() {
    let s1 = '更改成你的網站建立日期,例如:2025-11-03';
    s1 = new Date(s1.replace(/-/g, "/"));
    
    // 內建翻譯字典
    const translations = {
        'en': { years: ' years ', months: ' months ', days: ' days' },
        'zh-tw': { years: '年', months: '個月', days: '天' },
        'zh-cn': { years: '年', months: '个月', days: '天' },
        'ko': { years: '년 ', months: '개월 ', days: '일' }
    };
    
    function updateRunningTime() {
        let s2 = new Date();
        
        let years = s2.getFullYear() - s1.getFullYear();
        let months = s2.getMonth() - s1.getMonth();
        let days = s2.getDate() - s1.getDate();
        
        if (days < 0) {
            months -= 1;
            let prevMonth = new Date(s2.getFullYear(), s2.getMonth(), 0);
            days += prevMonth.getDate();
        }
        if (months < 0) {
            years -= 1;
            months += 12;
        }

        // 自動偵測當前語言(預設英文)
        let lang = document.documentElement.lang || 'en';
        lang = lang.toLowerCase();
        let t = translations[lang] || translations['en'];

        let result = years + t.years + months + t.months + days + t.days;
        
        let element = document.getElementById('runningdays');
        if (element) {
            element.innerHTML = result;
        }
    }
    
    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', updateRunningTime);
    } else {
        updateRunningTime();
    }
    
    setInterval(updateRunningTime, 60000);
})();

發布文章及總字數統計
#

已發布了 10 篇文章 · 總計 1萬2千345個字

一樣參考Hugo Stack 主题装修笔记 Part 3

我增加了class的類型,以配合 Blowfish 主題顏色及字體大小,且將原先只顯示x萬x千的格式改成增加百位數後並直接以數字顯示:

<!-- Add total page and word count time -->
<section class="totalcount text-center text-xs text-neutral-500 dark:text-neutral-400 mt-2">
  {{ $scratch := newScratch }}
  {{ range (where .Site.Pages "Kind" "page") }}
  {{ $scratch.Add "total" .WordCount }}
  {{ end }}
  {{ $totalWords := $scratch.Get "total" }}
  {{ if $totalWords }}
  {{ $wan := div $totalWords 10000 }}
  {{ $remainder := mod $totalWords 10000 }}
  {{ $qian := div $remainder 1000 }}
  {{ $finalRemainder := mod $remainder 1000 }}
  已發布了 {{ len (where .Site.RegularPages "Section" "posts") }} 篇文章 · 總計 
  {{ if gt $wan 0 }}{{ $wan }}萬{{ end }}{{ if gt $qian 0 }}{{ $qian }}千{{ end }}{{ if gt $finalRemainder 0 }}{{ $finalRemainder }}{{ end }}個字
  {{ end }}
</section>

文章內容相關
#

添加連結圖標
#

參考Hugo Blowfish主題|添加連結圖標


macOS 視窗風格可折疊程式碼區塊
#

長這樣
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
可折疊喔

參考Hugo Blowfish 主題|程式碼區塊樣式與折疊


新增額外 Hero 佈局樣式
#

使用 Blowfish 2.92 版本為基礎更改,共兩種。

第一種:與 background 樣式相同,但是只使用預設圖片當作背景(不使用文章 feature 圖)。

先複製 /themes/blowfish/layouts/partials/hero路徑下的thumbAndBackground.html/layouts/partials/hero並改名為default.html,程式碼改成下面這樣:

{{ $disableImageOptimization := site.Store.Get "disableImageOptimization" }}

{{/* === Background === */}}
{{ $useDefault := false }}
{{ $images := .Resources.ByType "image" }}
{{ $background := $images.GetMatch "*background*" }}
{{ $backgroundURL := "" }}

{{ if not (or $background $backgroundURL) }}
  {{ $default := site.Store.Get "defaultBackgroundImage" }}
  {{ if $default.url }}
    {{ $backgroundURL = $default.url }}
    {{ $useDefault = true }}
  {{ else if $default.obj }}
    {{ $background = $default.obj }}
    {{ $useDefault = true }}
  {{ end }}
{{ end }}

{{ if not (or $background $backgroundURL) }}
  {{ range slice "*cover*" "*thumbnail*" "*feature*" }}
    {{ if not $background }}{{ $background = $images.GetMatch . }}{{ end }}
  {{ end }}
{{ end }}

{{/* generate image URL if not hotlink */}}
{{ if not $backgroundURL }}
  {{ with $background }}
    {{ $backgroundURL = .RelPermalink }}
    {{ if not (or $disableImageOptimization (eq .MediaType.SubType "svg")) }}
      {{ $size := site.Store.Get "backgroundImageWidth" }}
      {{ $backgroundURL = (.Resize $size).RelPermalink }}
    {{ end }}
  {{ end }}
{{ end }}

{{ $isParentList := eq (.Scratch.Get "scope") "list" }}
{{ $shouldBlur := $.Params.layoutBackgroundBlur | default (or
  (and ($.Site.Params.article.layoutBackgroundBlur | default true) (not $isParentList))
  (and ($.Site.Params.list.layoutBackgroundBlur | default true) ($isParentList))
  )
}}
{{ $shouldAddHeaderSpace := $.Params.layoutBackgroundHeaderSpace | default (or
  (and ($.Site.Params.article.layoutBackgroundHeaderSpace | default true) (not $isParentList))
  (and ($.Site.Params.list.layoutBackgroundHeaderSpace | default true) ($isParentList))
  )
}}

{{ if $shouldAddHeaderSpace | default true }}
  <div id="hero" class="h-[150px] md:h-[200px]"></div>
{{ end }}
<div class="single_hero_background nozoom fixed inset-x-0 top-0 h-[800px]">
  {{ with $backgroundURL }}
    {{ $style := "" }}
    {{ $defaultPosition := cond $useDefault site.Params.imagePosition false }}
    {{ with $.Params.imagePosition | default $defaultPosition }}
      {{ $style = printf "object-position: %s;" . }}
    {{ end }}
    <img
      id="background-image-main"
      src="{{ . }}"
      alt=""
      role="presentation"
      loading="eager"
      decoding="async"
      fetchpriority="high"
      class="absolute inset-0 h-full w-full object-cover"
      {{ if $style }}style="{{ $style | safeCSS }}"{{ end }}>
  {{ end }}
  <div
    class="from-neutral absolute inset-0 bg-gradient-to-t to-transparent mix-blend-normal dark:from-neutral-800"></div>
  <div
    class="from-neutral to-neutral absolute inset-0 bg-gradient-to-t opacity-30 mix-blend-normal dark:from-neutral-800 dark:to-neutral-800 dark:opacity-60"></div>
</div>

{{ if $shouldBlur | default false }}
  <div
    id="background-blur"
    class="fixed opacity-0 inset-x-0 top-0 h-full single_hero_background nozoom backdrop-blur-2xl"></div>
  {{ $backgroundBlur := resources.Get "js/background-blur.js" }}
  {{ $backgroundBlur = $backgroundBlur | resources.Minify | resources.Fingerprint (.Site.Params.fingerprintAlgorithm | default "sha512") }}
  <script
    type="text/javascript"
    src="{{ $backgroundBlur.RelPermalink }}"
    integrity="{{ $backgroundBlur.Data.Integrity }}"
    data-blur-id="background-blur"
    data-image-id="background-image-main"
    {{ with $background }}data-image-url="{{ .RelPermalink }}"{{ end }}></script>
{{ end }}

其實就是把主題預設的thumbAndBackground.html中下面這段刪掉

{{/* === Featured === */}}
{{ $featured := "" }}
{{ $featuredURL := "" }}
{{ with .Params.featureimage }}
  {{ if or (strings.HasPrefix . "http:") (strings.HasPrefix . "https:") }}
    {{ if site.Params.hotlinkFeatureImage }}
      {{ $featuredURL = . }}
    {{ else }}
      {{ $featured = resources.GetRemote . }}
    {{ end }}
  {{ else }}
    {{ $featured = resources.Get . }}
  {{ end }}
{{ end }}

{{ if not (or $featured $featuredURL) }}
  {{ $images := $.Resources.ByType "image" }}
  {{ range slice "*feature*" "*cover*" "*thumbnail*" "*background*" }}
    {{ if not $featured }}{{ $featured = $images.GetMatch . }}{{ end }}
  {{ end }}
{{ end }}

{{ if not (or $featured $featuredURL) }}
  {{ $default := site.Store.Get "defaultFeaturedImage" }}
  {{ if $default.url }}
    {{ $featuredURL = $default.url }}
  {{ else if $default.obj }}
    {{ $featured = $default.obj }}
  {{ end }}
{{ end }}

{{/* generate image URL if not hotlink */}}
{{ if not $featuredURL }}
  {{ with $featured }}
    {{ $featuredURL = .RelPermalink }}
    {{ if not (or $disableImageOptimization (eq .MediaType.SubType "svg")) }}
      {{ $size := site.Store.Get "backgroundImageWidth" }}
      {{ $featuredURL = (.Resize $size).RelPermalink }}
    {{ end }}
  {{ end }}
{{ end }}

{{ $isParentList := eq (.Scratch.Get "scope") "list" }}
{{ $shouldBlur := $.Params.layoutBackgroundBlur | default (or
  (and ($.Site.Params.article.layoutBackgroundBlur | default true) (not $isParentList))
  (and ($.Site.Params.list.layoutBackgroundBlur | default true) ($isParentList))
  )
}}

然後在<div class="single_hero_background nozoom fixed inset-x-0 top-0 h-[800px]">上方加入

{{ if $shouldAddHeaderSpace | default true }}
  <div id="hero" class="h-[150px] md:h-[200px]"></div>
{{ end }}

第二種:與 thumbAndBackground 類似,使用預設背景圖,但是 feature 圖顯示為全高全寬,參考這篇文章

先複製 /themes/blowfish/layouts/partials/hero路徑下的thumbAndBackground.html/layouts/partials/hero並改名為BigThumbAndBackground.html,找到下面這段:

<div class="overflow-hidden rounded-md h-36 md:h-56 lg:h-72 nozoom">
  <img
    src="{{ . }}"
    alt="{{ $.Title }}"
    loading="eager"
    decoding="async"
    fetchpriority="high"
    class="w-full h-full nozoom object-cover"
    {{ with $.Params.imagePositionFeature }}style="object-position: {{ . }};"{{ end }}>
</div>

改為:

<div class="overflow-hidden rounded-md">
  <img
    src="{{ . }}"
    alt="{{ $.Title }}"
    loading="eager"
    decoding="async"
    fetchpriority="high"
    class="w-full h-fulobject-cover"
    {{ with $.Params.imagePositionFeature }}style="object-position: {{ . }};"{{ end }}>
</div>

使用方法跟預設的 style 一樣,可直接在文章Front Matter新增heroStyle: default或是heroStyle: BigThumbAndBackground,或是在/config/_default/params.toml中設定為全局heroStyle


短代碼(Shortcode)
#

可折疊 iframe
#

參考Hugo 可折疊 iframe Shortcode


可折疊聊天視窗
#

對話框 4 則訊息
2025年11月2日
小明   00:00
你好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好
2025年11月2日
01:00   我
你好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好
2025年11月2日
我   01:00
晚安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安
2025年11月2日
01:30   小明
晚安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安安
或是
你好

你好
參考Hugo 可折疊聊天視窗短代碼 Shortcode


其他
#

RSS 收錄全文
#

/layouts/_default/rss.xml中(如使用主題預設的,直接複製一份過來)找到:

<description>{{ .Summary | html }}</description>

將它改為:

<description>{{ .Content | html }}</description>

希望訂閱我 RSS 的人都能用自己喜愛的 RSS 閱讀器及更方便的方式閱讀我的文章~

透過郵件回覆
YoZ 柚子
作者
YoZ 柚子
韓國實用音樂系留學生/FOSS Nerd/ISTJ/襯衫、墨鏡愛好者
Hugo Blowfish 主題客製化 - 本文屬於一個選集。
§ 1: 本文

相關文章