Offsetting Markdown Headers

I have been using Jekyll to create my course web site for the last 2 years and have gotten fairly familiar with its syntax, but this has me stumped.

I have a collection for the course, which includes markdown files for each week’s readings, homework, etc.

The content from this collection is used in two ways:

  1. As its own page (e.g., https://mycourse.com/course/week01) and
  2. Embedded in other pages via a liquid tag {{ week.content | markdownify }}

My issue is that these two instances require different heading levels.

I see that Kramdown has a header_offset option which I can set in my config.yml. Is there any way to use that option on a per page or per block basis, much like {::options parse_block_html="true" /}?

I have, of course, tried wrapping the content in ::options header_offset and providing 2 as a value, but that hasn’t made a difference.

Thanks for reading and any suggestions!

I’ve found what feels like a hacky solution and would still appreciate any other insights.

For the time being, I’m using the replace filter like so:

{{ week.content | markdownify | replace: '<h2', '<h4' | replace: '</h2>', '</h4>' }}

Obviously, this only becomes more hacky if my content includes additional headers :grimacing:

You can leave the replace approach and use CSS. Or change up your templating - separate your content data from your styling.

Data and styling approach

Using content twice is a common flow for jekyll blogs. The title of a post is stored as title in the frontmatter and the content comes below.

---
title: Post 1 title
---

Body of post.

Here is a small H2 heading when embedded.

## {{ page.title }}

Here is it a big heading as H1 on a standalone page.

# {{ page.title }}

On the Posts listing page you have a title and snippet of a post. The main title of the page is H1. And the title of each post embedded on the page is H2. See plain text below

My Blog

Post 1 title
  Intro

Post 2 title
  Intro

And then on a Post page the same title is used as H1.

Post 1 title

Body of post

This pattern works for other pages and collections etc.

I used markdown instead of HTML but you can use H tags instead of # if you want.

CSS approach

Less elegant solution but it is possible

You can have this on two pages where your H2 is the same but your CSS is different.

<style>
h2 {
  font-size: small;
}
</style>

<h2>{{ course.title }}</h2>

<style>
h2 {
  font-size: large;
}
</style>

<h2>{{ course.title }}</h2>

I would think an HTML semantically correct way is to change page layout a little if you haven’t like in collection archive page:

<h1>Site Name</h1>
<h2>Some Course</h2>
<div class="collection_archive>
  <article>
    <h1>Week 1</h1>
    <h2>Some Heading</h2>
  </article>
  <article>
    <h1>Week 2</h1>
    <h2>Some Heading</h2>
  </article>
  ...
</div>

And in single page:

<div class="collection_page>
  <article>
    <h1>Week 1</h1>
    <h2>Some Heading</h2>
  </article>
</div>

Then CSS.

Yes I agree with that. You have missing quotes BTW which is breaking the highlighting.

The HTML approach above is a more complete example but similar to my first answer on using Liquid variables in H1/# and H2/##. So you can use markdown or html as you need to for changing heading level and Liquid to insert values.

My desire to do this is definitely informed by wanting my output to be semantic HTML, not about the styling of the various header styles.

So, given that, the issue is that the content has Markdown in it that translates to h2s, e.g. ## My subheading. This markup is appropriate when the content appears as its own page, but is not correct when it’s embedded in other content. If the headings were part of the front matter, it would be easy to reconfigure via Liquid variables, but they’re within the content. @printf’s solution of using a wrapping article element may be the cleanest way to go. I just saw the header_offset setting and was hopeful it could be applied to individual pages or content (vs at the config.yml level).

You can see the content I’m talking about here: