Control Flow

How each templating language expresses conditionals and loops, ranging from deliberately logic-less to fully expressive.

Pug

Pug supports if/else and each/while as native block-level keywords that follow its indentation rules, compiling down to plain conditional and looping constructs. Because it compiles to JavaScript functions, arbitrary JavaScript expressions can also be used within these constructs.

Mustache

Mustache is deliberately logic-less: it has no if or for keywords, only “sections” ({{#name}}...{{/name}}) that render their block once per truthy value or once per item in an array, and inverted sections ({{^name}}...{{/name}}) for falsy/empty cases. Any real branching or iteration logic must be prepared in the view model before rendering.

Handlebars

Handlebars extends Mustache’s section syntax with explicit built-in helpers {{#if condition}}...{{/if}} and {{#each list}}...{{/each}}, and allows custom helpers to implement further logic. This makes it noticeably less “logic-less” than plain Mustache while keeping the same block-tag style.

Blade

Blade provides directive-based control structures like @if/@elseif/@else/@endif and @foreach/@endforeach, which compile to native PHP control flow. Because Blade compiles to PHP, these directives support the full range of PHP conditions and iterables.

ERB

ERB has no dedicated control-flow syntax of its own; conditionals and loops are just Ruby code written inside <% %> tags, such as <% if condition %> and <% items.each do |item| %>. This gives templates the complete expressive power of the host Ruby language.

Django Templates

Django Templates provide {% if %}/{% elif %}/{% else %}/{% endif %} and {% for %}/{% endfor %} tags, deliberately limited to simple boolean and iteration logic without arbitrary expression evaluation. This constraint is intentional, keeping business logic out of templates.

Jinja2

Jinja2 offers {% if %}/{% elif %}/{% else %} and {% for %}/{% endfor %} tags with a substantially richer expression language than Django’s, including inline conditional expressions, loop variables like loop.index, and filtering within for loops. This makes it more programmable while retaining Django-like tag syntax.

EJS

EJS control flow is plain JavaScript inside <% %> scriptlet tags, so if/else blocks and for/forEach loops are written exactly as they would be in any JavaScript function body. There is no separate templating-specific control-flow syntax to learn.

Twig

Twig supports {% if %}/{% elseif %}/{% else %}/{% endif %} and {% for %}/{% endfor %} tags, along with conveniences like an else clause on empty loops, closely mirroring Jinja2’s control-flow design adapted for PHP.

Thymeleaf

Thymeleaf expresses conditionals and loops as attributes on HTML elements, using th:if/th:unless to conditionally render an element and th:each to repeat an element once per item in a collection. This keeps control flow attached to the markup structure rather than embedded in text.

Edge.js

Edge provides @if/@elseif/@else/@end tags for conditionals and an @each(item in collection)...@end tag for iterating over collections, both compiled to plain JavaScript under the hood. The syntax reads as template tags layered directly over standard HTML.