Fluid Templates

To understand the following section you need basic knowledge about how to use the Fluid templating engine and TypoScript.

This chapter is based on the following steps:

After this tutorial you have created Fluid templates and split them into manageable pieces.

Implement template files

Based on the facts explained above, it should be easy to copy the static files from the Design Template into the appropriate folders of the site package directory structure.

The custom CSS file, as well as the custom JavaScript file, are files which will be maintained by a developer and never modified by TYPO3 at all. The same applies to the logo. However, TYPO3 may create a modified copy of the image, but should never manipulate the original image file (the "source"). Therefore, all three files can be classified as static and copied to the Public/ folder as follows.

  • site_package/Resources/Public/Css/website.css
  • site_package/Resources/Public/JavaScript/website.js
  • site_package/Resources/Public/Images/logo.png

As discussed before, the Bootstrap and jQuery files should be ignored for the time being. This leaves us with the index.html file, more precisely with the <body>-part of that file.

Due to the fact that this file needs to be rendered and enriched with dynamic content from the CMS, it can not be static and the content of this file will not be sent to the user directly. Therefore, this file should be stored somewhere inside the Resources/Private/ directory. The question about the exact sub-directory pops up though: is Resources/Private/Layouts/Page/ or Resources/Private/Templates/Page/ the perfect fit?

In our case, directory Resources/Private/Templates/Page/ is the correct folder, because this is the entry point for all page templates, despite the fact that our index.html file in fact implements the layout of the entire site. Therefore, the index.html file gets copied into Resources/Private/Templates/Page/ and renamed to Default.html (in order to visualize that this file represents the layout of a default page).

As a result, we end up with the following structure.

site_package
└── Resources
    ├── Private
    │   ├── Language
    │   ├── Layouts
    │   │   └── Page
    │   ├── Partials
    │   │   └── Page
    │   └── Templates
    │       └── Page
    │           └── Default.html
    └── Public
        ├── Css
        │   └── website.css
        ├── Images
        │   └── logo.png
        └── JavaScript
            └── website.js
Copied!

It is important to note that at this point in time the sitepackage extension contains four files only: Default.html, website.css, logo.png and website.js. The rest are empty directories for now.

The point is that TYPO3 follows the convention over configuration principle. This is a software design paradigm to decrease the number of decisions that a web developer is required to make. Simply learn and follow the conventions (e.g. that the path should be Resources/Private/Templates/Page/) and the development will be smooth, easy and straight forward. In addition, if another web developer (e.g. one of your colleagues) looks at your sitepackage extension, they know the locations and naming of files. This reduces development time significantly, e.g. if an issue needs to be investigated or a change should be implemented.

Furthermore, you might want to consider technologies such as Sass, SCSS and TypeScript for improved productivity and maintainability of your style sheets and JavaScript code. For the sake of simplicity, this tutorial uses the basic implementation of Cascading Style Sheets (CSS) and JavaScript files.

The page layout file

As described before, a typical static index.html file contains a <head> and a <body> section, but we only need to focus on the <body>. Open file site_package/Resources/Private/Templates/Page/Default.html in your favorite text editor and remove all lines before the starting <body> tag and after the closing </body> tag. Then, remove these two lines, too. As a result, your Default.html may now be empty. In that case, you can use the following example based on the Bootstrap Jumbotron. If using your own layout template, your Default.html now contains only the HTML code inside the body.

So, let's assume it contains something like the following HTML code:

EXT:site_package/Resources/Public/StaticTemplate/Step1Default.html
<nav class="navbar navbar-expand-md navbar-dark bg-dark fixed-top">
    <a class="navbar-brand" href="#">Navbar</a>
    <button aria-controls="navbarsExampleDefault"
            aria-expanded="false"
            aria-label="Toggle navigation"
            class="navbar-toggler"
            data-target="#navbarsExampleDefault"
            data-toggle="collapse"
            type="button"
    >
        <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarsExampleDefault">
        <ul class="navbar-nav mr-auto">
            <li class="nav-item active">
                <a class="nav-link" href="#">
                    Home
                </a>
            </li>
        </ul>
    </div>
</nav>

<main role="main">
    <div class="jumbotron">
        <div class="container">
            <h1 class="display-3">Hello, world!</h1>
            <p> ... </p>
        </div>
    </div>
    <div class="container">
        <div class="row">
            <div class="col-12 col-md-6">
                <h2>Main Content</h2>
                <p> ... </p>
            </div>
            <div class="col-12 col-md-4">
                <h2>Sidebar Content</h2>
                <p> ... </p>
            </div>
        </div>
    </div>
</main>
Copied!

In case you have worked with the Bootstrap library before, you will quickly realize that this is a simplified version of the well-known template called Bootstrap Jumbotron. The first section creates a mobile responsive navigation menu (<nav> ... </nav>) and the second section a container for the content (<main> ... </main>). Inside the content area we see a full-width section (<div class="jumbotron"> ... </div>) and a simple container with two columns.

The code above misses a few lines at the end, which include some JavaScript files such as jQuery and Bootstrap. You are advised to remove these line from the Resources/Private/Templates/Page/Default.html file, too.

Due to the fact that the "jumbotron" elements could be used on several pages (page layouts) across the entire website, we should move this part to a partial. Create a new file named Jumbotron.html inside directory site_package/Resources/Private/Partials/Page/ and copy the approriate six lines (starting from <div class="jumbotron">) into it. Make sure the file name reads exactly as stated above with upper case "J" as the first character.

Now, remove the lines from file Resources/Private/Templates/Page/Default.html and replace them with the following single line:

EXT:site_package/Resources/Private/Templates/Page/Default.html
<f:render partial="Jumbotron" />
Copied!

Congratulations -- you just applied your first ViewHelper! HTML tags starting with <f:...> are typically core ViewHelpers in Fluid. The tag <f:render> is the Render-ViewHelper, which (as the name suggests) renders the content of a section or partial. In our case it is the latter, because of the partial="..." argument. Note: do not append .html here. HTML is the default format and as a convention, the ViewHelper automatically knows the file name and its location: Partials/Page/Jumbotron.html.

Let us also move the navigation part into the file Partials/Page/Navigation/MainNavigation.html. As the navigation will contain dynamic parts we forward all variables as arguments:

EXT:site_package/Resources/Private/Partials/Page/Navigation/MainNavigation.html
<f:render partial="Navigation/MainNavigation.html" arguments="{_all}"/>
Copied!

The file Default.html should now look like this:

EXT:site_package/Resources/Public/StaticTemplate/Step2Default.html
<f:render partial="Navigation/MainNavigation.html" arguments="{_all}"/>

<main role="main">
    <f:render partial="Jumbotron" />
    <div class="container">
        <div class="row">
            <div class="col-12 col-md-6">
                <h2>Main Content</h2>
                <p> ... </p>
            </div>
            <div class="col-12 col-md-4">
                <h2>Sidebar Content</h2>
                <p> ... </p>
            </div>
        </div>
    </div>
</main>
Copied!

At this point, we have implemented an (optional) partial and a page layout template. Keep the file Resources/Private/Templates/Page/Default.html open in your text editor, because we need to make one more small adjustment.

As described above, files inside the Templates/ directory are page-specific layouts. An additional component allows web developers to build the overall layout (the skeleton) of the website: this is an HTML file in the Resources/Private/Layouts/Page/ folder that we name Default.html, too. Before we create this file, we need to tell our page layout template (Resources/Private/Templates/Page/Default.html) which website template it should use:

EXT:site_package/Resources/Public/StaticTemplate/Step3Default.html
<f:layout name="Default" />
<f:section name="Main">
    <f:render partial="Navigation/MainNavigation.html" arguments="{_all}"/>

    <main role="main">
        <f:render partial="Jumbotron" />
        <div class="container">
            <div class="row">
                <div class="col-12 col-md-6">
                    <h2>Main Content</h2>
                    <p> ... </p>
                </div>
                <div class="col-12 col-md-4">
                    <h2>Sidebar Content</h2>
                    <p> ... </p>
                </div>
            </div>
        </div>
    </main>
</f:section>
Copied!

The updated template file shows two additional lines at the top (<f:layout> and <f:section>) and an additional line at the bottom (the closing </f:section> tag). The Layout-ViewHelper refers to the "Default" website layout file, which we will create in the next step. The Section-ViewHelper simply wraps the page template code we created before and therefore defines a section named "Main".

The website layout file

Now, let's implement the website layout file. First, we create a new file Default.html inside the directory site_package/Resources/Private/Layouts/Page/ and add the following line:

EXT:site_package/Resources/Private/Layouts/Page/Default.html
<f:render section="Main" />
Copied!

Surprisingly, that is all. This line instructs Fluid to render the section "Main", which we have implemented in the page layout template file Resources/Private/Templates/Page/Default.html.

However, we will do an additional step. The navigation menu will be shown on all pages across the entire website. Therefore, it can be part of the global website layout. Therefore, file Resources/Private/Layouts/Page/Default.html is a suitable destination.

Move the <f:render partial="Navigation/MainNavigation.html" arguments="{_all}"/> part from file Resources/Private/Templates/Page/Default.html to Resources/Private/Layouts/Page/Default.html as shown here:

EXT:site_package/Resources/Private/Layouts/Page/Default.html
<f:render partial="Navigation/MainNavigation.html" arguments="{_all}"/>
<f:render section="Main" />
Copied!

Do not forget to remove the line from the Resources/Private/Templates/Page/Default.html file. If you do not remove them, the menu would appear twice in the frontend.

Next steps: Fetch the content and configure the menus