快轉到主要內容

改善圖片處理

·1759 字·4 分鐘
目錄

在md裡面用gallery放圖時,發現圖已經載入,但layout是錯的,要等一段時間才會正常。這並不是載入速度慢,是hugo在渲染圖片時,無法正確算出要給多少空間去展現圖片。問了Gemini、chatGPT、Grok等工具,實際測試過後用了以下解法:

縮圖
#

手機拍的圖都蠻大的,但要在手機或電腦上看,其實可以縮到200~300KB;解析度縮成800X600(橫式)或是600X800(直式),可以改善下載和渲染、解碼的速度。
線上縮圖工具: iloveimg
另外,將jpeg轉換成webp會進一步改善圖片載入的速度,將相同品質的圖片壓縮得更小。
jpeg轉webp線上工具: piliapp

改善排版
#

blowfish很常用gallery做多圖的排版,當圖片載入後,browser必須計算長寬後決定要給你多大的空間,這邊會花時間,所以如果能"告訴"它要留多少空間,會讓速度改善不少。

  • img裡面調整class,加上aspect-xxx: class="aspect-xxx object-cover"
    • aspect-square: 呈現1:1正方形
    • aspect-video: 呈現16:9
    • aspect-[4/3]: 寬長比為4:3, 標準landscape圖片
    • aspect-[3/4]: 寬長比為3:4, 標準portrait圖片
    • object-cover 必加,不然會變形
沒有加aspect,瀏覽器必須等圖片下載完,知道寬高後,才開始計算佈局;加上後browser在下載前就會知道該圖會佔多少空間,跳過計算重排的時間
  • img裡設定decoding=“lazy”loading=“async”

    • 可以先檢查layouts/_default/_markup/render-image.html中有沒有找到這兩個設定,沒有的話,把theme/blowfish/下的render-image.html複製到layouts下的同一目錄,不然就直接加在img裡。
    • 若要修改layout/_default/_markup/render-image.html,參考下面程式碼:
      RenderImageResponsive
      ....
      {{- define "RenderImageResponsive" -}}
      {{- $imgObj := .imgObj -}}
      {{- $alt := .alt -}}
      {{- $originalWidth := $imgObj.Width -}}
      
      {{/* 1. 邏輯判斷:寬度是否小於高度 (直式) */}}
      {{- $isPortrait := lt $imgObj.Width $imgObj.Height -}}
      
      {{/* 2. 根據橫直決定縮圖策略,這能解決「解碼大圖」造成的卡頓 */}}
      {{- $img800 := "" -}}
      {{- if $isPortrait -}}
        {{/* 直式圖:限制高度為 800px,寬度自適應 */}}
        {{- $img800 = $imgObj.Resize "x800 webp" -}}
      {{- else -}}
        {{/* 橫式圖:限制寬度為 800px,高度自適應 */}}
        {{- $img800 = $imgObj.Resize "800x webp" -}}
      {{- end -}}
      
      <img
        {{/* 3. 根據橫直式動態加入不同的 CSS Class (搭配你的 Gallery 設定) */}}
        class="my-0 !rounded-lg !shadow-md w-full h-full object-cover {{ if $isPortrait }}img-portrait{{ else }}img-landscape{{ end }}"
        loading="lazy"
        decoding="async"
        alt="{{ $alt }}"
        /* 4. 傳入縮圖後的正確寬高這是消除 Layout Shift 紅色尖峰的關鍵 */
        width="{{ $img800.Width }}"
        height="{{ $img800.Height }}"
        src="{{ $img800.RelPermalink }}"
        data-zoom-src="{{ $imgObj.RelPermalink }}">
      {{- end -}}
  • 修改assets/css/custom.css

    custom.css
    /* ============================================================
       1. 效能優化區(安全版)
       ============================================================ */
    
    /* GPU 加速只套用在圖片,不動 filter/stacking context */
    img {
        transform: translateZ(0);
        /* 移除 content-visibility:iOS Safari bug,手機上不安全 */
    }
    
    /* ⚠️ 移除全域 filter:none — 這會破壞 Blowfish 的 stacking context */
    /* 若需要關閉特定毛玻璃效果,改用精準選擇器,例如:
    .backdrop-blur { backdrop-filter: none !important; } */
    
    /* ============================================================
       2. Gallery 佈局:改用 Flexbox/Grid,完全棄用 float
       ============================================================ */
    
    /* Blowfish gallery 容器:改用現代佈局,不依賴 float */
    .prose .gallery,
    .prose .grid {
        display: flex !important;
        flex-wrap: wrap !important;
        gap: 0.5rem;
        /* 建立新的 stacking context,隔離內部 z-index 影響 */
        isolation: isolate;
    }
    
    
    /* ============================================================
       3. Grid-w 寬度控制:改用 flex-basis,不用 float
       ============================================================ */
    
    .prose [class*="grid-w"] {
        box-sizing: border-box;
        flex-shrink: 0;
        /* 移除 float 與 inline-block,交由 flex 父層控制排列 */
    }
    
    /* 常用 grid-w 尺寸對應(Blowfish 預設) */
    .prose .grid-w25  { flex-basis: calc(25% - 0.5rem); }
    .prose .grid-w33  { flex-basis: calc(33.333% - 0.5rem); }
    .prose .grid-w50  { flex-basis: calc(50% - 0.5rem); }
    .prose .grid-w66  { flex-basis: calc(66.666% - 0.5rem); }
    .prose .grid-w75  { flex-basis: calc(75% - 0.5rem); }
    .prose .grid-w100 { flex-basis: 100%; }
    
    /* 手機斷點:小螢幕自動單欄,防止圖片過窄導致重疊 */
    @media (max-width: 640px) {
        [class*="grid-w"] {
            flex-basis: 100% !important;
        }
    }
    
    /* ============================================================
       4. 比例與形狀控制
       ============================================================ */
    
    .aspect-square {
        aspect-ratio: 1 / 1 !important;
        object-fit: cover !important;
    }
    
    [class*="aspect-["] {
        object-fit: cover !important;
    }
    
    /* ============================================================
       5. Figure 安全防護
       ============================================================ */
    
    figure {
        max-width: 100%;
        margin: 0; /* 移除預設 margin 避免撐破 flex 容器 */
    }
    
    figure img {
        max-width: 100%;
        height: auto;
        display: block; /* 消除圖片底部的 inline 空白間隙 */
    }
    
    /* ============================================================
     6 清除 Blowfish gallery 圖片的內建 float
    ============================================================ */
    
    /* 強制讓 gallery 容器撐開高度 */
    .prose .gallery, 
    .prose .grid {
        display: block !important; /* 確保它是一個區塊 */
        clear: both !important;    /* 清除上方所有浮動 */
        overflow: hidden !important; /* 自動計算內部浮動元素的高度 */
        margin-bottom: 2rem !important; /* 與下方文字保持距離 */
    }
    
    /* 這是最關鍵的一招:確保 gallery 後面的「任何東西」都不能往上飄 */
    .prose .gallery + p,
    .prose .grid + p,
    .prose .gallery + h2,
    .prose .gallery + h3 {
        clear: both !important;
        padding-top: 1rem;
    }

美化
#

img裡的class可以對邊框做一些處理 <img = ...class="rounded-lg shadow-md ":

  • rounded-lg 大圓角 - 四邊做圓角處理
  • shadow-md 中等陰影 - 會在圖片下方和側邊加上一層淡淡的灰色陰影

另外,使用gallery和figure要和文字至少隔一行,避免css誤判。


閱讀次數: