Pug Mixins vs Includes – Decision Guide for Modular UI
Decide whether to use Pug mixins or includes for UI components by comparing dynamic and static use cases, trade‑offs, and a real example.
26 Aug 2026, 09:16 UTC

Problem Statement
When a Pug project grows, developers must decide how to split large templates into reusable pieces. Two built‑in mechanisms exist: include for static file composition and mixin for functional components. Choosing the wrong one can lead to fragile code, hard‑to‑debug logic, or unnecessary repetition.
Decision Guide
Below is a compact decision table that maps common requirements to the appropriate Pug feature.
| Requirement | Include | Mixin |
|---|---|---|
| Static content shared across pages (no data changes) | ✔️ | ✖️ |
| Reusable component that needs parameters | ✖️ | ✔️ |
| Conditional logic inside the component | ✖️ | ✔️ |
| Projection of arbitrary nested content (slot‑like behavior) | ✖️ | ✔️ |
| Minimal indentation overhead, simple copy‑paste | ✔️ | ✖️ |
Trade‑Offs
- Includes keep the template surface flat and avoid the complexity of function syntax. They are ideal for layout scaffolding like headers, footers, or a global navigation bar.
- Mixins act like functions: they accept arguments, can contain loops, conditionals, and expose a
blockfor content projection. This makes them powerful but increases the cognitive load when debugging. - Both approaches share the same indentation sensitivity. Mixing tabs and spaces across files can cause silent rendering failures.
- Mixins can be nested and can call other mixins, which is useful for building a component library but can quickly become hard to trace if overused.
Concrete Implementation Example
We’ll build a simple user card component. First, we’ll attempt it with an include and then refactor it into a mixin to illustrate the differences.
1. Static Include Approach (Limited)
File: components/user-card.pug
div.card
h2= name
p= role
Usage in pages/profile.pug:
var name = 'Alice'
var role = 'Admin'
include components/user-card.pug
var name = 'Bob'
var role = 'Editor'
include components/user-card.pug
While this works, it relies on global variables that must be overwritten before each include. In a list of dozens of users, this pattern is error‑prone and hard to maintain.
2. Dynamic Mixin Approach (Recommended)
Define a mixin with parameters and a block for optional content:
mixin userCard(name, role, avatarUrl = null)
div.card
if avatarUrl
img(src=avatarUrl, alt='Avatar')
h2= name
p= role
block // allows callers to inject extra markup
Call the mixin from pages/profile.pug:
+userCard('Alice', 'Admin', '/images/alice.png')
p.extra-info= 'Loves coffee'
+userCard('Bob', 'Editor')
p.extra-info= 'Enjoys hiking'
Key points:
- Parameters are passed explicitly, eliminating reliance on global state.
- The
blockkeyword lets callers project arbitrary nested content, similar to slots in Vue or React. - Conditional logic (e.g.,
if avatarUrl) is straightforward inside the mixin.
Verification Steps
- Run
pug pages/profile.pug -o distto render the HTML. - Open
dist/profile.htmland confirm that each card contains the correct name, role, and optional avatar image. - Inspect the rendered source to verify that the
p.extra-infoelements appear only where the mixin was called.
Running the same command with the include version will show that the second card reuses the global name and role variables unless they are manually overwritten, which is less reliable.
Limitations and Practical Checks
- Indentation Sensitivity: Pug treats tabs and spaces differently. Use a linter (e.g.,
pug-lint) to enforce consistent indentation. - Debugging Complexity: For very large mixins, consider extracting sub‑mixins or using partials to keep the logic readable.
- Performance: Mixins are resolved at compile time, so they do not incur runtime overhead. However, excessive nesting can increase the compiled template size.
Conclusion
Use includes for static, copy‑paste fragments that never need data injection. Opt for mixins when a component requires parameters, dynamic behavior, or content projection. Following this decision guide will keep your Pug templates clean, maintainable, and less error‑prone as your project scales.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.