layout: page description: Jekyll-style template inheritance title: Template Inheritance tagline: Jekyll-style template inheritance based on layouts group: pages toc: true


:website: www.elastic.co/ :license: Apache License, Version 2.0 :revdate: 2015 :revnumber: 4.2.2

//Ref // {% raw %} Disable from processing to preserve the liquid markup's in the document

.boxShadow

The most powerful – and for sure the most complex – part of a template engine is template inheritance. Template inheritance allows to build base skeleton templates (for the different types of web page) that contains all the common elements. These base templates defines blocks that child templates can overwride.

Template systems like Django's template engine (for Python) fully supports template inheritance - unfortuneatly Liquid (that seems inspired from Django) does NOT. Bad news?

No, not that bad. Read the following how to create building blocks based on Jekyll's layouts and layout inheritance.

To create large sites, consists in complex pages, it is fundamental to *not repeat yourselves* in creating the *building blocks*. Therefor, the Jekyll engine supports template inheritance based on the layout system introduces by Jekyll. Let call this typeof inheritance layout inheritance.

.base template

source, html

<!DOCTYPE html> <html lang=“en”> <head>

<link rel="stylesheet" href="style.css" />
<title>{% block title %}My amazing Web site{% endblock %}</title>

</head>

<body>

<div id="sidebar">
    {% block sidebar %}
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/blog/">Blog</a></li>
    </ul>
    {% endblock %}
</div>

<div id="content">
    {% block content %}{% endblock %}
</div>

</body> </html>


This `base` template, which we’ll call `base.html`, defines a simple HTML skeleton document that you might use for a simple two-column page. It’s the job of `child` templates to fill in the empty blocks with content.

In this example, the `block` tag defines three blocks that can be overwritten by child templates:

* title
* sidebar
* content

All the `block` tag does is to instruct the template engine that a `child` template may override those portions of the `base` template.

A `child` template might look like this:

.child template

source, html

{% extends 'base.html' %}

{% block title %}My amazing Blog{% endblock %}

{% block content %} {% for entry in blog_entries %}

<h2>{{ entry.title }}</h2>
<p>{{ entry.body }}</p>

{% endfor %} {% endblock %}


The `extends` tag is the key here. It tells the template engine that this template extends another template. When the template system evaluates the `child` template, first it's parent is located – in this case `base.html`.

At that point, the template engine parses the three `block` tags in the `base.html` template. These blocks are replaced by the contents of the `child template`. Depending on the value of `blog entries`, the output might look like:

.HTML output

source, html

<!DOCTYPE html> <html lang=“en”> <head>

<link rel="stylesheet" href="style.css" />
<title>My amazing Blog</title>

</head>

<body>

<div id="sidebar">
    <ul>
        <li><a href="/">Home</a></li>
        <li><a href="/blog/">Blog</a></li>
    </ul>
</div>

<div id="content">
    <h2>Entry one</h2>
    <p>This is my first entry.</p>

    <h2>Entry two</h2>
    <p>This is my second entry.</p>
</div>

</body>

</html>


Note that since the child template didn't define the `sidebar` block, the value from the parent template is used instead. Content within a `{% block %}` tag in a parent template is always used as a fallback.

You can use as many levels of inheritance as needed. One common way of using inheritance is the following three-level approach:

* Create a `base.html` template that holds the main look-and-feel of
  your site.

* Create a `base_SECTIONNAME.html` template for each `section` of your
  site. For example, `base_news.html` and `base_sports.html`. These `child`
  templates *extends* the `base.html` template and include section-specific
  styles/design.

* Create individual templates for each type of page, such as a news
  article or blog entry. These templates extend the appropriate section
  template.

This approach maximizes code reuse and makes it easy to add items to shared content areas, such as section-wide navigation.

NOTE

Note, that you can’t define multiple `block` tags with the *same name* in the *same template*. This limitation exists because a block tag works in both directions. That is, a block tag doesn’t just provide a hole to fill – it also defines the content that fills the hole in the __parent__. If there were two similarly-named `block` tags in a template, that template’s parent wouldn’t know which one of the blocks’ content to use.

Working with inheritance

Here some tips for working with inheritance:

* If you use `{% extends %}` in a template, it must be the *first* tag in 
  that template. Template inheritance won’t work, otherwise.

* More `{% block %}` tags in your base templates are better. Remember, child
  templates don’t have to define all parent blocks, so you can fill in 
  reasonable defaults in a number of blocks, then only define the ones you 
  need later. It’s better to have more hooks than fewer.

* If you find yourself duplicating content in a number of templates, it
  probably means you should move that content to a `{% block %}` in a
  parent template.

* If you need to get the content of the block from the `parent` template,
  the `{{ block.super }}` variable will do the trick. This is useful if
  you want to add to the contents of a parent block instead of completely
  overriding it. Data inserted using `{{ block.super }}` will not be
  automatically escaped, since it was already escaped, if necessary, in 
  the parent template.

* For better readability, you can (optionally) give a *name* to your
  `{% endblock %}` tag. For example:

+


{% block content %} … {% endblock content %}


+ In larger templates, this technique helps you see which `{% block %}` tags are being closed.

Stackoverflow

See: stackoverflow.com/questions/13086569/jekyll-templates-using-django-like-liquid-blocks-inheritance

I'm not sure this is ever going to work within Jekyll. I might be wrong, but here's my reasoning:

Each page is rendered out using do_layout in github.com/mojombo/jekyll/blob/master/lib/jekyll/convertible.rb

This works recursively - it processes the content of the page, then processes the page's layout, then that layout's layout and so on and so forth, passing the YAML variables up the chain (so they're always available in parent templates as {{ page.whatever}}).

This means that the only things which get passed up are the YAML values, and whatever the value of 'content' is after it has been processed by Liquid. I don't know how it is done elsewhere, but that seems incompatible with the idea of blocks, as they'd require you to pass up the two blocks separately.

Fundamentally, it seems to me that the issue is that Jekyll already has a simple form of inheritance - via the “layout” attribute that you can give to a layout. Fundamentally, I think that this is compatible with liquid-templating.

All that said, I'm not sure that you've exhausted the limits of using YAML, _includes, and template logic. If you're at the point of putting Django style blocks into your content, why not just do something like this:

.Content

source, html


title: some title secondary_content: |

Here is some *secondary* content that will be [markdownified](http://example.com).
It can run to multiple lines and include
* Lists
* Good things
* Etc

And here is the main content, as per usual


.Template

source, html

<html> <article>

<h1>{{ page.title }}</h1>
{{ content }}

</article> <aside> {{ page.secondary_content | markdownify}} </aside>


If you wanted to keep your templates clean, and have different content for different types of pages, you could use various includes:

._includes/sidebar_negotiation.html

source, bash

{% if page.type = 'foo' %} {% include sidebar_foo.html %} {% else if page.type = 'bar' %} {% include sidebar_bar.html %} {% endif %}


And then put your page type specific stuff in those files. Obviously you could include it directly, but it is probably nice to abstract it out. Those includes will get all of the variables in the YAML.

If none of this is a win, you could always try Hyde: hyde.github.com/ which is written in Python, uses Jinja2 (basically Django templates++), and does the same sort of thing.

.comment


I just tested further, and found that although liquid-inheritance works fine on layouts, it fails when you get to actual content pages - which I think is where your problem arises (which. But as I said - once you get down to a specific piece of content, I'm still convinced that YAML is a better way to include ancillary content than putting blocks in your content area… – heliotrope Oct 31 '12 at 21:11


.comment


YAML is definitely the best way to do it, but it becomes unnecessarily complex if most of your content is simply large blocks of inseparable HTML. Aside from a title, there isn't a great deal of raw data that I really need to process. I just need to insert large chunks of HTML into specific, non-contiguous regions of the page. Describing that HTML in YAML is clumsy and unmaintainable. – xcession Nov 1 '12 at 10:08


// {% endraw %}