Blog Engineering Markdown Kramdown Tips and Tricks
July 19, 2016
8 min read

Markdown Kramdown Tips and Tricks

Learn how to apply classes to markdown, create ToCs, embed iframes and much more!

markdown-kramdown-tips-and-tricks-cover.png

If you use a markdown engine for writing your website content and you'd like to learn a few tricks to have more freedom with it, this post is for you.

The markdown engine we use for about.GitLab.com is Kramdown, and that is the one we'll be referring to on this post.

Note: We assume you already know what a markdown engine is and how it is applied to a website.


On this post

  • TOC

Our Markdown Guide

Last week a lot of people were happy for our Handbook being open source, as we explained in details on the post "Our Handbook is open source: here's why". Every GitLab Team member does touch our website, starting on his or her first weeks, as part of the onboarding tasks. Doesn't matter if he or she is an advanced programmer or never have seen an HTML code before, collaborating is the key for making sure we are all on the same side. And we love it!

One of our Handbook pages is a full Markdown Guide for the markup that we use in our website, generated by Middleman. It brings a lot of details on how to use Kramdown for writing content. Every markdown page of this website, which is an open source project available for peeking and contributing, can use any of the rules explained there. This April we changed the markdown engine from RDiscount to Kramdown, and not everybody in our Team knew the new "magical" stuff we could use from this change. That's why we decided that writing a guide would be useful for those already used to markdown, and helpful for those completely new to it.

Why Kramdown

Perhaps your first question will be something like "okay, why is Kramdown so special?". My first experience with markdown was when I first used a Static Site Generator, Jekyll. Coming from previous experiences in web development on PHP and HTML, the first thing I wanted to do to a markdown post was adding a class to a particular heading. When I googled for that, I was pretty disappointed because apparently we aren't supposed to apply classes inline into markdown files. So, I had to experiment a lot until I got the desired result: add some color to my heading.

After trying a lot of new tweaks, and digging through the web for answers that insisted on not coming, I finally found out that with Kramdown, yes, I could do a lot of things. And finally I could apply some inline classes through my posts and have my blue headings when I wanted them blue. But at that time, I hadn't noticed that we could do some really great magic with it, and that's what I'm sharing with you in this post.

The magic

We could say that the Kramdown magic concentrates to the following syntax: {: something}. This little devil is the basis of a lot of awesome resources.

Let's go over a few of them now, but you'll find a lot more in our Markdown Guide.

Classes, IDs and Attributes

Let's start with something classic, as the ability of applying CSS classes, custom IDs, and custom attributes to the elements.

Applying classes

If you think of any CSS class, what comes into your mind first? I suppose it's something like:

.blue {
  color: blue;
}

Okay, we have a .blue class. Let's say once in a while we want a blue paragraph or a blue heading. Just do:

This is a paragraph that for some reason we want blue.
{: .blue}

And of course, the output will be:

**Output** {: .panel-heading}
This is a paragraph that for some reason we want blue. {: .blue}

And if we want a blue heading, we do exact the same thing:

#### A blue heading
{: .blue}

And the output is going to behave as we expect it to:

**Output** {: .panel-heading style="margin-bottom:10px"}
#### A blue heading {: .blue .no_toc}

What if I want to apply two classes at the same time?

A blue and bold paragraph.
{: .blue .bold}

And the output will be as expected:

**Output** {: .panel-heading style="margin-bottom:10px"}
A blue and bold paragraph. {: .blue .bold}

As simple as that! The markup is simple and intuitive.

Now, guess what, we can do exactly the same for IDs!

Custom IDs

Kramdown itself will append an ID for each heading, automatically. The ID will be all the words in the heading together, connected by dashes. For the example above, "A blue heading", the HTML output ID will be a-blue-heading:

<h4 class="blue" id="a-blue-heading">A blue heading</h4>

Let's say we want the ID called blue-h:

#### A blue heading
{: .blue #blue-h}

Will produce exactly what it's meant to (a blue heading with the custom ID):

<h4 class="blue" id="blue-h">A blue heading</h4>

So, the output would be:

**Output** {: .panel-heading style="margin-bottom:10px"}
#### A blue heading {: .blue .no_toc #blue-h}

Note that we can attribute both class and ID in one markup, as in {: .class #custom-id}. But we can use just one of them too: {: .class} or {: #custom-id}.

Interesting, isn't it?

Custom Attributes

Yes, we can go even further and apply any key/value pair we need:

An example of key/value pair
{: .class #id key="value"}

We can use them, for example, for quickly applying general styles:

#### A simple example
{: #custom-id style="margin-top:0"}

But they are specially useful for links, as in:

[text][identifier]{: #custom-id key="value"}

This way we can call a JavaScript function, for example:

[CLICK ME][identifier]{: #custom-id onclick="myJsFunc();"}

<script type="text/javascript">
  function myJsFunc() {
  var answer = confirm ("Please click on OK to continue.")
  if (answer)
  window.location="#";
  }
</script>
**Output** {: .panel-heading}
[CLICK ME][identifier]{: #custom-id onclick="myJsFunc();"}

Table of Contents (ToC)

A ToC is so awesome and easy to produce. Have you noticed our ToC on this post? It's generated automatically by Kramdown with this simple markup:

- TOC
{:toc}

All the file headings will be all automatically included in the ToC, except for those we don't want there. For these, we apply a class called no_toc, and Kramdown will respect our will:

#### This heading will not be included in the ToC.
{: .no_toc}

And of course, we can make the ToC an ordered list instead of unordered:

1. TOC
{:toc}

Awesome, isn't it?


HTML Blocks

Whenever we need HTML blocks, we can use them freely!

<div>
  <p>Hello World</p>
</div>

In our Marketing Handbook you will find plenty of them.

Font Awesome

Font Awesome is a good use-case for HTML blocks within markdown files.

Check this!

We <i class="fas fa-heart" aria-hidden="true" style="color:#c7254e"></i> GitLab!
**Output** {: .panel-heading style="margin-bottom:10px"}
We GitLab!

Iframes

We can embed anything within <iframe> tags, such as YouTube and Vimeo videos, Google and OneDrive documents and anything else available in iframes:

<figure class="video_container">
  <iframe src="https://www.youtube.com/embed/NoFLJLJ7abE" frameborder="0" allowfullscreen="true"> </iframe>
</figure>

We are using the class video_container to make it responsive.

**Output** {: .panel-heading style="margin-bottom:10px"}

CodePen

CodePens are really good for some cases, when you want to display codes and results, for example. Check this cute dog, created with HTML and Sass:

<p data-height="431" data-theme-id="dark" data-slug-hash="OXzjLL" data-default-tab="html,result" data-user="virtuacreative" data-embed-version="2" class="codepen">See the Pen <a href="http://codepen.io/virtuacreative/pen/OXzjLL/">Dog</a> by Virtua Creative (<a href="http://codepen.io/virtuacreative">@virtuacreative</a>) on <a href="http://codepen.io">CodePen</a>.</p>
<script async src="//assets.codepen.io/assets/embed/ei.js"></script>

See the Pen Dog by Virtua Creative (@virtuacreative) on CodePen.


Mix HTML with Markdown

Yes, we definitely can do this! We need to add the following markup to the markdown document before mixing up HTML and markdown:

{::options parse_block_html="true" /}

And we can close it any time, if necessary:

{::options parse_block_html="false" /}

This is going to make this:

Something in **markdown**.

<p>Then an HTML tag with crazy **markup**!</p>

To be displayed like this:

**Output** {: .panel-heading style="margin-bottom:10px"}
Something in **markdown**.

Then an HTML tag with crazy **markup**!

Blue boxes, like this one above, used to display the outputs on this post, were generated with this resource.


Styles

One of the most useful features is the ability to add <style> tags to our markdown file too! We can do that for simply styling our web page without affecting the entire site. Just go on and add the tag to any part of your markdown:

<style>
.blue {
  color: blue;
}
.bold {
  font-weight: bold;
}
</style>

This tag was applied to this very document to exemplify this case, also to help with the classes described earlier in this post.


Conclusion

There is a lot more you can do, mix, and bring together using Kramdown. It's awesome! Check out our Markdown Guide for more resources, examples and applications and use your creativity to create beautiful posts, with great styles!

Anything else you know of and is not in our Guide? Any new magic? Any trick? Please contribute by submitting an MR to the source file. Your collaboration is much appreciated.

Happy markdowning!

Follow @GitLab and stay tunned for the next post!

We want to hear from you

Enjoyed reading this blog post or have questions or feedback? Share your thoughts by creating a new topic in the GitLab community forum. Share your feedback

Ready to get started?

See what your team could do with a unified DevSecOps Platform.

Get free trial

New to GitLab and not sure where to start?

Get started guide

Learn about what GitLab can do for your team

Talk to an expert