Skip to navigation Skip to main content
Eleventy
Eleventy Documentation
Stable
3.0.0
Toggle Menu
Eleventy 1.93s
Gatsby 29.05s

Liquid

Contents

Eleventy Short Name File Extension npm Package
liquid .liquid liquidjs

You can override a .liquid file’s template engine. Read more at Changing a Template’s Rendering Engine.

Liquid Options

Default Options

Rather than constantly fixing outdated documentation, find getLiquidOptions in Liquid.js. These options are different than the default liquidjs options.

JavaScript Truthiness in Liquid

Surprising to JavaScript developers—in LiquidJS both "" and 0 are truthy values! If you’d like to switch to use more JS-familiar conventions, use the Liquid option jsTruthy: true in your Eleventy config:

eleventy.config.js
export default function (eleventyConfig) {
eleventyConfig.setLiquidOptions({
jsTruthy: true,
});
};
module.exports = function (eleventyConfig) {
eleventyConfig.setLiquidOptions({
jsTruthy: true,
});
};

Use your own options

It’s recommended to use the Configuration API to override the default options above.

eleventy.config.js
export default function (eleventyConfig) {
eleventyConfig.setLiquidOptions({
dynamicPartials: false,
strictFilters: false, // renamed from `strict_filters` in Eleventy 1.0
});
};
module.exports = function (eleventyConfig) {
eleventyConfig.setLiquidOptions({
dynamicPartials: false,
strictFilters: false, // renamed from `strict_filters` in Eleventy 1.0
});
};

Optional: Set your own Library instance

As an escape mechanism for advanced usage, pass in your own instance of the Liquid library using the Configuration API. See all liquidjs options.

WARNING:
Not compatible with setLiquidOptions above—this method will override any configuration set there.
eleventy.config.js
import { Liquid } from "liquidjs";

export default function (eleventyConfig) {
let options = {
extname: ".liquid",
dynamicPartials: false,
strictFilters: false, // renamed from `strict_filters` in Eleventy 1.0
root: ["_includes"],
};

eleventyConfig.setLibrary("liquid", new Liquid(options));
};
const { Liquid } = require("liquidjs");

module.exports = function (eleventyConfig) {
let options = {
extname: ".liquid",
dynamicPartials: false,
strictFilters: false, // renamed from `strict_filters` in Eleventy 1.0
root: ["_includes"],
};

eleventyConfig.setLibrary("liquid", new Liquid(options));
};

Supported Features

Feature Syntax
✅ Include {% include user %} looks for _includes/user.liquid. Does not process front matter in the include file.
✅ Includes (Relative Path) Relative paths use ./ (template’s directory) or ../ (template’s parent directory): {% include ./included %} looks for included.liquid in the template’s current directory. Does not process front matter.

WARNING:
If _includes/included.liquid also exists, Liquid will use this file instead.
✅ Include (Quoted)
INFO:
Starting in Eleventy 1.0, Liquid includes without quotation marks require dynamicPartials: false—Read more at Quoted Include Paths.
{% include 'user' %} looks for _includes/user.liquid. Does not process front matter in the include file.
✅ Include (Relative Path, Quoted)
INFO:
Starting in Eleventy 1.0, Liquid includes without quotation marks require dynamicPartials: false—Read more at Quoted Include Paths.
Relative paths use ./ (template’s directory) or ../ (template’s parent directory): {% include './dir/user' %} looks for ./dir/user.liquid from the template’s current directory. Does not process front matter in the include file.

WARNING:
If _includes/dir/user.liquid also exists, Liquid will use this file instead.
✅ Include (pass in Data) {% include 'user' with 'Ava' %}. Does not process front matter in the include file.
✅ Include (pass in Data) {% include 'user', user1: 'Ava', user2: 'Bill' %}. Does not process front matter in the include file.
✅ Custom Filters {{ name | upper }} Read more about Filters
Universal Filters {% name | filterName %} Read more about Filters
Custom Tags {% uppercase name %} Read more about Custom Tags.
Shortcodes {% uppercase name %} Read more about Shortcodes.

Quoted Include Paths

WARNING:
This is a common pitfall if you’re using Liquid templates.

If you’d like to use include paths without quotation marks, you must enable dynamicPartials: false in your Liquid options. The default in Eleventy 1.0 (and liquidjs) swapped from false to true. Read more about this limitation at Issue #72.

Default behavior, dynamicPartials: true

{% include 'user' %} looks for _includes/user.liquid

Non-quoted includes with dynamicPartials: false

{% include user %} looks for _includes/user.liquid

Filters

Filters are used to transform or modify content. You can add Liquid specific filters, but you probably want to add a Universal filter instead.

Read more about LiquidJS Filter syntax

Note that Liquid supports asynchronous filters out of the box (without any additional code or API method changes).

eleventy.config.js
export default function(eleventyConfig) {
// Liquid Filter
eleventyConfig.addLiquidFilter("myLiquidFilter", function(myVariable) { /* … */ });

// Async-friendly too
eleventyConfig.addLiquidFilter("myAsyncLiquidFilter", async function(myVariable) { /* … */ });

// Universal filters (Adds to Liquid, Nunjucks, 11ty.js)
eleventyConfig.addFilter("myFilter", function(myVariable) { /* … */ });
};
module.exports = function(eleventyConfig) {
// Liquid Filter
eleventyConfig.addLiquidFilter("myLiquidFilter", function(myVariable) { /* … */ });

// Async-friendly too
eleventyConfig.addLiquidFilter("myAsyncLiquidFilter", async function(myVariable) { /* … */ });

// Universal filters (Adds to Liquid, Nunjucks, 11ty.js)
eleventyConfig.addFilter("myFilter", function(myVariable) { /* … */ });
};

Usage

<h1>{{ myVariable | myFilter }}</h1>

Multiple Filter Arguments

eleventy.config.js
export default function (eleventyConfig) {
// Liquid Filter
eleventyConfig.addLiquidFilter(
"concatThreeStrings",
function (arg1, arg2, arg3) {
return arg1 + arg2 + arg3;
}
);
};
module.exports = function (eleventyConfig) {
// Liquid Filter
eleventyConfig.addLiquidFilter(
"concatThreeStrings",
function (arg1, arg2, arg3) {
return arg1 + arg2 + arg3;
}
);
};
<h1>{{ "first" | concatThreeThings: "second", "third" }}</h1>

Shortcodes

Shortcodes are basically reusable bits of content. You can add Liquid specific shortcodes, but you probably want to add a Universal shortcode instead.

Shortcode

eleventy.config.js
export default function(eleventyConfig) {
// Liquid Shortcode
// These can be async functions too
eleventyConfig.addLiquidShortcode("user", function(name, twitterUsername) { /* … */ });

// Universal Shortcodes (Adds to Liquid, Nunjucks, 11ty.js)
eleventyConfig.addShortcode("user", function(name, twitterUsername) {
return `<div class="user">
<div class="user_name">
${name}</div>
<div class="user_twitter">@
${twitterUsername}</div>
</div>
`
;
});
};
module.exports = function(eleventyConfig) {
// Liquid Shortcode
// These can be async functions too
eleventyConfig.addLiquidShortcode("user", function(name, twitterUsername) { /* … */ });

// Universal Shortcodes (Adds to Liquid, Nunjucks, 11ty.js)
eleventyConfig.addShortcode("user", function(name, twitterUsername) {
return `<div class="user">
<div class="user_name">
${name}</div>
<div class="user_twitter">@
${twitterUsername}</div>
</div>
`
;
});
};

liquidjs is already Promise-based internally, so an async function for a shortcode function works out of the box here.

Usage

{% user "Zach Leatherman", "zachleat" %}

<!-- The comma between arguments is optional in Liquid templates -->
{% user "Zach Leatherman" "zachleat" %}
Outputs
<div class="user">
<div class="user_name">Zach Leatherman</div>
<div class="user_twitter">@zachleat</div>
</div>

Paired Shortcode

eleventy.config.js
export default function(eleventyConfig) {
// Liquid Shortcode
// These can be async functions too
eleventyConfig.addPairedLiquidShortcode("user2", function(bioContent, name, twitterUsername) { /* … */ });

// Universal Shortcodes (Adds to Liquid, Nunjucks, 11ty.js)
eleventyConfig.addPairedShortcode("user2", function(bioContent, name, twitterUsername) {
return `<div class="user">
<div class="user_name">
${name}</div>
<div class="user_twitter">@
${twitterUsername}</div>
<div class="user_bio">
${bioContent}</div>
</div>
`
;
});
};
module.exports = function(eleventyConfig) {
// Liquid Shortcode
// These can be async functions too
eleventyConfig.addPairedLiquidShortcode("user2", function(bioContent, name, twitterUsername) { /* … */ });

// Universal Shortcodes (Adds to Liquid, Nunjucks, 11ty.js)
eleventyConfig.addPairedShortcode("user2", function(bioContent, name, twitterUsername) {
return `<div class="user">
<div class="user_name">
${name}</div>
<div class="user_twitter">@
${twitterUsername}</div>
<div class="user_bio">
${bioContent}</div>
</div>
`
;
});
};

liquidjs is already Promise-based internally, so an async function for a shortcode function works out of the box here.

Usage

Note that you can put any Liquid tags or content inside the {% user %} shortcode! Yes, even other shortcodes!

{% user2 "Zach Leatherman" "zachleat" %} Zach likes to take long walks on
Nebraska beaches. {% enduser2 %}
Outputs
<div class="user">
<div class="user_name">Zach Leatherman</div>
<div class="user_twitter">@zachleat</div>
<div class="user_bio">Zach likes to take long walks on Nebraska beaches.</div>
</div>

Asynchronous Shortcodes

Liquid is already promise-based internally so async functions with await work fine out of the box.

eleventy.config.js
export default function (eleventyConfig) {
eleventyConfig.addLiquidShortcode(
"user",
async function (name, twitterUsername) {
return await fetchAThing();
}
);

eleventyConfig.addPairedShortcode(
"user2",
async function (content, name, twitterUsername) {
return await fetchAThing();
}
);
};
module.exports = function (eleventyConfig) {
eleventyConfig.addLiquidShortcode(
"user",
async function (name, twitterUsername) {
return await fetchAThing();
}
);

eleventyConfig.addPairedShortcode(
"user2",
async function (content, name, twitterUsername) {
return await fetchAThing();
}
);
};

Usage

(It’s the same.)

{% user "Zach Leatherman" "zachleat" %} {% user2 "Zach Leatherman" "zachleat" %}
Zach likes to take long walks on Nebraska beaches. {% enduser2 %}

Shortcode Parameter Parsing

Eleventy’s includes its own parameter parsing implementation for shortcodes. To swap to a more robust, Liquid-native solution, use the setLiquidParameterParsing Configuration API method. This will likely be enabled by default in a future major version of Eleventy. Related GitHub #2679.

eleventy.config.js
export default function (eleventyConfig) {
// Current default:
// eleventyConfig.setLiquidParameterParsing("legacy");

// Liquid-native
eleventyConfig.setLiquidParameterParsing("builtin");
};
module.exports = function (eleventyConfig) {
// Current default:
// eleventyConfig.setLiquidParameterParsing("legacy");

// Liquid-native
eleventyConfig.setLiquidParameterParsing("builtin");
};

Access to page data values

If you aren’t using an arrow function, Liquid Shortcodes (and Nunjucks and 11ty.js JavaScript Functions) will have access to Eleventy page data values without needing to pass them in as arguments.

eleventy.config.js
export default function (eleventyConfig) {
eleventyConfig.addLiquidShortcode("myShortcode", function () {
// Available in 0.11.0 and above
console.log(this.page);

// For example:
console.log(this.page.url);
console.log(this.page.inputPath);
console.log(this.page.fileSlug);
});
};
module.exports = function (eleventyConfig) {
eleventyConfig.addLiquidShortcode("myShortcode", function () {
// Available in 0.11.0 and above
console.log(this.page);

// For example:
console.log(this.page.url);
console.log(this.page.inputPath);
console.log(this.page.fileSlug);
});
};

Other pages in Template Languages: