IMG shortcode (Bootstrap 4)

Following is my shortcode for images in articles (responsive, with imgsrc). It uses a Bootstrap 4 theme, so image sizes are more or less static depending on the viewport width (col-xl-$$, col-lg-$$, and so on). Most of the comparable shortcodes here use the size-attribute, which, in my opinion, is not necessary with Bootstrap sizes.

In my config.toml (I like to leave much of comments in my files… it’s an Alzheimer thing):

#############################################################
# Imaging setup
#############################################################
[imaging]
  # Default resample filter used for resizing. Default is Box,
  # a simple and fast averaging filter appropriate for downscaling.
  # See https://github.com/disintegration/imaging
  resampleFilter = "lanczos"
  # Default JPEG quality setting. Default is 75.
  quality = 85
  # Anchor used when cropping pictures.
  # Default is "smart" which does Smart Cropping, using https://github.com/muesli/smartcrop
  # Smart Cropping is content aware and tries to find the best crop for each image.
  # Valid values are Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight
  anchor = "smart"

[params.imaging]
  # xl, lg, md, sm and below
  sizes = ["825","610","510","450"]

In params.imaging I added all the widths of images in my content column. You need to test with different viewport widths, and those are more or less the widths I reach with a two column layout. This map can contain as many widths as you may want. My content column is defined as col-xl-8 col-lg-8 col-md-7 col-sm-12 col.

Everything under [imaging] is just for posterity. I like higher qualities in images. Lanczos seems to be delivering the best results at maximum compression, and smart is just smart for cropping images. These are settings for my article images, and they tend to be at a landscape with a specific layout. Needs may vary. I probably should add those three settings as parameters to the shortcode just for future needs.

The shortcode itself then (layouts/shortcodes/img.html):

{{/* 
	see 
	https://laurakalbag.com/processing-responsive-images-with-hugo/ 
	https://discourse.gohugo.io/t/easy-way-to-serve-responsive-images-with-hugo/16184
	https://www.adamwills.io/blog/responsive-images-hugo/
	https://gohugo.io/content-management/image-processing/
*/}}

{{ $src := .Page.Resources.GetMatch (printf "*%s*" (.Get "src")) }}
<figure {{ with .Get "class" }}class="{{.}}"{{ end }}>
{{ with .Get "link" }}<a href="{{.}}">{{ end }}
	<img 
		width="825"	  
		srcset="{{- range $i, $e := .Site.Params.Imaging.Sizes -}}
			{{- if $i -}}, {{- end -}}
			{{- if ge $src.Width $e -}}
				{{ $small := $src.Resize (print $e "x") }}
				{{ with $small.RelPermalink }}{{.}} {{ $e }}w{{ end }}
			{{- end -}}
		{{- end -}}"
		src="{{ $src.RelPermalink }}" 	  
		{{- with .Get "alt" -}}alt="{{.}}" {{- end -}}>
{{ if .Get "link"}}</a>{{ end }}
{{ with .Inner }}
	<figcaption>{{ . | markdownify }}</figcaption>
{{ end }}
</figure>

You can call the shortcode via: {{< img src="filename.jpg" >}}caption{{< /img >}}. This assumes that filename.jpg is in a page bundle at the same level of the .md-file that is parsed.

Available attributes for the shortcode are:

  • src: file path to the image (required)
  • class: class names for the figure (optional)
  • link: linking the image (optional)
  • alt: alternative text (option) - this probably should be printed even if it’s empty to make browsers happy.

Text within the shortcode will be printed as formatted (I am using HTML, but simple markdown will be parsed).

Again, this works because Bootstrap 4 column widths are more or less static. Other setups might require the size attribute in the image tag.

1 Like

I sent my site through the W3org validator and it appears that the standard requires, that the sizes attribute is set, if the srcset attribute uses the w indicators. Long story short, here is the resulting img shortcode in layouts/shortcodes/img.html:

{{/* 
	see 
	https://laurakalbag.com/processing-responsive-images-with-hugo/ 
	https://discourse.gohugo.io/t/easy-way-to-serve-responsive-images-with-hugo/16184
	https://www.adamwills.io/blog/responsive-images-hugo/
	https://gohugo.io/content-management/image-processing/
*/}}

{{ $src := .Page.Resources.GetMatch (printf "*%s*" (.Get "src")) }}
<figure {{ with .Get "class" }}class="{{.}}"{{ end }}>
{{ with .Get "link" }}<a href="{{.}}">{{ end }}
	<img 
		width="{{ range first 1 .Site.Params.Imaging.Sizes }}{{ . }}{{ end }}"
		sizes="{{- range $i, $e := .Site.Params.Imaging.Sizes -}}
			{{- if $i -}}, {{- end -}}
			{{- if ge $src.Width $e -}}
				(min-width: {{ $e }}px) {{ $e }}px
			{{- end -}}
		{{- end -}}"
		srcset="{{- range $i, $e := .Site.Params.Imaging.Sizes -}}
			{{- if $i -}}, {{- end -}}
			{{- if ge $src.Width $e -}}
				{{ $small := $src.Resize (print $e "x") }}
				{{ with $small.RelPermalink }}{{.}} {{ $e }}w{{ end }}
			{{- end -}}
		{{- end -}}"
		src="{{ $src.RelPermalink }}" 	  
		{{- with .Get "alt" -}}alt="{{.}}" {{- end -}}>
	{{ if .Get "link"}}</a>{{ end }}
	{{ with .Inner }}
	<figcaption>{{ . }}</figcaption>
{{ end }}
</figure>

I also changed the width attribute to use the first item in the list of sizes — that’s better than a static integer. I am not sure what the right approach of order is for sizes so I would say order your sizes from largest to smallest size :wink: This way the width parameter is always the largest value.

This parameter is technically speaking irrelevant for the page rendering because good web designers™ use CSS to let the browser know how the image should be sized. It is more or less needed to point in some accessibility and speed tests.

1 Like