Adding responsive images in shortcode, markdown and templates

I’m looking to leverage responsive images across my site. Thanks to the documentation and great posts online like this one from [Mijndert] (Responsive images on a static Hugo website) I’m mostly up and running. So far, I have them working well from markdown and shortcode.

Here is a commit showing the markdown default override and shortcode both in use and working, which uses Hugo’s lovely (and fast!) image processing in multiple formats, lazy loading, and pretty simple usage:

Now my question: Do I understand correctly that neither Markdown nor shortcodes are available from the template files so I need to write a partial that provides similar functionality for images in my template? I feel like there must be a better way to organize the code so I’m not duplicating similar functionality three times so I’m open to advice and pointers to examples or docs.

Thanks in advance for any help.

Rob

You can call a partial from a shortcode so to deduplicate the implementation one would

  • implement the funtionality in a partial
  • wrap that into the shortcode

Not sure on that but I think you might also call a partial in a render hook

2 Likes

Thank you. I found this example which has been helpful in seeing how an image partial can be called from the render-image.html hook:

I can get this partial to work, but still trying to get the render-hook to pass the intended image along. This code errors out gracefully but drops all the resized/responsive images for me. I find these types of failures tricky to debug in Hugo as a newer user as it seems to usually be a scope thing, or sometimes a path search that I’m not quite following yet but I’m sure I’ll get to the bottom of it.

Thanks for your help and I’ll post when I’ve got something working.

If anyone has a responsive image module or code they love, I’m all ears. I’m looking for support from template and markdown – bonus points for featured images. :slight_smile:

Thanks!

Rob

Glad to point you in a promising direction

If you get stuck with a specific problem. Come back, point out your problem, wanted result and share your code. Someone will pick that up.

Thanks for the pointers. I got it working after quite a bit of experimentation. Although I couldn’t get some of the more full-featured responsive image modules to work (I had trouble tracking down where the builds were failing), the code in those modules was helpful in getting me to a working version that suits my purposes which is multiple image sizes and formats using picture sources with a fallback to a low resolution image in the img tag for backwards compatibility.

In case it’s helpful for anyone else I’ll document my solution here. I welcome any pointers if the more experienced here see issues I’m creating for myself!

/layouts/partials/responsive-img.html:

{{ $img := .img }}
{{ $alt := .alt }}
{{ $class := .class }}
{{ $lazy := .lazy }}
{{ $caption := .title }}

{{- $respSizes := slice "960" "1920" -}}

{{- with $src := resources.Get ($img) -}}
  {{- $divClass := "" -}}{{/* Init'g */}}
  {{- $imgClass := "lazy" -}}
  {{- $dataSzes := "(min-width: 1024px) 100vw, 50vw" -}}
  {{- $actualImg := $src.Resize "640x jpg" -}}
  <picture>
    <source
      type="image/webp"
      data-srcset="
        {{- with $respSizes -}}
          {{- range $i, $e := . -}}
          {{- if ge $src.Width . -}}
            {{- if $i }}, {{ end -}}{{- ($src.Resize (printf "%sx%s" . " webp") ).RelPermalink }} {{ . }}w
          {{- end -}}
        {{- end -}}
      {{- end -}}"
      data-sizes="{{ $dataSzes }}"
    />
    <source
      type="image/jpeg"
      data-srcset="
        {{- with $respSizes -}}
          {{- range $i, $e := . -}}
            {{- if ge $src.Width . -}}
              {{- if $i }}, {{ end -}}{{- ($src.Resize (printf "%sx%s" . " jpg") ).RelPermalink }} {{ . }}w
            {{- end -}}
        {{- end -}}
      {{- end -}}"\
      data-sizes="{{ $dataSzes }}"
    />
    <img class="{{ $imgClass }}"
      src="{{ $actualImg.RelPermalink }}"
      width="{{ $src.Width }}"
      height="{{ $src.Height }}"
      alt="{{ $alt }}"
      title="{{ .Title }}"
    />
  </picture>
{{- else -}}
<img extra="MISSING" src="{{ .Destination | safeURL }}"
  {{- with .Text }} alt="{{ . }}"{{ end -}}
  {{- with .Title }} title="{{ . }}"{{ end -}}
>
{{- end -}}

That can be called from a template like this:

    {{ partial "responsive-img.html" (dict 
      "img" .Site.Params.author_section.author_section_image
      "alt" .Site.Params.author_section.author_section_image_alt
    ) }}

Then for shortcode usage with two simple parameters, that looks like:

/layouts/shortcodes/img.html

{{- $imgBase := "" -}}
{{- $src := resources.Get (printf "%s%s" $imgBase (.Get "src")) -}}
{{- $alt := .Get "alt" -}}

{{ partial "responsive-img.html" (dict 
  "img" $src
  "alt" $alt
) }}

Which can be called from a template with arguments that looks like this:
{{< img src="/images/bobs-big-boy.jpg" alt="Bob's Big Boy" >}}

And finally, for overriding the default markdown, there’s the render-image.html override:

/layouts/_default/_markup/render-image.html

{{ partial "responsive-img.html" (dict 
  "img" .Destination
  "alt" .Text
  "caption" .Title
) }}

And the markdown code for that remains as documented:
![Bob's Big Boy](/images/bobs-big-boy.jpg "Bob's Big Boy")

I’m still hoping to get one of the expertly written responsive image modules working someday when I understand the errors a little better, but for now this looks like it’s generating mostly good code!

Thanks

Rob

P.S. Thank you to Brycewray.com for the post that got me started on this.

1 Like