Choosing Between Native Fragments and Layout Dialect in Thymeleaf
Thymeleaf offers two layout composition models: native fragments (th:fragment/th:replace) and the Layout Dialect (layout:decorate). This post compares both with a worked example, highlights caching and parameter pitfalls, and gives a decision checklist for your project.
01 Jun 2026, 09:32 UTC

The layout composition dilemma
Thymeleaf gives you two distinct ways to compose pages from reusable pieces: the native th:fragment/th:replace mechanism and the third-party Layout Dialect (layout:decorate). Both work, but they encourage different mental models. Pick the wrong one for your team's workflow and you'll fight the framework on every new page.
Natural templating: the designer handoff that actually works
Thymeleaf's killer feature is that a template file opens in a browser as valid HTML. Attributes like th:text and th:replace are ignored by the browser, so designers can style real markup without a running Spring Boot instance. No template conversion step, no placeholder syntax that breaks HTML validity.
Try it: save this as src/main/resources/templates/fragments/card.html and open it via file://.
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<div class="card" th:fragment="card(title, body)">
<h3 th:text="${title}">Card Title</h3>
<p th:text="${body}">Card body content</p>
</div>
</html>
The browser renders a styled card with placeholder text. Thymeleaf replaces the placeholders at runtime. This is the "natural templating" promise — and it holds up.
Native fragments: explicit composition
With native fragments you define a piece in one file and include it in another using th:replace (substitutes the host element) or th:insert (keeps the host, puts fragment inside). Parameters are passed positionally or by name.
<!-- page.html -->
<div th:replace="~{fragments/card :: card('Welcome', 'Hello world')}"></div>
Key distinction: th:replace removes the <div> host. If that host carries CSS classes or IDs needed for styling, use th:insert instead or move those attributes into the fragment root.
Fragment expressions (~{...}) unify inclusion, replacement, and layout extension. They support inline conditionals and can be passed as variables to other fragments, enabling component-like composition without Java component classes.
Layout Dialect: decorator-style inversion
The Layout Dialect (nz.net.ultraq.thymeleaf:layout-dialect) flips control. A base template declares slots with layout:fragment; pages extend the base and fill only their unique sections.
<!-- layout.html -->
<html layout:decorate="~{layout}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<body>
<section layout:fragment="content">
<p>Page-specific markup</p>
</section>
</body>
</html>
This reduces boilerplate in large apps — pages don't repeat header/footer includes. But it adds a third-party dependency and a different mental model. Mixing native fragments and Layout Dialect in the same codebase creates inconsistency.
Worked example: same page, two approaches
Assume a Spring Boot 3 project with spring-boot-starter-thymeleaf and thymeleaf-layout-dialect on the classpath. Build a page with header, main content, and footer.
Approach A: Native fragments
<!-- fragments/header.html -->
<header th:fragment="header"><nav>...</nav></header>
<!-- fragments/footer.html -->
<footer th:fragment="footer">© 2026</footer>
<!-- page-native.html -->
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org">
<body>
<div th:replace="~{fragments/header :: header}"></div>
<main>Page content</main>
<div th:replace="~{fragments/footer :: footer}"></div>
</body>
</html>
Approach B: Layout Dialect
<!-- layout.html -->
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<body>
<header><nav>...</nav></header>
<section layout:fragment="content"></section>
<footer>© 2026</footer>
</body>
</html>
<!-- page-layout.html -->
<html layout:decorate="~{layout}">
<body>
<section layout:fragment="content">Page content</section>
</body>
</html>
Count templates: native uses 3 files (header, footer, page), Layout Dialect uses 2 (layout, page). Lines of code are similar, but Layout Dialect eliminates the explicit include calls on every page.
Trade-offs and limitations
- Caching:
spring.thymeleaf.cache=true(default in production) caches parsed fragments. Changes require restart or cache invalidation. In development, setspring.thymeleaf.cache=falsewithspring.devtools.restart.enabled=truefor hot reload. - Parameter safety: Fragment parameters are untyped. Misspelled names fail silently at render time, producing empty output. Guard with
#strings.isEmpty()or default expressions. - Granularity: Dozens of tiny fragment files hurt readability and increase template resolution overhead. Favor coarse fragments aligned with UI components (card, modal, table row).
- Template mode: Default HTML5 mode is lenient. Switching to XML (
spring.thymeleaf.mode=XML) requires well-formed markup — self-closing tags, quoted attributes, no void elements like<br>without/>. - Security integration: Spring Boot 3.x requires
thymeleaf-extras-springsecurity6. Usesec:authorize="hasRole('ADMIN')"on fragments for conditional rendering without controller changes.
Decision checklist
| Scenario | Prefer |
|---|---|
| Small app, few shared pieces, designers need standalone HTML prototypes | Native fragments |
| Large app, consistent layout across 20+ pages, team comfortable with decorator pattern | Layout Dialect |
| Mixed team: designers edit HTML, developers add logic | Native fragments (more explicit, easier to debug) |
| Existing codebase already uses one approach | Stay consistent — avoid mixing |
Verify your choice
- Create a Spring Boot 3 project with both dependencies.
- Build two identical pages using each approach.
- Enable DEBUG logging for
org.thymeleafand compare template resolution counts. - Open each template via
file://— confirm they render as styled HTML without a server. - Toggle
spring.thymeleaf.cacheand verify hot reload behavior with DevTools.
Start with native fragments. They're built-in, explicit, and preserve natural templating for designers. Adopt Layout Dialect only when boilerplate reduction outweighs the added dependency and mental-model shift.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.