Skip to content
Go back

HugoでSVG画像を表示する

事前調査#

  • 分かりやすさのため、外部リンクにアイコンを付けたい
    • render-link.html<a>の隣に画像を貼ればできる
    • PaperModはHTMLに<svg>を直書きしていた
  • SVGを表示するやり方はいくつかある
    • <svg>で直接書く
    • <img>でファイルを読み込む
    • CSSで背景画像として貼り付ける
    • <use>でSVGスプライトを使う
  • それぞれ良い悪いがある
    • <svg>は直接埋め込むので、余分なリクエストが発生しないが、DOMが肥大化してパフォーマンスに影響する可能性がある
    • <img>は別のファイルとして持つので、DOMの肥大化を避けられるが、追加のリクエストが必要になる
      • そのリクエストは画像が必要になるまで遅延させることができる
    • <use><img>のように貼り付けられる<svg>のようなものだが、画像をひとつのファイルにまとめる必要があったり、セキュリティの関係で内部ドメインからしか読み出せなかったりする
    • CSSは「HTMLでない」こと自体がメリットにもデメリットにもなる
  • やりたいことが達成できるものを選べば良い
    • スタイリングしたりインタラクションさせたりしたい場合、<svg><use>を使う
      • そこでしか使われないなら、<svg>で直書きしても良い
      • 使い回す前提なら、<use>を使う
    • 静的でいいなら、<img>を使う
    • CSSは重要でない付加的な要素にのみ使用する

作業中#

  • PaperModがFeather iconsを使っているのでそれに倣う
  • SVGスプライトをダウンロードしてassets/imagesに入れる
    • assetsにあるファイルはHugoのアセットパイプラインを通して使用する
    • ファイルをそのまま使いたいだけなら、static/に入れても良い
  • use-icon.htmlを以下のように作り、SVGスプライトから指定の画像を取り出すpartialを定義する
{{- $path := "images/feather-sprite.svg" -}}
{{- with resources.Get $path -}}
    <svg xmlns="http://www.w3.org/2000/svg"{{with $.Class}} class="{{.}}"{{end}}><use href="{{.RelPermalink}}#{{$.Name}}"/></svg>
{{- else -}}
    {{- errorf "Icons not found (path: %s)" $path -}}
{{- end -}}
  • リンクのテキストの後ろで以下のように呼び出す
    • 今回は、テキスト付きリンクだけにしておく
{{- partial "use-icon.html" (dict "Name" "external-link" "Class" "external-link") -}}
  • 以下のようなCSSで大きさや色味を整える
svg.external-link {
    width: 14px;
    height: 14px;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    fill: none;
    color: var(--secondary);
}
  • ついでに、これまでに使用したOSSの著作権表示をNOTICEにまとめた

参考文献#