published on 24.01.2021
edited on 11.06.2021

Some time ago, I wanted to display image galleries on my Hugo website and searched for Hugo themes for photography and gallery. I can’t say I find much. Then, I met with a javascript library called nanogallery2 which is using another javascript library as an image viewer lightbox2. In this post, I’ll explain how I used nanogallery2 on my Hugo website. I assume that you know about image processing in Hugo or read my previous post.

Use LightBox in a Post

Lightbox2 is a javascript library developed by Lokesh Dhakar. It displays images and videos in a good looking way. NanoGallery2 is another library, which is using lightbox2 as an image viewer and has its other features.

To use an image in a post I have created a shortcode called named img: /layouts/shortcodes/img.html. You can see the whole img shortcode at the end of the post but I’ll continue by taking only the related part with nanogallery2:

1
2
3
{{ $image = resources.GetMatch (.Get "src") }}
{{ $.Scratch.Set "thumbnail" ($image.Resize "600x q90") }}
<img src="{{ ($.Scratch.Get "thumbnail").RelPermalink }}" data-ngsrc="{{$image.RelPermalink}}" alt="{{ $caption }}"/>
  • We get the resource $image.
  • Create a smaller one and call it thumbnail.
  • Pass the original image we want to display as data-ngsrc.

You can see the original concept from nanogallery2 documentation

Additionaly, we can change the default settings by providing data-nanogallery2-lightbox. The settings should be in json format, you can directly add the parameters you want into html or keep the settings in a separate file and pass it to the HTML using Hugo’s getJSON function. To learn about the settings, you must read the nanogallery2’s documentation.

1
2
3
4
{{ $nanogallery2_settings := getJSON "/static/ng2_lightbox.json" | jsonify}}

<img src="{{ ($.Scratch.Get "thumbnail").RelPermalink }}" data-ngsrc="{{$image.RelPermalink}}" 
data-nanogallery2-lightbox="{{$nanogallery2_settings}}" alt="{{ $caption }}"/>

Click on the image to see lightbox in action.

Village of Sekiya at Sumida River
Village of Sekiya at Sumida River

Use NanoGallery2

This is probably not very useful for a blog post we can use the gallery view too. To do that, I’ve created a separate shortcode called gallery.html. This one takes a directory and displays the resources under that directory.

You can call the gallery shortcode like this: {{/< gallery directory="images/posts/nanogallery/*" >}} Don’t forget the star at the end, read the pattern matching for more info.

images/posts/nanogallery/IMG_20190702_155840 (Large).jpg [ images/posts/nanogallery/IMG_20190702_160055 (Large).jpg [ images/posts/nanogallery/IMG_20190702_160231 (Large).jpg [ images/posts/nanogallery/IMG_20190925_083347 (Large).jpg [ images/posts/nanogallery/IMG_20200106_113749 (Medium).jpg [ images/posts/nanogallery/IMG_20200106_113826 (Medium).jpg [ images/posts/nanogallery/IMG_20200106_113902 (Medium).jpg [ images/posts/nanogallery/IMG_20200106_115825 (Medium).jpg []

Recently, as a weekend project, I’ve created an image gallery site for myself. I’ve published the project on GitLab: Art-Collection Theme. It’s pretty simple and it, probably, requires some improvements. It doesn’t allow you to publish text content. Yet, I learned a lot while building it.

The Libraries

To use the libraries, we have to load them, usually in the head section of the HTML. Jquery is a dependency of nanogallery2, so we have to add it too.

1
2
3
4
5
{{ if .Params.gallery }}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/nanogallery2/3.0.4/css/nanogallery2.min.css"/>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/nanogallery2/3.0.4/jquery.nanogallery2.min.js"></script>
{{ end }}

You should set gallery: true in the page’s front-matter, in order to load these scripts. Otherwise, they won’t be loaded. This is just a small trick for not adding the libraries to all the pages if we are not going to use them.


1
2
3
4
5
6
7
8
{{ $nanogallery2_settings := getJSON "/static/ng2_gallery_compact.json" | jsonify}}

<div data-nanogallery2="{{$nanogallery2_settings}}">
    {{ range $index, $image := sort (resources.Match (.Get "directory")) }}
    {{ $.Scratch.Set "thumbnail" ($image.Resize "x300 q90") }}
    <a href="{{ $image.RelPermalink }}" data-ngthumb="{{ ($.Scratch.Get "thumbnail").RelPermalink }}">{{$image.Name}}</a>
    [{{ end }}]
</div>

img shortcode

I used <figure> instead of <img> alone to be able to add caption when necessary. The shortcode seems long but what it does is actually simple.

  • It takes an image, checks it’s size
  • If the image is bigger than 600x450,
  • Then, it resize the image as 600x width or x450 height, based on the image rotation and protects the aspect ratio.
  • Use the smaller image in post and sets the original image as a link (so we may show it on full quality on click).
1
2
3
4
5
6
7
Inputs:
    - src: image path [required]
    - class: center, right, left
    - width: width for image (example: 400px, 20%)
    - caption: text for caption
    - alt: alt text for the image (caption will be used if not specified)
    - link: href on caption

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{{ $class :=  or (.Get "class") "center" }}
{{ $image = resources.GetMatch (.Get "src") }}
{{ $caption := "" }}


{{/* Generate Thumbnail */}}
{{ if ge $image.Width $image.Height }}
{{ if ge $image.Width "600" }}
    {{ $.Scratch.Set "thumbnail" ($image.Resize "600x q90") }}
{{ else}}
    {{ $.Scratch.Set "thumbnail" $image }}
{{ end }}
{{ else }}
{{ if ge $image.Height "450" }}
    {{ $.Scratch.Set "thumbnail" ($image.Resize "x450 q90") }}
{{ else }}
    {{ $.Scratch.Set "thumbnail" $image }}
{{ end }}
{{ end }}

{{ if (.Get "caption") }}
    {{ $caption = (.Get "caption" | markdownify | plainify) }}
{{ else }}
    {{ $caption = (path.Split $image.Name).File }}
{{ end }}

{{ $nanogallery2_settings := getJSON "/static/ng2_lightbox.json" | jsonify}}

<figure class="{{ $class }}">
<img src="{{ ($.Scratch.Get "thumbnail").RelPermalink }}" data-ngsrc="{{$image.RelPermalink}}"
    data-nanogallery2-lightbox="{{$nanogallery2_settings}}"
    alt="{{ $caption }}" {{ with .Get "width" }} width="{{.}}"{{ end }}/>
{{ with .Get "link" }}<a href="{{.}}">{{ end }}
{{ with .Get "caption" }}<figcaption>{{ $caption }}</figcaption>{{ end }}
{{ if .Get "link" }}</a>{{ end }}
</figure>
You are reading the 19th of 19 episodes in Hugo.
Published on 24.01.2021 by Mert Bakır. Last update on 11.06.2021 with commit 017b782.
hugo
#hugo #web-dev
published on 23.01.2021
edited on 11.06.2021

Image processing may seem complicated at first but it’s actually easy and definitely worth implementing since it’ll help you decrease page load times. As you probably know, we don’t want to load raw images with huge sizes for small thumbnails or blog-posts. We want to load a small …

published on 29.11.2020
edited on 05.12.2020

Plotly is a visualization library that allows us to write code in Python, R, or Julia and generates interactive graphs using Javascript. So, we don’t have to deal with Javascript. You can checkout Plotly gallery, there are interesting works. Anyway, last week, I’ve started learning …

published on 18.09.2020
edited on 13.02.2021

First of all, if you don’t know about data files, you may want to start reading from data files in hugo. This post is about a solution for a very particular problem. How can we use “group by” for the data from data files? Let me clarify with an example. I was creating a single page …

published on 30.08.2020

The question is clear. We need to pass variables or arguments in Hugo’s partials. We usually use only the dot when calling partials. {{ partial "foo.html" . }}. The dot means the current page’s context. All it’s variables like .Title, .Permalink, .Content and all others …

published on 31.12.2020
edited on 26.06.2021

I’ve, recently, published a blog post called Perfect Workflow for Publishing Python Notebooks. I talked about some of the benefits of using Rmarkdown and reticulate. In this post, I’ll try HTML widgets and explain how we can embed those in our blog post using nothing but R. […] 1 …

published on 05.12.2020

Resume A4 is a side project of mine. It’s one page Hugo Theme that allows you to write your resume in YAML format and keep track of it using git. Also, you can publish it online as a static site using GitLab, GitHub Pages, Netlify, or some other service you are familiar with. A few months …

published on 30.11.2020

I’ve been searching for a good workflow for publishing Jupyter or RMarkdown Notebooks as static blog posts. I think I’ve found the optimal solution for my use case. In this post, I’ll explain my workflow and why chose this way with examples. […] In reality my main purpose to …