Dynamic and Extendable Page Headers in Liquid Projects

Page headers are common, sometimes the frontpage is different from the rest. Sometime indexes of posttypes have also their own unique style.

This is how I make it work in my recent Liquid projects.

So in the project structure I have the following structure:

theme/
├─ includes/
│  ├─ headers/
│  │  ├─ page_header.liquid
│  │  ├─ frontpage_header.liquid
│  ├─ header.liquid

In the header.liquid I include the page header. This is the default header for all pages.

This is then added to main theme.liquid file.

<main>
{% include 'includes/header' %}
{{ content }}
</main>

And then it looks like this:

The Purpose of indexHeaderTypes and detailHeaderTypes

These variables act as buckets that hold a list of content_type.name values. Later, the code checks if a post's content_type.name matches any value in these buckets.

{%- assign indexHeaderTypes = '' | split: ',' -%}
{%- assign detailHeaderTypes = '' | split: ',' -%}

{%- if post.is_index == true and indexHeaderTypes contains post.content_type.name -%}
{% include 'includes/headers/index_header' %}
{%- elsif post.is_index == false and post.content_type.name == "event" -%}
{%- include "includes/headers/event_header" -%}
{%- elsif post.is_index == false and detailHeaderTypes contains post.content_type.name -%}
{%- include "includes/headers/page_header" -%}
{%- elsif post.frontpage_header != blank -%}
{% include 'includes/headers/frontpage_header' %}
{%- elsif post.page_header != blank -%}
{% include 'includes/headers/page_header' %}
{%- elsif post.is_index == false and post.content_type.name == "job_posting" -%}
{% comment %}Only add this fallback job header if page_header is not set on job_posting itself...{% endcomment %}
{%- include "includes/headers/job_header" -%}
{%- elsif post.is_index == false and post.content_type.name == "team_member" -%}
{% comment %}Team member has it's own special page including a h1.{% endcomment %}
{% else %}
{%- comment -%}
For all pages where no explicit header is set, we use the default header. But only if the first section is not an header (kind of) section.
{%- endcomment -%}
{%- unless headerSectionTypes contains post.sections.first.content_type.name -%}
<header class="post-header">
<div class="post-header-content">
<div class="post-header-content-inner">
<h1 class="fallback-title">{{ post.title }}</h1>
</div>
</div>
</header>
{%- endunless -%}
{%- endif -%}

With this piece of code I make sure every option is easily 'extendable'.

p.s. I use https://ascii-tree-generator.com/ to create the directory structure. Neat!