Centering images via JavaScript on a Markdown-based Middleman blog

Background

As much as I detested Markdown when I first began using it, further exposure to the document format across a lot of open-source projects definitely made me reconsider. Another turning point was realizing that I never had to lift a finger to reach for formatting options. A lot of my notes are now by default in .markdown format!

If you use the officially supported middleman-blog gem with your Middleman website, article templates would by default be in Ruby’s ERB template formatting. Seeing as I simply wanted to focus on writing, not on inserting code while writing, I quickly moved to Markdown-based articles with front-matter.

Unfortunately, easy as it is adding images via Markdown syntax, it was not so easy to get the images to center. Writing this in Markdown…

1
![alt-text](https://www.yourwebsite.com/link/to/image.jpeg)

…would render with the following hierarchy in the DOM:

1
2
3
- p
|
-- img

That is, we’d have a paragraph element under which there exists the image element we want.

Is there a CSS fix?

Naturally, one would go to CSS for a ‘visual’ fix and ask themselves: how would I change the paragraph to center-align its children, if there is only child under it – specifically an image element?

Your limitations are that you cannot differentiate between the paragraph elements by adding a CSS ID or Class.

There are dirty fixes involving adding ’#center’ to the end of the image URLs and then using identifiers in CSS to target such elements. Unnecessary.

Alternatively, you can also use fixed-width on the parent element (p) and then specify the margin to 0 auto on the child element ('img’) – but going fixed-width was not an option for me.

OK, is there a Markdown fix?

Depends. Kramdown, for example, has the following syntax for centering elements (including images):

1
->![alt-text](https://www.yourwebsite.com/link/to/image.jpeg)<-

It also allows you to add classes to elements like so:

1
![alt-text](https://www.yourwebsite.com/link/to/image.jpeg){:center_class}

I use Redcarpet, which supposedly does not offer these syntax.

JavaScript to the rescue

Enter JavaScript.

First, collect all paragraph elements by using document.getElementsByTagName. Note that the documentation says (emphasis mine):

The returned HTMLCollection is live, meaning that it updates itself automatically to stay in sync with the DOM tree without having to call document.getElementsByTagName() again.

Cool. That’s good for us!

Next, iterate through each p element in the HTMLCollection object and ask it two questions: do you have only a single element underneath you? If so, is it an img element? Yes - add a style attribute to this p element. No - do nothing.

The JavaScript would look like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
window.onload = function() {
  // IIFE
  (function(){
    els = document.getElementsByTagName('p');
    for (var i = 0; i < els.length; i++) {
      if (els[i].children.length == 1) {
        if (els[i].children[0].outerHTML.substr(1,3) == 'img' ) {
          els[i].setAttribute("style", "text-align: center;");
        }
      }
    }
  })();
}