Posted onby

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

The markdown engine we use for is Kramdown, and that is the onewe'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

Go to gem file add gem 'kramdown-parser-gfm' open terminal and give command bundler after install all packages, in terminal give command bundle exec jekyll serve I hope application will run properly now.

  • Classes, IDs and Attributes
  • HTML Blocks

The kramdown library is mainly written to support the kramdown-to-HTML conversion chain. However, due to its flexibility (by creating an internal AST) it supports other input and output formats as well. Here is a list of the supported formats: input formats: kramdown (a Markdown superset), Markdown, GFM, HTML. Footnotes (Kramdown) This is some text. ^1: Some. crazy. footnote definition. With kramdown, creating a Table of Contents is the easiest thing ever! The automatic ToC will include every heading in the document, unless you don't want it to be included. You do not need to add anchors individually to every title.

Our Markdown Guide

Last week a lot of people were happy for our Handbook being open source, as we explainedin 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 markupthat 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 opensource project available for peeking and contributing, can use anyof the rules explained there. This April we changed the markdown engine from RDiscount toKramdown, and not everybody in our Team knew the new 'magical' stuff we could use from this change. That'swhy we decided that writing a guide would be useful for those already used to markdown, andhelpful for those completely new to it.

Why Kramdown

Perhaps your first question will be something like 'okay, why is Kramdown so special?'. My firstexperience with markdown was when I first used a Static Site Generator, Jekyll. Coming fromprevious experiences in web development on PHP and HTML, the first thing I wanted to do to amarkdown post was adding a class to a particular heading. When I googled for that, I was prettydisappointed 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 finallyfound out that with Kramdown, yes, I could do a lot of things. And finally I could apply some inline classesthrough my posts and have my blue headings when I wanted them blue. But at that time, I hadn't noticedthat 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 customattributes to the elements.

Applying classes

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

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

And of course, the output will be:


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

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

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


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

And the output will be as expected:


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 wordsin the heading together, connected by dashes. For the example above, 'A blue heading', the HTML output IDwill be a-blue-heading:

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

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

So, the output would be:


Kramdown editor

Note that we can attribute both class and ID in one markup, as in {: .class #custom-id}. But we can usejust 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:

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

But they are specially useful for links, as in:

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


Table of Contents (ToC)

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

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:

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

Awesome, isn't it?

HTML Blocks

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

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 can embed anything within <iframe> tags, such as YouTube and Vimeo videos,Google and OneDrive documents and anything else available in iframes:

We are using the class video_container to make it responsive.



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:

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 upHTML and markdown:

And we can close it any time, if necessary:

This is going to make this:

To be displayed like this:


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.


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 thetag to any part of your markdown:

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


There is a lot more you can do, mix, and bring together using Kramdown. It's awesome! Check outour Markdown Guide for more resources, examples and applications and use your creativity to createbeautiful 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 thesource file. Your collaboration is much appreciated.

Happy markdowning!

Follow @GitLab and stay tunned for the next post!

Below are examples of all available structural elements that can be used in a kramdown text. Sincethe kramdown syntax is a superset of the Markdown syntax, only a small part of the available syntaxis not available in standard Markdown syntax. Note, that only the most basic syntax information isgiven. However, a link to the detailed syntax for each element is provided (which also details thedifferences to the standard Markdown syntax). The quick reference is for version <%=::Kramdown::VERSION %> of the syntax documentation.

kramdown has two main classes of elements: block and span-level elements. Block-level elements areused to create paragraphs, headers, lists and so on whereas span-level elements are used to markuptext phrases as emphasized, as a link and so on.

All examples below feature the kramdown source, the converted HTML source (shown when hovering overthe kramdown source) and the output as it appears in the browser. This looks like this:


{kdlink: {oid: paragraphs, part: 'paragraphs'}}

Consecutive lines of text are considered to be one paragraph. As with other block level elements youhave to add a blank line to separate it from the following block-level element:

{kdexample::}The first paragraph.

Another paragraph{kdexample}

Explicit line breaks in a paragraph can be made by using two spaces or two backslashes at the end of a line:

{kdexample::}This is a paragraph
which contains a hard line break.{kdexample}


{kdlink: {oid: headers, part: 'headers'}}

kramdown supports Setext style headers and atx style headers. A header must always be preceded by ablank line except at the beginning of the document:

Second level header



H2 header

H3 header

H4 header

H5 header
H6 header


If you set the option auto_ids to false (for example, by using the options extension, seeExtensions), then the automatic header ID generation is turned off:

{kdexample::}{::options auto_ids='false' /}



{kdlink: {oid: blockquotes, part: 'blockquotes'}}

A blockquote is started using the > marker followed by an optional space; all following lines thatare also started with the blockquote marker belong to the blockquote. You can use any block-levelelements inside a blockquote:


A sample blockquote.

Nested blockquotes arealso possible.

Headers work too

This is the outer quote again.{kdexample}

You may also be lazy with the > markers as long as there is no blank line:


This is a blockquotecontinued on thisand this line.

But this is a separate paragraph.{kdexample}

Code Blocks

{kdlink: {oid: code-blocks, part: 'code blocks'}}

kramdown supports two different code block styles. One uses lines indented with either four spacesor one tab whereas the other uses lines with tilde characters as delimiters -- therefore the contentdoes not need to be indented:

{kdexample::}This is a sample code block.




The following is a code block with a language specified:



Horizontal Rules

{kdlink: {oid: horizontal-rules, part: 'horizontal rules'}}

It is easy to insert a horizontal rule in kramdown: just use three or more asterisks, dashes orunderscores, optionally separated by spaces or tabs, on an otherwise blank line:





{kdlink: {oid: lists, part: 'lists'}}

kramdown supports ordered and unordered lists. Ordered lists are started by using a number followedby a period, a space and then the list item text. The content of a list item consists of block-levelelements. All lines which have the same indent as the text of the line with the list marker belongto the list item:


  1. This is a list item
  2. And another item
  3. And the third onewith additional text{kdexample}

As with block quotes, you may be lazy when using the list item marker:


  • A list itemwith additional text{kdexample}

As the content consists of block-level elements you can do things like the following:


  1. This is a list item

    with a blockquote

  2. Followed by another item{kdexample}

Nested lists are also easy to create:


  1. Item one
    1. sub item one
    2. sub item two
    3. sub item three
  2. Item two{kdexample}

Lists can occur directly after other block-level elements, however, there has to be at least oneblank line if you want to follow a paragraph with a list:

{kdexample::}This is a paragraph.

  1. This is NOT a list.

  2. This is a list!{kdexample}

Unordered lists are started by using an asterisk, a dash or a plus sign (they can be mixed) and aspace. Apart from that unordered lists follow the same rules as ordered lists:


  • Item one
  • Item two
  • Item three{kdexample}

Definition Lists

{kdlink: {oid: definition-lists, part: 'definition lists'}}

A definition list works similar to a normal list and is used to associate definitions with terms.Definition lists are started when a normal paragraph is followed by a line starting with a colon andthen the definition text. One term can have many definitions and multiple terms can have the samedefinition. Each line of the preceding paragraph is assumed to contain one term, for example:

{kdexample::}term: definition: another definition

another termand another term: and a definition for the term{kdexample}

If you insert a blank line before a definition (note: there must only be one blank line between theterms and the first definition), the definition will be wrapped in a paragraph:


: definition: definition{kdexample}

Each term can be styled using span-level elements and each definition is parsed as block-levelelements, i.e. you can use any block-level in a definition. Just use the same indent for the linesfollowing the definition line:

{kdexample::}This is a term

: This will be a para

a blockquote



{kdlink: {oid: tables, part: 'tables'}}

kramdown supports a syntax for creating simple tables. A line starting with a pipe character ()starts a table row. However, if the pipe characters is immediately followed by a dash (-), aseparator line is created. Separator lines are used to split the table header from the table body(and optionally align the table columns) and to split the table body into multiple parts. If thepipe character is followed by an equal sign (=), the tables rows below it are part of the tablefooter.

{kdexample::} A simple table with multiple lines {kdexample}


{: rules='groups'}

HTML elements

{kdlink: {oid: html-blocks, part: 'HTML blocks'}}

kramdown allows you to use block-level HTML tags (div, p, pre, ...) to markup whole blocks oftext -- just start a line with a block-level HTML tag. kramdown syntax is normally not processedinside an HTML tag but this can be changed with the parse_block_html option. If this options isset to true, then the content of a block-level HTML tag is parsed by kramdown either as blocklevel or span-level text, depending on the tag:


Something that stays right and is not wrapped in a para.

{::options parse_block_html='true' /}

This can contain only *span* level elements.


Block Attributes

{kdlink: {oid: block-ials, part: 'block IALs'}}{kdlink: {oid: attribute-list-definitions, part: 'ALDs'}}

You can assign any attribute to a block-level element. Just directly follow the block with a blockinline attribute list (or short: block IAL). A block IAL consists of a left curly brace, followedby a colon, the attribute definitions and a right curly brace. Here is a simple example which sets thetitle attribute of a block quote:


A nice blockquote{:}{kdexample}

As one often wants to set one or more CSS classes on an element, there is an easy shortcut:


A nice blockquote{: .class1 .class2}{kdexample}

A shortcut for setting the ID is also provided. Just prefix the ID with a hash symbol:


A nice blockquote{: #with-an-id}{kdexample}

Sometimes one wants to use the same attributes for many elements. kramdown allows you to define theattributes in one place with an attribute list definition (or short: ALD) and just reference thisdefinition in a block IAL. An ALD has the same structure as a block IAL but the colon has to bereplace with a colon, the reference name and another colon. By just using the reference name as-isin a block IAL, one can include the attributes of the referenced ALD:

{kdexample::}{:refdef: .c1 #id .c2}paragraph{: refdef}{kdexample}

The order in a block IAL or ALD is important because later defined attributes overwrite (with theexception of the shortcut for CSS classes) prior defined attributes:

{kdexample::}{:refdef: .c1 #id .c2}paragraph{: refdef .c3 #para}{kdexample}


{kdlink: {oid: extensions, part: 'extensions'}}

kramdown provides some less used functionality through a common syntax. This will allow the easyaddition of other extensions if need arises. Currently, there are extensions for ignoring text (i.e.treating text as comment), for inserting arbitrary text as-is into the output and for settingkramdown options.

Here is an example that shows how to insert comments into text:

{kdexample::}This is a paragraph{::comment}This is a comment which iscompletely ignored.{:/comment}... paragraph continues here.

Extensions can also be usedinline {::nomarkdown}see{:/}!{kdexample}

As one can see from the above example, the syntax for extensions is nearly identical to that ofALDs. However, there is no trailing colon after the extension name and the extension end tag needs aslash between the colon and the extension name. One can also use the short form of the end tag, i.e.{:/}. Attribute definitions can be specified on the start tag by separating them with a space fromthe extension name. Also, if the extension does not have a body, there needs to be a slash rightbefore the closing brace:


{kdexample::}{::options auto_ids='false' /}



{kdlink: {oid: emphasis, part: 'emphasis'}}

Emphasis can be added to text by surrounding the text with either asterisks or underscores:

{kdexample::}This is emphasized,this too!{kdexample}

Strong emphasis can be done by doubling the delimiters:

{kdexample::}This is strong,this too!{kdexample}

Kramdown Image

The form with the asterisks can also be used to markup parts of words:

{kdexample::}This works as expected!{kdexample}

Links and Images

{kdlink: {oid: links-and-images, part: 'links and images'}}

A simple link can be created by surrounding the text with square brackets and the link URL withparentheses:

{kdexample::}A linkto the kramdown homepage.{kdexample}

You can also add title information to the link:

{kdexample::}A linkto the homepage.{kdexample}

There is another way to create links which does not interrupt the text flow. The URL and title aredefined using a reference name and this reference name is then used in square brackets instead ofthe link URL:

{kdexample::}A linkto the homepage.


If the link text itself is the reference name, the second set of square brackets can be omitted:

{kdexample::}A link to the kramdown hp.


Images can be created in a similar way: just use an exclamation mark before the square brackets. Thelink text will become the alternative text of the image and the link URL specifies the image source:

{kdexample::}An image: {kdexample}

Inline Code

Kramdown Toc

{kdlink: {oid: code-spans, part: 'code spans'}}

Text phrases can be easily marked up as code by surrounding them with backticks:

{kdexample::}Use convert the text in kramdownsyntax to HTML.{kdexample}

If you want to use literal backticks in your code, just use two or more backticks as delimiters. Thespace right after the beginning delimiter and the one right before the closing delimiter are ignore:

{kdexample::}Use backticks to markup code,e.g. `code`.{kdexample}


{kdlink: {oid: footnotes, part: 'footnotes'}}

Footnotes can easily be used in kramdown. Just set a footnote marker (consists of square bracketswith a caret and the footnote name inside) in the text and somewhere else the footnote definition (whichbasically looks like a reference link definition):

{kdexample::}This is a text with afootnote[^1].

[^1]: And here is the definition.{kdexample}

The footnote definition can contain any block-level element, all lines following a footnotedefinition indented with four spaces or one tab belong to the definition:

{kdexample::}This is a text with afootnote[^2].

[^2]:And here is the definition.


As can be seen above the footnote name is only used for the anchors and the numbering is doneautomatically in document order. Repeated footnote markers will link to the same footnotedefinition.


{kdlink: {oid: abbreviations, part: 'abbreviations'}}

Abbreviations will work out of the box once you add an abbreviation definition. So you can justwrite the text and add the definitions later on.

{kdexample::}This is an HTMLexample.

*[HTML]: Hyper Text Markup Language{kdexample}

HTML Elements

{kdlink: {oid: html-spans, part: 'HTML spans'}}

HTML is not only supported on the block-level but also on the span-level:

Kramdown Ruby

{kdexample::}This is written inred.{kdexample}

Inline Attributes

{kdlink: {oid: span-ials, part: 'span IALs'}}

Kramdown Table

As with a block-level element you can assign any attribute to a span-level elements using a spaninline attribute list (or short: span IAL). A span IAL has the same syntax as a block IAL and mustimmediately follow the span-level element:


{kdexample::}This is red{:}.{kdexample}