Clay Harmon Blog Just another internet ASCII hole

Site Redesign with Jekyll part 3 - fixing the images

The situation

As I mentioned in the two prior posts, I decided to modify a nice simple Jekyll theme called Lanyon for my new website.

Since I am relying on Squarespace for my image-heavy content, I really don’t have to do a lot of heavy-lifting in that category in this text-centric part of my website. Squarespace excels at allowing a non-technical user to quickly upload and arrange image galleries and videos, and it handles all the messy stuff that kind of content invariably brings with it. However, its ability to perform as a real blogging engine, i.e. text-centric and easy-to-use, sort of sucks. Making mommy-blog recipe posts look amazing is something Squarespace does extremely well. Handling nerdy technology-centric posts like I make with computer code and equations is another matter.

So I decided to do what all programmers are taught: create a separation of concerns. I use Squarespace for the image-heavy and text-light stuff, and a Jekyll site hosted on Github to display all of my writing.

The issue

Now to get to the gist of this post, with, yes, a gist. One of the things about my blog is that there is occasionally a post for some activity that requires a lot of images. My post about a long hike in Wyoming has over 20 images! When I looked at how the theme handled images, it was a little underwhelming. I wanted my images to display with a caption and look nice to boot. But I did not want to give up the ease of writing a post in Markdown and have to code in a bunch of HTML tags for each image so I could have a caption on each image.

A partial solution

The way to drop an image into a Markdown document is by using this shorthand when writing the plain text Markdown document: ![image description](image url) This is in contrast to doing it in HTML:<img src="image url" alt="image description"/> What I did not know until sleuthing on the internets is that Markdown also accepts a string that is the “title” attribute of the image tag. This means that I can embed an image with this Markdown: ![image description](image_url "Image Title").

I also discovered that the Kramdown Markdown parser used by Jekyll allows the addition of CSS classes to markdown elements with this syntax: ![image description](image_url "Image Title"){: .class-one .class-two .class-etc}. This gave me the idea that I could still enjoy the mostly pure Markdown writing experience and be able to style the images with some special CSS classes such as “half-width-flush-right” or “half-width-flush-left”. These are not actually the class names I used, but you get the idea. All these new-to-me discoveries resulted in:

via GIPHY

Both of these things allow me to add an image with a title when writing in Markdown without having to be a tag-jockey. But of course, I want more. I wanted to surround the image tag that the Jekyll blog engine creates with a more semantically appropriate set of tags that could then be styled. The Jekyll engine spits this HTML when it runs across this Markdown expression:

<img src="image_url" alt="image description" title="image caption"/>

But I want it all

However, I really want the tag structure to look like this:

<figure>
    <img src="image_url" alt="image description" title="image caption">
    <figcaption>image caption</figcaption>
</figure>

I realized that I was going to have to use some Javascript to add what was missing to my HTML document. I figured that surely someone had already run into this issue and solved it. I googled furiously, and yet was not able to find a solution that did exactly what I wanted. I wanted a pure Javascript solution that did not require me to include JQuery on all of my site’s pages.

The solution

I fired up the search engine, did some reading, and wrote a little Javascript script (that seems redundant to me) that is in my Jekyll _includes folder. This include is added in my default layout to the bottom of every document made by the Jekyll engine.

Here is the gist:

I am not a Javscript programmer by any measure, and I am certain someone could write this more efficiently, but essentially what this little script does is find all the image tags on a HTML document generated by the Jekyll engine. It then takes each <img> tag in succesion in a ‘for’ loop. The first steps extracts all the CSS classes from the <img> tag, if they exist, and adds them to a new <figure> tag, then removes them from the original <img> tag.

The script then surrounds the original <img> tag with a <figure> tag and then extracts the title attribute from the image tag and writes it between a <figcaption> tag pair. The <img> tag and the <figcaption> tag are siblings nested inside the <figure> tag. Like all Javascript, in my experience, you have to stare at this a moment, but it is fairly straightforward.

One thing that I added after using this a while is the conditional inside the ‘for’ loop that tests each image for a class of ‘not-figure’. If an image tag contains the ‘not-figure’ tag, the script does nothing and moves on to the next image tag on the page. The reason I needed to add this is so that images used in the the framework or scaffolding part of the site (as opposed to the actual content) are not affected. This script will not affect any image tag written like this: <img class='not-figure' href="img_url"> . There are always a few images in any site that could be a part of the site’s look and feel. And these types of images don’t need to be styled in any way. I felt it was far more likely that an image would exist in a post rather than be part of the site’s scaffolding, so I made the exception for the framework images.

Now, I have some fat juicy c elements to target with my CSS. I modified my .scss file to center the content, add a tasteful drop shadow and centered up the captions under each image. Here is the CSS code:

/*---Styling for figure, video and figcaption elements ---*/


figure, video, iframe{
  display:block;
  padding: 1rem;
  margin-left: auto;
  margin-right: auto;
  border-radius: .25rem;
  box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.12);
}
video{
  margin-bottom:1rem;
}
figcaption{
  display:block;
  padding-top:1rem;
  text-align:center;
  font-weight:400;
}
figure img{
  margin-left: auto;
  margin-right: auto;
}

And here is the result:

Blue Steel

Hope this helps!