Skip to content
Branch: master
Go to file

Latest commit

fte378 authored and liwenyip committed 2935729 Apr 22, 2019
Avoid doubled thumbnail downloads (#43)
Fixed double slash in thumbnail URL, which was causing thumbnail image to be downloaded twice.


Failed to load latest commit information.


2019-01-20: I'm looking for people to help maintain this project - e.g. review and approve pull requests, which I no longer have time to do. Please contact me if you are interested. Thanks!

Automagical css image gallery in Hugo using shortcodes, with optional lightbox/carousel gadget using PhotoSwipe and jQuery.

New: Create a gallery of all images in a directory with just one line of shortcode, see demo.

Need help?

  • Post your question at
  • Include a link to a test page that demonstrates the issue you are having
  • Include your source code for the test page
  • Please be patient (I have a busy day job as that has nothing to do with web development or computer science, so every time I look at issues/PRs it takes me a while to get back up to speed); I will respond eventually. Please DO NOT email me asking for help, you are very unlikely to get a response from me this way.

Fixed an issue or made an improvement?

  • Please submit a pull request
  • Include a link to a test page
  • Include your source code for the test page
  • Let me know if you are in Sydney and I will thank you with beer :-)


Image Gallery Features

  • Custom {{< figure >}} shortcode that enables new features but is backwards-compatible with Hugo's built-in {{< figure >}}shortcode
  • Use the {{< figure >}} shortcode by itself to enable pretty captions
  • Put multiple {{< figure >}} shortcodes inside a {{< gallery >}} to create a pretty image gallery
  • Point {{< gallery >}} at a directory to generate a gallery of all images in that directory
  • Gallery is responsive, images are scaled/cropped to fill square (or other evenly-sized) tiles
  • Pretty captions appear/slide/fade upon hovering over the image
  • Optionally make gallery images zoom, grow, shrink, slide up, or slide down upon hover
  • Only requires 3.6kB of CSS (unminified; you can minify it if you want)
  • CSS is automatically loaded the first time you use the {{< figure >}} shortcode on each page

PhotoSwipe Features

  • Load PhotoSwipe by calling the {{< load-photoswipe >}} shortcode anywhere in your post
  • Loads all of the <figure> elements in your post, regardless of where in your post they appear, into a lightbox/carousel style image gallery
  • Works with any existing <figure> elements/shortcodes in your posts
  • Does not require you to pre-define the image sizes (the initialisation script pre-loads the image to determine its size; you can optionally pre-define the image size if you want to avoid this pre-loading)
  • Loads PhotoSwipe js and css libraries from


Put files in following places:

  • /layouts/shortcodes/figure.html
  • /layouts/shortcodes/gallery.html
  • /layouts/shortcodes/load-photoswipe.html
  • /static/js/load-photoswipe.js
  • /static/css/hugo-easy-gallery.css

NB load-photoswipe.html loads jQuery from

  • If your template already loads jQuery in the header, you can delete the jQuery link in load-photoswipe.html.
  • If your template already loads jQuery in the footer, you should load-photoswipe.js from the footer instead of in load-photoswipe.html.

If you want, you could (depending on a front matter param) conditionally load load-photoswipe.html or its contents from the footer of your template. But I've consciously chosen to load PhotoSwipe using a shortcode so that you don't have to modify your template if you don't want to.

Theme integration

Put files in the relevant folders within your theme.

Delete /layouts/shortcodes/load-photoswipe.html.

Rename /layouts/shortcodes/load-photoswipe-theme.html to /layouts/shortcodes/load-photoswipe.html.

Add the following lines to the footer of your template, just before </body>:

(Omit the jQuery line if jQuery is already loaded elsewhere in your template; just make sure that jQuery is loaded before this code.)

<!-- Load PhotoSwipe js if the load-photoswipe shortcode has been used -->
{{ if ($.Scratch.Get "photoswipeloaded") }}
<script src="" integrity="sha256-ZosEbRLbNQzLpnKIkEdrPv7lOy9C27hHQ+Xp8a4MxAQ=" crossorigin="anonymous"></script>
<script src="/js/load-photoswipe.js"></script>
<script src="" integrity="sha256-UplRCs9v4KXVJvVY+p+RSo5Q4ilAUXh7kpjyIP5odyc=" crossorigin="anonymous"></script>
<script src="" integrity="sha256-PWHOlUzc96pMc8ThwRIXPn8yH4NOLu42RQ0b9SpnpFk=" crossorigin="anonymous"></script>
{{ end }}

{{< figure >}} shortcode usage

Specifying your image files:

  • {{< figure src="thumb.jpg" link="image.jpg" >}} will use thumb.jpg for thumbnail and image.jpg for lightbox
  • {{< figure src="image.jpg" >}} or {{< figure link="image.jpg" >}} will use image.jpg for both thumbnail and lightbox
  • {{< figure link="image.jpg" thumb="-small" >}} will use image-small.jpg for thumbnail and image.jpg for lightbox

Optional parameters:

  • All the features/parameters of Hugo's built-in figure shortcode work as normal, i.e. src, link, title, caption, class, attr (attribution), attrlink, alt
  • size (e.g. size="1024x768") pre-defines the image size for PhotoSwipe. Use this option if you don't want to pre-load the linked image to determine its size.
  • class allows you to set any custom classes you want on the <figure> tag.

Optional parameters for standalone {{< figure >}} shortcodes only (i.e. don't use on {{< figure >}} inside {{< gallery >}} - strange things may happen if you do):

  • caption-position and caption-effect work the same as for the {{< gallery >}} shortcode (see below).
  • width defines the max-width of the image displayed on the page. If using a thumbnail for a standalone figure, set this equal to your thumbnail's native width to make the captions behave properly (or feel free to come up with a better solution and submit a pull request :-)). Also use this option if you don't have a thumbnail and you don't want the hi-res image to take up the entire width of the screen/container.
  • class="no-photoswipe" prevents a <figure> from being loaded into PhotoSwipe. If you click on the figure you'll instead a good ol' fashioned hyperlink to a bigger image (or - if you haven't specified a bigger image - the same one).

{{< gallery >}} shortcode usage

To specify a directory of image files:

{{< gallery dir="/img/your-directory-of-images/" />}}`
  • The images are automatically captioned with the file name.
  • [image].jpg is used for the hi-res image, and [image]-thumb.jpg is used for the thumbnails.
  • If [image]-thumb.jpg doesn't exist, then [image].jpg will be used for both hi-res and thumbnail images.
  • The default thumbnail suffix is -thumb, but you can specify a different one e.g. thumb="-small" or thumb="_150x150".

To specify individual image files:

{{< gallery >}}
  {{< figure src="image1.jpg" >}}
  {{< figure src="image2.jpg" >}}
  {{< figure src="image3.jpg" >}}
{{< /gallery >}}

Optional parameters:

  • caption-position - determines the captions' position over the image. Options:
    • bottom (default)
    • center
    • none hides captions on the page (they will only show in PhotoSwipe)
  • caption-effect - determines if/how captions appear upon hover. Options:
    • slide (default)
    • fade
    • none (captions always visible)
  • hover-effect - determines if/how images change upon hover. Options:
    • zoom (default)
    • grow
    • shrink
    • slideup
    • slidedown
    • none
  • hover-transition - determines if/how images change upon hover. Options:
    • not set - smooth transition (default)
    • none - hard transition

PhotoSwipe usage

  • Call {{< load-photoswipe >}} once on each page where you want to use PhotoSwipe.
  • It doesn't matter where on the page.
  • If you don't load PhotoSwipe, each figure will instead have a good ol' fashioned hyperlink to a bigger image (or - if you haven't specified a bigger image - the same one).

You can optionally have different captions on page vs in PhotoSwipe:

  • {{< figure src="image.jpg" alt="This is a caption">}} or {{< figure src="image.jpg" caption="This is a caption">}} will use the same caption both on the page and in PhotoSwipe.
  • {{< figure src="image.jpg" caption="A short caption" alt="This is a much longer, verbose, comprehensive caption that will be used in PhotoSwipe">}} will use a different caption in PhotoSwipe.

CSS Hackers

hugo-easy-gallery.css is designed to provide square tiles in a container with max-width: 768px.

Here are some pointers if you want to adapt the CSS:

  • Change .gallery {max-width: 768px;} if you want a gallery wider than 768px.
  • Change min-width in the @media styles to change the screen widths at which the layout changes
  • Change min-width: 9999px in the last @media style to something sensible if you want to use a 4-tile layout
  • If you want more than 4 tiles per row, set width = 100% / number of tiles per row
  • padding-bottom = width gives square tiles. Change padding-bottom if you want some other aspect ratio, e.g. width: 33.3%; padding-bottom: 25% gives a 4:3 aspect ratio.


I've tested this with the beautifulhugo theme. If things don't work properly with other themes, raise an issue on GitHub, or even better fix the issue and submit a pull request :-)


These blog posts helped me immensely:


Automagical css image gallery in Hugo using shortcodes, with optional lightbox/carousel gadget using PhotoSwipe and jQuery.




No releases published
You can’t perform that action at this time.