Jekyll Includes vs Layouts: What's the Difference and When to Use Each
Confused about when to use Jekyll includes vs layouts? This guide explains both clearly, shows how they work together, and gives practical patterns for clean template architecture.
Jekyll has two ways to reuse HTML across your site: layouts and includes. Both reduce repetition, but they work differently and serve different purposes. Understanding when to reach for each one is key to building a clean, maintainable Jekyll site.
The short version
- Layouts wrap content — they are the outer shell (nav, header, footer,
<html>) - Includes are embedded fragments — reusable chunks pulled into a template at a specific point
A layout is used once per page and applied from the outside. An include is embedded from the inside, anywhere you need it, as many times as you like.
Layouts in detail
Layouts live in _layouts/ and are applied via front matter:
---
layout: post
---
A layout wraps a page’s content using the {{ content }} variable:
<!-- _layouts/post.html -->
---
layout: default
---
<article class="post">
<h1>{{ page.title }}</h1>
{{ content }} ← the post's Markdown renders here
</article>
Key characteristics of layouts:
- Applied by the page/post via front matter — the content does not choose what goes around it, the layout does
- Can inherit from other layouts (layout stacking)
- Only one layout per page
- Contain major structural sections
Includes in detail
Includes live in _includes/ and are pulled into any template using the include tag:
{% include nav.html %}
{% include footer.html %}
{% include components/card.html %}
A layout file using includes:
<!-- _layouts/default.html -->
<!DOCTYPE html>
<html lang="en">
<head>
{% include head.html %}
</head>
<body>
{% include nav.html %}
{{ content }}
{% include footer.html %}
</body>
</html>
Key characteristics of includes:
- Pulled in using
{% include %}from anywhere — layouts, other includes, page content - Can be used multiple times on one page
- Can receive parameters (variables)
- Contain specific UI components or repeating fragments
A concrete example
Imagine a post page with the following sections:
┌─────────────────────────────────────┐
│ <head> meta, CSS, title │ ← head.html (include)
│─────────────────────────────────────│
│ Navigation bar │ ← nav.html (include)
│─────────────────────────────────────│
│ Article header (title, date) │ ┐
│ Article body content │ │ post.html (layout)
│ Author bio │ │ using includes:
│ Related posts │ │ - author-bio.html
│─────────────────────────────────────│ │ - related-posts.html
│ Footer │ ┘
└─────────────────────────────────────┘ ← footer.html (include)
The layout (post.html, inheriting from default.html) provides the outer structure. The includes are the discrete components within that structure.
Passing variables to includes
Includes accept parameters, making them more flexible than layouts:
{% include components/card.html
title=theme.title
url=theme.url
image=theme.card_image
price=theme.price %}
Inside _includes/components/card.html, the variables are accessed via include.variable_name:
<!-- _includes/components/card.html -->
<div class="card">
{% if include.image %}
<img src="{{ include.image | relative_url }}" alt="{{ include.title }}">
{% endif %}
<h3><a href="{{ include.url }}">{{ include.title }}</a></h3>
{% if include.price == 0 %}
<span class="badge">Free</span>
{% else %}
<span class="price">${{ include.price }}</span>
{% endif %}
</div>
Layouts cannot receive parameters this way — they work with the page’s front matter variables.
When to use a layout
Use a layout when you need to wrap an entire page in a consistent outer structure. Layouts answer the question: “What shell does this type of page use?”
Good candidates for layouts:
default.html— the base HTML shell for all pagespost.html— article structure for blog postspage.html— standard content page structuretheme.html— theme detail page with gallery and sidebarhome.html— homepage with hero and special sections
Rule of thumb: if every page of that type shares the same outer structure, it is a layout.
When to use an include
Use an include for any reusable fragment that appears in multiple templates, or any component complex enough to extract for readability.
Good candidates for includes:
nav.html— navigation bar (used in every layout)footer.html— footer (used in every layout)head.html—<head>contents (meta, CSS, SEO tags)analytics.html— analytics scriptscomponents/card.html— a theme card used in gridsauthor-bio.html— author bio block used in postsrelated-posts.html— related posts sectionnewsletter-form.html— newsletter signup form
Rule of thumb: if you paste the same HTML in more than one place, extract it to an include.
Using includes inside page content
Includes can be used inside Markdown content, not just in layout files. This is useful for embedding repeating components mid-article:
Here is a callout box:
{% include callout.html type="warning" text="This changed in Jekyll 4.0." %}
And here is a code block:
The callout.html include renders inline wherever the tag appears.
Organising your _includes folder
For anything beyond a simple site, organise includes into subdirectories:
_includes/
├── head.html
├── nav.html
├── footer.html
├── analytics.html
├── components/
│ ├── card.html
│ ├── badge.html
│ └── breadcrumb.html
├── sections/
│ ├── home-hero.html
│ ├── home-newsletter.html
│ └── home-featured.html
└── partials/
├── author-bio.html
├── related-posts.html
└── share-buttons.html
Reference subdirectory includes with the path:
{% include components/card.html title=theme.title %}
{% include sections/home-hero.html %}
Include variables and scope
Variables defined inside an include are local to that include — they do not leak into the parent template. Variables from the parent are accessible in the include via page, site, and layout:
<!-- _includes/author-bio.html -->
{% assign author = site.authors | where: "name", page.author | first %}
{% if author %}
<div class="author-bio">
<img src="{{ author.avatar }}" alt="{{ author.name }}">
<p>{{ author.bio }}</p>
</div>
{% endif %}
The page.author variable comes from the post’s front matter. The include accesses it as part of the normal Liquid scope.
Performance: cacheify repeated includes
If an include is used many times on one page (such as a card component inside a loop), Jekyll processes it once per call. For complex includes in large loops, simplify the include or pre-compute values with Liquid assign outside the loop.
{% comment %} Pre-assign outside the loop {% endcomment %}
{% assign sorted_themes = site.themes | sort: "stars" | reverse %}
{% for theme in sorted_themes %}
{% include components/card.html theme=theme %}
{% endfor %}
The difference in one sentence
A layout is the house; an include is a piece of furniture. The layout determines the structure and surrounds the content; includes are discrete components placed within that structure.
Most Jekyll sites need both: a small set of layouts (3–5) and a larger set of includes (10–20+). Knowing which to use in each situation is what keeps your templates readable and easy to maintain as your site grows.
When to use includes: practical patterns
Includes shine whenever you have a block of HTML that appears in more than one place, or when you want to isolate a complex template fragment into its own file for clarity. The patterns that benefit most from includes are navigation bars (which appear in every layout but may have multiple states), post cards (which appear on index pages, related post sections, and search results), social sharing buttons (which appear on every post), and schema markup templates (which are structurally complex but should be consistent across all posts of the same type).
An underused feature of includes is parameter passing with include_relative and the include tag’s with syntax. By passing variables to includes, you make them truly reusable — the same _includes/card.html can render a post card, a theme card, or a product card by accepting different data through parameters. This eliminates the need for multiple nearly-identical include files and keeps your template directory manageable as the site’s complexity grows.
When an include becomes longer than fifty lines, consider whether it should be a layout variant instead. A very complex author bio include that has its own sub-sections may indicate that “author pages” deserve their own layout rather than an include in the existing post layout. The boundary between layouts and includes is not rigid; the goal is always clarity and reusability, and sometimes that means rethinking the structural choice as the site evolves.
When to use layouts: building clear hierarchies
Layouts are most valuable when you have fundamentally different page structures — a homepage that is nothing like a blog post, a blog post that differs significantly from a documentation page, a landing page with a full-width hero section that no other page type uses. Each distinct page structure is a candidate for its own layout; each structural variation within a page type is a candidate for front matter configuration rather than a new layout.
The layout hierarchy should be readable as a description of your site architecture. A site with default → post and default → page layouts is clearly structured: one base template, two content types. A site with default → post → featured-post → featured-post-with-sidebar has grown in a disorganised direction — those variants should probably be handled by conditionals and includes within a single post layout, not by a four-level inheritance chain.
Keep layout files focused on structure, not content. A layout file should contain the page skeleton, the includes for navigation and footer, the content injection point, and conditional logic for structural variations. It should not contain hard-coded copy, specific class names for non-structural elements, or large blocks of HTML that would be clearer in an include. The twenty lines that define a page’s structure and fifty lines that implement a reusable component are better separated into a layout and an include respectively, even when they currently only appear together.
Refactoring towards cleaner templates
Most Jekyll sites start with a few template files and accumulate complexity over time. A post layout that began with fifty lines grows to two hundred as new features are added. A navigation include starts simple and ends up with seven conditional branches covering different user states and page types. Periodically stepping back and refactoring templates — extracting overgrown includes into sub-includes, simplifying inheritance chains, moving hard-coded values to configuration — keeps the codebase maintainable.
The practical approach to refactoring: when you open a template file to make a change and find yourself spending more time understanding the existing code than making your change, the file is ready to refactor. This is the point of maximum value for reorganisation — you understand the current structure well enough to improve it, and the pain of the complexity is fresh. Set aside an extra hour for the refactor while the context is in your head.
Version control is your safety net during template refactoring. Commit the current state before refactoring, work on the refactor as a single focused change, test thoroughly, and commit the result. If the refactor introduces bugs, you have a clean rollback point. This disciplined approach removes the risk from template maintenance and makes it something you can do incrementally rather than saving up for a big, scary rewrite.
Templates that are clear, well-structured, and appropriately separated into layouts and includes are templates that you can modify confidently and hand off to collaborators without extensive explanation. That clarity is worth investing in, and the layouts-vs-includes distinction is the primary structural decision that creates it.
When the boundary blurs: layout-level includes
The includes-vs-layouts distinction is clearest in simple sites and becomes genuinely blurry in complex ones. A site with five different page types — post, page, documentation, landing, author — may have a default.html layout, five type-specific layouts that extend it, and dozens of includes shared across various subsets of those layouts. At that scale, the boundary between “this should be a layout” and “this should be an include” requires judgement rather than a simple rule.
The useful heuristic: if a block of template code represents the full structural wrapper for a page type, it belongs in a layout. If it represents a component that appears within pages (potentially in multiple different layouts), it belongs in an include. Navigation belongs in an include because it appears in many layouts. The two-column article grid belongs in the post layout because it is the defining structure of the post page type.
When a layout grows large enough that it becomes hard to read in one screen — more than 80-100 lines — look for sections that could be extracted into named includes. A post layout that contains navigation HTML, article header HTML, sidebar HTML, and footer HTML inline is doing too much. Extract each of those sections into a well-named include and reference them from the layout. The layout becomes a readable outline of the page structure; the includes contain the implementation details.