What You'll Learn

Most web sites will have some form of consistency in their structure - often realised as a header and footer. In this tutorial, we will introduce that structure.

It is good practice to make it obvious what files reside in which folders.
Create a folder called fragments under /main/resources/templates.

In the fragments folder, create a file called header.html and enter this content.

In header.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <link crossorigin="anonymous" href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css"
          integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC"
          rel="stylesheet" th:fragment="bootstrap-css">
</head>
<body>

<nav class="navbar navbar-expand-lg navbar-light bg-light" th:fragment="header">
    <div class="container">
        <a class="navbar-brand" href="/">
            <span><img alt="Charity Giving Logo" src="/images/cg-logo.jpg"/>
            </span>
        </a>
    </div>
</nav>
</body>
</html>

Note that this is a full HTML page and that the head tag contains elements to include Bootstrap. There is then a nav tag within the body tag.

Pay specific attention to the th:fragment attributes.
These identify the elements that should be treated as fragments.
There are two in the header.

Do the same for a footer with this content.

In footer.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
</head>
<body>
<div>
    <script crossorigin="anonymous" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM"
            src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"
            th:fragment="bootstrap-js"></script>
</div>
</body>
</html>

Note that this contains the script tag to include the Bootstrap JavaScript and that that element has the th:fragment attribute on it.

We can now amend the index.html page to include the fragments.

In index.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Welcome to Charity Giving</title>
    <link th:replace="fragments/header :: bootstrap-css"></link>

</head>
<body>
<div class="container">
    <div th:replace="fragments/header :: header"/>

    <div>
        <span>Welcome to Charity Giving.  Today is </span><span th:text="${today}"></span>
    </div>
    <div>
        <a href="charities">View our charities</a>
    </div>
</div>
<div th:replace="fragments/footer :: bootstrap-js"></div>
</body>
</html>

In the head element, we have this:

<link th:replace="fragments/header :: bootstrap-css"></link>

The th:replace attribute tells Thymeleaf to replace this link element with what it finds in fragment called "bootstrap-css" within the fragments file (located at fragments/header) - there is no need for the ‘.html' suffix.

This is repeated for the footer as well.

This is the simplest way of using Thymeleaf fragments. There is another method that can produce a neater design but requires more work. There are also additional Thymeleaf attributes for other scenarios.