Stop Repeating Your HTML: Mastering Dynamic Fragments in Thymeleaf
Stop duplicating HTML across your templates. Learn how to use Thymeleaf Fragments and dynamic expressions to create reusable UI components that simplify maintenance.
01 Jun 2026, 10:30 UTC

The Problem: The Copy-Paste Template Trap
When building a web application, you often find yourself copying the same navigation bar, footer, or alert box across ten different HTML files. The moment a design change is requested—like adding a new link to the header—you are forced to hunt through every single template to update the code. This manual repetition is a primary source of UI inconsistency and maintenance fatigue.
The solution is Thymeleaf Fragments. Instead of duplicating code, you define a UI component once and call it dynamically wherever it is needed. By using fragment expressions, you can transform static HTML blocks into reusable components that accept parameters, much like functions in a programming language.
Fragments vs. Inserts: Choosing Your Replacement Strategy
Thymeleaf provides two primary ways to include a fragment: th:replace and th:insert. Choosing the wrong one often leads to "mystery divs" that break your CSS grid or flexbox layouts.
- th:replace: This removes the host tag entirely and replaces it with the fragment's content. Use this when the host tag is merely a placeholder.
- th:insert: This keeps the host tag and places the fragment inside it. Use this when the host tag provides necessary styling or structural context that the fragment lacks.
Implementing a Parameterized Component
To make a fragment truly reusable, it should not rely on global model attributes. Instead, define it to accept parameters. This decouples the UI component from the specific controller logic of the page calling it.
Step 1: Define the Fragment
Create a dedicated file for shared components, such as src/main/resources/templates/fragments/common.html. Use the th:fragment attribute to name the block and define its expected arguments.
<!-- fragments/common.html -->
<div th:fragment="alert(message, type)"
th:class="alert alert-" + ${type}" role="alert"
>
<span th:text="${message}">Default Alert Message</span>
</div>
Step 2: Call the Fragment Dynamically
In your main page (e.g., index.html), call the fragment using the syntax ~{filename :: fragmentName(params)}. Run this within a Spring Boot application context to ensure the template resolver can locate the file.
<!-- index.html -->
<div th:replace="~{fragments/common :: alert('Your profile was updated!', 'success')}">
<div th:replace="~{fragments/common :: alert('Invalid password provided.', 'danger')}">
Diagnostic Check: Verifying the Output
Because Thymeleaf processes templates on the server, the browser only sees the final HTML. To verify your implementation, right-click the rendered page and select View Page Source.
- Success Case (th:replace): You should see
<div class="alert alert-success">...</div>. The placeholder<div th:replace...>should be completely gone. - Failure Case: If you see nested divs (e.g., a div inside a div both having alert classes), you likely used
th:insertwhen you intended to useth:replace.
Trade-offs and Performance Limits
While fragments are powerful, they introduce a layer of processing overhead. Every fragment expression requires the Thymeleaf engine to resolve a template path and parse a separate block of HTML.
Avoid Deep Nesting: Avoid creating fragments that call other fragments, which in turn call more fragments (e.g., Page → Layout → Sidebar → UserWidget → Avatar). Deeply nested fragments increase template processing time and make debugging rendering errors significantly harder, as the error stack trace may not clearly point to the original source file.
Coupling Risk: Resist the urge to pass complex business objects (like a full UserEntity) into a fragment. Instead, pass only the specific strings or booleans the fragment needs to render. This ensures your UI components remain agnostic of your database schema.
Actionable Summary
To clean up your templates, start by identifying the most repeated HTML block in your project. Move it to a fragments/common.html file, define it with th:fragment, and replace the duplicated code with th:replace. This shift reduces your maintenance surface area and ensures a consistent look and feel across your entire application.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.