An img srcset using Page Resources

I wanted to grasp the concept of Page Resources and Scratch a little bit better so I created an image srcset partial that puts them both to good use (at least in my opinion). One of the things I really like about it is you can quickly halve the image (0.5), double it (2) or explicitly have the widths you want the images to be.

Here’s the Github Gist of the partial only since formatting here may be wonky.

I would also love feedback on this to see how it could be improved upon.

A couple notes:
This needs only 2 params:

  1. Image file location: location/to/file.jpg
  2. The sizes of the images you want

I also use a custom headless media folder inside the content directory to hold all my images. You may need to change the $media variable to best fit your project.

Front-matter

---
image: images/testing-image.jpg
# Order doesnt matter
sizes: [0.25, 1, 0.5, 0.33, 2, 900]  

# Below are optional
alt: Testing an image
class: testing-class
options: Lanczos q90
---

Partial.html

{{ $image := .Params.image}}
{{ $media := (.Site.GetPage "page" "media").Resources }}
{{ $original := index ($media.Match (printf "%s" $image)) 0 }}
{{ $width := $original.Width}}
{{ $intWidth := int $width }}
{{ $sizes := .Params.sizes}}
{{ $options := .Params.options}}

{{ if le (len $sizes) 1 }}
  {{ $oneSize := index $sizes 0}}

  {{- if ge $oneSize 10 -}}
    {{- $img := ($original.Resize (printf "%sx %s" $oneSize $options)) -}}
    {{ $.Scratch.Add "src" $img.RelPermalink }}
  {{- else -}}
    {{- $floatSize := float $oneSize -}}
    {{- $newSize := (mul $intWidth $floatSize) -}}
    {{- $int2string := string (math.Round $newSize) -}}
    {{- $img := ($original.Resize (printf "%sx %s" $int2string $options)) -}}
    {{ $.Scratch.Add "src" $img.RelPermalink }}
  {{- end -}}

  <img
  {{with .Params.class}}class="{{.}}"{{end}}
  src="{{ .Scratch.Get "src" }}"
  {{with .Params.alt | default $original.Title}}alt="{{.}}"{{end}}>
{{else}}
  {{ range $i, $sort := (seq (len $sizes)) }}
    {{- if ge (index $sizes $i) 10 -}}
      {{ $.Scratch.Add "sort" (slice (index $sizes $i)) }}
    {{ else }}
      {{- $floatSize := float (index $sizes $i) -}}
      {{- $newSize := (math.Round (mul $intWidth $floatSize)) -}}
      {{- $int2string := string $newSize -}}
      {{ $.Scratch.Add "sort" (slice $int2string) }}
    {{ end }}
  {{ end }}
  {{ $sort := sort (.Scratch.Get "sort") }}

  {{- range $i, $num := (seq (len $sort )) -}}
    {{- $imgSize := index $sort $i -}}
    {{- $img := ($original.Resize (printf "%sx %s" $imgSize $options)) -}}
    {{ $.Scratch.Add "sizes" (slice $img.Width) }}
    {{- $int2string := string $img.Width -}}
    {{ $.Scratch.Add "string" (slice (printf "%s %sw" $img.RelPermalink $int2string)) }}
  {{- end -}}

  <img
  {{with .Params.class}}class="{{.}}"{{end}}
  src="{{ $original.RelPermalink }}"
  srcset="{{delimit (.Scratch.Get "string") ", " }}"
  sizes="
    {{- $last := sub (len (.Scratch.Get "sizes")) 1 -}}
    {{- range first $last (.Scratch.Get "sizes") -}}
    (max-width: {{ . }}px) {{ sub . 40 }}px,
    {{end}}
    {{- index (.Scratch.Get "sizes") (sub (len (.Scratch.Get "sizes")) 1) -}}px"
  {{with .Params.alt | default $original.Title}}alt="{{.}}"{{end}}>
{{end}}

Hopefully this was useful. I welcome feedback and improvement since this was meant to be a learning exercise for me.

7 Likes

Looks like some good hard work :). Can you also link a test page that’s using this partial?

Not currently. The project that it’s currently being utilized on is still in local dev.

Also, for those interested I added a stripped down version of this concept (partial only) that includes a condition if the length of the array is only 1, in which case it will fall back to a non-srcset img element - I also removed two unused variables and added optional class/title support. Here’s the GitHub Gist.

2 Likes

I updated the Gist. I was running into a non-user friendly issue where if the multiple was higher than your specified size (like the original image - 1 or 2x), the srcset and media sizes would be out of order. Now width sizing and sorting occurs first, then image resizing.

I also added image options parameter (like the resampling options, quality, etc.).

3 Likes