Having a random header on reload is a neat feature. I managed to get it to work. Try it… hit reload!. I have included my initial attempt which didn’t work but parts of it made it into the solution.
The initial idea
Loop through header images and construct a list
I have placed all the header images that I would like to randomize in /assets/images/headers/
. So I want to loop over all site.static_files
and add only the images within that specific folder to my list.
1
2
3
4
5
6
7
8
9
10
<!-- init the list -->
{% assign headers = "" | split: ',' %}
<!-- loop and add -->
{% for image in site.static_files %}
{% if image.path contains '/assets/images/headers/' %}
<!-- add image -->
{% assign headers = headers | push: image.path %}
{% endif %}
{% endfor %}
We can now have a look at what is stored in the headers
array with:
1
{{ headers | inspect }}
which outputs:
["/assets/images/headers/CIG_Group_Photo_2.jpg", "/assets/images/headers/c72dcb0f-8d7a-4956-b49e-5b8461c777a2.jpg", "/assets/images/headers/cig_llnl_sw4_ws.jpg", "/assets/images/headers/e0642ed4-7bb9-41e3-ae9e-52a8d75ea044.jpg", "/assets/images/headers/img_0144.jpg", "/assets/images/headers/img_0319.jpg", "/assets/images/headers/img_0376.jpg", "/assets/images/headers/img_0551.jpg", "/assets/images/headers/img_1540.jpg", "/assets/images/headers/img_1912-pano.jpg", "/assets/images/headers/img_1912.jpg", "/assets/images/headers/img_2407.jpg", "/assets/images/headers/img_2423.jpg", "/assets/images/headers/img_2426-animation.gif", "/assets/images/headers/img_2427.jpg", "/assets/images/headers/img_2428.jpg", "/assets/images/headers/img_2553.jpg", "/assets/images/headers/img_2583.jpg", "/assets/images/headers/img_3022.jpg", "/assets/images/headers/img_3139.jpg", "/assets/images/headers/img_3187.jpg", "/assets/images/headers/img_3217.jpg", "/assets/images/headers/img_3619.jpg", "/assets/images/headers/img_3672.jpg", "/assets/images/headers/img_4365.jpg", "/assets/images/headers/img_4637.jpg", "/assets/images/headers/img_4829.jpg", "/assets/images/headers/img_5227.jpg", "/assets/images/headers/img_5275.jpg", "/assets/images/headers/img_5296.jpg", "/assets/images/headers/img_5297.jpg", "/assets/images/headers/img_5306.jpg", "/assets/images/headers/img_5325.jpg", "/assets/images/headers/img_5875.jpg", "/assets/images/headers/img_5896.jpg", "/assets/images/headers/img_5903.jpg", "/assets/images/headers/img_6016.jpg", "/assets/images/headers/phd_overview.png", "/assets/images/headers/wadi_rum_pan.jpg"]
Pick a random header
Using the sample
filter we get a random item from the headers
array.
1
2
{% assign random-header = headers | sample %}
{{ random-header | inspect }}
"/assets/images/headers/img_5275.jpg"
The problem is that because Jekyll is a static site generator, this happens when the static page is built and not on reload. So we need to encapsulate this in a JavaScript that is executed every time a page is served.
The solution
I found this very helpfull post by James W Thorne that mixes Liquid code and JavaScript code. This may not be the most elegant solution but id works.
default.html layout
I added the following JavaScript/Liquid mix to the <head>
section of the default.html
layout:
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<!-- Load jQuery -->
<script src="/assets/js/vendor/jquery/jquery-3.3.1.min.js" type="text/javascript"></script>
{% if page.header.image == 'random' or page.header.overlay_image == 'random' %}
<!-- Make a list of header images -->
<!-- init the list -->
{% assign header_images = "" | split: ',' %}
<!-- loop and add -->
{% for image in site.static_files %}
{% if image.path contains '/assets/images/headers/' %}
<!-- add image -->
{% assign header_images = header_images | push: image.path %}
{% endif %}
{% endfor %}
<!--
Javascript and Liquid code to gather a list of all header images
in /assets/images/headers/
-->
<script type="text/javascript">
// get images from ``header_images`` array to js var
var header_images = [
{% for image in header_images %}
"{{ site.baseurl }}{{ image }}",
{% endfor %}
];
var randomIndex = Math.floor(Math.random() * header_images.length);
// and the winning ``header_image`` is...
var header_image = header_images[randomIndex]
// image without overlay
{% if page.header.image == 'random' %}
$(document).ready(function() {
$(".page__hero-image").attr('src', header_image);
});
// image with overlay
{% elsif page.header.overlay_image == 'random' %}
// make sure overlay filter is handled correctly
{% if page.header.overlay_filter contains "rgba" %}
{% capture overlay_filter %}{{ page.header.overlay_filter }}{% endcapture %}
{% elsif page.header.overlay_filter %}
{% capture overlay_filter %}rgba(0, 0, 0, {{ page.header.overlay_filter }}){% endcapture %}
{% endif %}
$(document).ready(function() {
$(".page__hero--overlay").attr('style',
'{% if page.header.overlay_color %}
background-color: {{ page.header.overlay_color | default:
"transparent" }};
{% endif %}
background-image: {% if overlay_filter %}
linear-gradient({{ overlay_filter }}, {{ overlay_filter }}),
{% endif %}url(' + header_image + ')');
});
{% endif %}
</script>
{% endif %}
Line 2 loads the jQuery library that allows setting the src
attribute of the .page__hero-image
class in the case of image:
or the style
attribute of the .page__hero--overlay
class in the case of overlay_image:
.
On build, line 4 makes sure nothing happens unless randomization is needed. If not, lines 5 through 62 will completely vanish from the page source.
Lines 7 through 15 compile a list of images in /assets/images/headers/
and assigns that list to a header_images
array variable. This is outside the JavaScrip code so it is run only when the page is built, not every time it is served.
The contents of the square brackets between lines 23 and 27 must be one line. Similarly, Lines 50 through 57 must be one line. *Lines here are broken for readability.
YAML front matter
Every other layout is initially dependent on the default
layout so header image
or overlay_image
can be randomized in all layouts. Simply set image: random
or overlay_image: random
in the front matter and you are set.
Here is an example of a page with a random header image (unlike this post which has a random header overlay_image
). If you were wondering what the front matter for this post looks like, here it is:
1
2
3
4
5
6
7
8
9
10
11
12
---
title: Randomizing header image
header:
overlay_image: random
overlay_filter: rgba(255, 255, 255, 0.3)
caption: "Image subject to Copyright: [**© Shahar Shani-Kadmiel**](https://shaharkadmiel.github.io)"
tags: [Random stuff, Images, Jekyll, Liquid, JavaScript, jQuery, Hacking]
toc: true
toc_label: "Contents"
author_profile: true
published: true
---
Leave a Comment