1. Home
  2. /
  3. Hugo
  4. /
  5. Hugoで画像を自動でWebP化する、ついでにクリックで拡大できるようにする

Hugoで画像を自動でWebP化する、ついでにクリックで拡大できるようにする

Hugoで画像を自動でWebP化する、ついでにクリックで拡大できるようにする

このブログではHugoというmarkdownから静的サイトを生成するツールを使用しています。画像はmarkdownの書式どおり下記の記載をしています。

![](img/hogehoge.png)

このままだとデータ容量が大きいためWebPに自動変換処理を追加しました。また画像を拡大して見られるようにLightbox対応も行いました。

なお本ブログでは下記のHugoテーマをお借りしております。こちらのテーマを利用している前提で記載していますが、基本的には他のテーマでも利用できると思います。

Hugo標準のgistショートコードをテーマ内に移行しました | Hugoブログテーマ「Salt」

WebPへの自動変換

このブログでは、HugoのRender Hook機能を使って、記事内の画像を自動的にWebPに変換しています。具体的には layouts/_default/_markup/render-image.html ファイルで以下の処理を行っています。

実装の流れ

  1. 画像リソースの取得:Markdownで指定した画像パスを .Page.Resources.GetMatch で取得
  2. 形式判定:jpg/jpeg/png拡張子の画像のみWebP変換対象とする(ここで制限しないとgif動画とかも変換されてしまうので)
  3. リサイズ処理:元画像を幅1280pxにリサイズして軽量化
  4. WebP変換:リサイズ後の画像をWebP形式に変換
  5. HTML出力:<picture> タグで画像を表示、念のためWebPを表示できないブラウザは従来形式で表示するようにしています

詳細は後述しますが、Lightbox対応のコードも下記には一部含まれています。

{{ $src := .Page.Resources.GetMatch (printf "%s*" .Destination) }}
{{ if $src }}
{{ $sourceImage := $src }}
{{ if in (slice "jpg" "jpeg" "png") $sourceImage.MediaType.SubType }}
{{ $resizedImage := $sourceImage.Resize "1280x" }}
{{ $webpImage := $resizedImage.Resize (printf "%dx%d webp" $resizedImage.Width $resizedImage.Height) }}
<a href="{{ $sourceImage.RelPermalink }}" class="glightbox">
<picture>
    <source srcset="{{ $webpImage.RelPermalink }}" type="image/webp">
    <img src="{{ $resizedImage.RelPermalink }}" width="{{ $resizedImage.Width }}" alt="{{ .PlainText }}">
</picture>
</a>
{{ end }}
{{ end }}

このRender Hookにより、Markdown内で ![](img/example.png) と書くだけで、Build時に自動的にWebP変換が行われます。

このブログではデプロイをCloudflare Pagesで行っています。Cloudflare PagesなどのCI/CDサービスではBuildの実行時間に制限があるため大量の画像がある場合はこの方法では対応できない可能性がありますのでご注意ください。

当初Gif動画なども変換対象に入っており変換時間でタイムアウトしたためjpg/jpeg/pngの拡張子のみを変換するように制限を掛けました。

Lightboxの導入

画像をクリックしたときにオーバーレイで拡大表示する、いわゆるLightbox機能を導入しています。ライブラリはGLightboxを使用しています。

GLightboxの読み込み

GLightboxはCDN経由で読み込んでいます。

まずCSSを layouts/partials/head-add.html に追加します。このコードはテーマの <head> 内で読み込まれます。

<!-- GLightbox CSS -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/glightbox.min.css">

次にJavaScriptの読み込みと初期化を layouts/partials/body-add.html に追加します。こちらは </body> 直前で読み込まれます。

<!-- GLightbox JS -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/glightbox.min.js"></script>
<script>
    // GLightbox初期化
    window.addEventListener('DOMContentLoaded', function() {
        const lightbox = GLightbox({
            touchNavigation: true,
            loop: true,
            autoplayVideos: false,
            zoomable: true,
            draggable: true
        });
    });
</script>

初期化オプションでタッチ操作・ループ再生・ズーム・ドラッグを有効にしています。autoplayVideos は今回不要なのでオフにしています。(今のところ動画ファイルを直貼りはしていないので再生周りの動作確認はしていません)

Render Hookでの対応

前述のWebP変換で使用している layouts/_default/_markup/render-image.html 内の <a> タグにGLightbox用の属性を付与しています。

<a href="{{ $sourceImage.RelPermalink }}" class="glightbox" data-gallery="article-images" data-glightbox="description: {{ .PlainText }}">
  • class="glightbox":GLightboxがこのクラスを持つリンクを自動でLightbox対象として認識します
  • data-gallery="article-images":同一記事内の画像をギャラリーとしてグループ化し、左右の矢印で画像を送れるようにしています
  • data-glightbox="description: ...":画像のaltテキストをLightbox表示時の説明文として表示します

href にはWebP変換前の元画像を指定しているため、Lightboxで拡大した際は高解像度の原寸画像が表示されます。ここも将来的には解像度はそのままにWebP化したい。

カスタムスタイル

assets/scss/custom.scss にGLightbox用のスタイルを追加しています。

// GLightbox画像スタイル
a.glightbox {
    cursor: zoom-in;
    display: inline-block;
    border: none;
    
    img {
        transition: opacity 0.3s ease, transform 0.3s ease;
    }
    
    &:hover img {
        opacity: 0.9;
        transform: scale(1.02);
    }
}

// 記事コンテンツ内の画像を中央寄せ
.article__content {
    picture, 
    a.glightbox {
        display: block;
        text-align: center;
        margin: 1.5rem auto;
    }
}

cursor: zoom-in で画像にホバーすると拡大カーソルに変わるので、クリックで拡大できることが視覚的に伝わるようにしています。ホバー時に少し透明度を下げつつ微拡大するアニメーションも入れています。

WebP変換と合わせた全体像

Render Hookの全体コードを改めて掲載します。WebP変換とLightbox対応の両方が含まれています。

{{ $src := .Page.Resources.GetMatch (printf "%s*" .Destination) }}
{{ if $src }}
{{ $sourceImage := $src }}
{{ if in (slice "jpg" "jpeg" "png") $sourceImage.MediaType.SubType }}
{{ $resizedImage := $sourceImage.Resize "1280x" }}
{{ $webpImage := $resizedImage.Resize (printf "%dx%d webp" $resizedImage.Width $resizedImage.Height) }}
<a href="{{ $sourceImage.RelPermalink }}" class="glightbox" data-gallery="article-images" data-glightbox="description: {{ .PlainText }}">
<picture>
    <source srcset="{{ $webpImage.RelPermalink }}" type="image/webp">
    <img src="{{ $resizedImage.RelPermalink }}" width="{{ $resizedImage.Width }}" alt="{{ .PlainText }}">
</picture>
</a>
{{ else }}
<a href="{{ $sourceImage.RelPermalink }}" class="glightbox" data-gallery="article-images" data-glightbox="description: {{ .PlainText }}">
<img src="{{ $sourceImage.RelPermalink }}" width="{{ $sourceImage.Width }}" height="{{ $sourceImage.Height }}"
    alt="{{ .PlainText }}">
</a>
{{ end }}
{{ else }}
<a href="{{ .Destination }}" class="glightbox" data-gallery="article-images" data-glightbox="description: {{ .PlainText }}">
<img src="{{ .Destination }}" alt="{{ .PlainText }}">
</a>
{{ end }}

WebP変換対象外の画像(gifなど)やリソースとして取得できない外部画像に対しても、else ブロックでLightboxの <a> タグを付与しているため、すべての画像がクリックで拡大表示できるようになっています。

まとめ

これにより![](img/hogehoge.png)というmarkdownでおなじみの形式で画像を貼り付けるだけで、WebPへの変換・リサイズとLightboxでのクリック拡大等がすべて自動で挿入されるようになりました。書く方も楽ですし、見る方も便利な良い改善になりました。

Hugoにはまだまだ知らない機能が眠っていそうなので今後もいろいろ発掘しがいがありそうです。

サイト内の商品リンクは一部アフィリエイトリンクとなっています

関連記事

HugoをCloudflare Pagesで自動ビルド・デプロイする

HugoをCloudflare Pagesで自動ビルド・デプロイする

前回の記事でHugoでブログを作成しました。しかし現状では手動ビルド、アップロードが必要です。 ブログをWordPressからHugoに移行した このブログを放置して早3年半くらいの月日が経ってしまいました。 元々このブログの構成はさくらのレンタルサーバーにWordPressを乗せてというシンプルなものでした。しかし、脆弱性が生まれないようにWordPressを更新していくのが面倒になってきました。 そのため、静的サイトジェネレーターのHugoに移行することにしました。 Hugoのインストール Hugoは静的サイトジェネレーターのため、執筆する端末にHugoをインストールします。 今回はCloudflare Pages(以下、Pages)を使って自動ビルド、デプロイを行います。
ブログをWordPressからHugoに移行した

ブログをWordPressからHugoに移行した

このブログを放置して早3年半くらいの月日が経ってしまいました。 元々このブログの構成はさくらのレンタルサーバーにWordPressを乗せてというシンプルなものでした。しかし、脆弱性が生まれないようにWordPressを更新していくのが面倒になってきました。 そのため、静的サイトジェネレーターのHugoに移行することにしました。 Hugoのインストール Hugoは静的サイトジェネレーターのため、執筆する端末にHugoをインストールします。