Skip to main content

FLUID Templating

FLUID templates in TYPO3 follow all standard HTML conventions ✅, with some additional FLUID-specific rules to ensure maintainability, readability, and consistency. Below is a guide for writing FLUID templates:


🌟 General Rules

0️⃣ Base Rule

  • Embrace HTML Conventions: This FLUID Templating Guideline inherits all the rules and conventions from the HTML coding guidelines available here 🎉

1️⃣ Opening and Closing Tags

  • Every template must have an opening <html> tag with the FLUID namespace definition and a closing </html> tag.
  • Exceptions: Google Tag Manager scripts, Google Analytics, or similar cases where only a third party<script> tag is injected into the HTML.
<html data-namespace-typo3-fluid="true" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">

<!-- Template content here -->

</html>

2️⃣ Attribute Order and Namespace Definitions

  • In the first line, the following attribute order must be followed:

    1. data-namespace-typo3-fluid="true"
    2. Global namespace definition xmlns:f
    3. Further namespace definitions used, e.g. xmlns:fh, xmlns:custom, etc.
  • If multiple namespaces are defined, they must be placed on new lines for better readability and ease of editing (e.g., using PhpStorm shortcut: Option + Shift + Up/Down Arrow).

<html
data-namespace-typo3-fluid="true"
xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
xmlns:dist="http://typo3.org/ns/FULLHAUS/DistributionPackage/ViewHelpers"
>

<!-- Template content here -->

</html>

3️⃣ Attribute Placement in Tags

  • If a tag contains three or more attributes, place each attribute on a new line for better readability and ease of editing.
  • You're free to apply multi-line style in case an attribute value is exceeding regular length.
<img
alt="Company Logo"
class="c-main-footer__logo me-4"
src="{f:uri.image(src: site.settings.all.company.logo, width: '150m')}"
/>

4️⃣ Empty Lines for Structure

  • Ensure there is always an empty line:
    1. After the opening <html> tag (first line).
    2. Before the closing </html> tag (last line).
    3. Where it makes sense to separate code blocks(sections, divs) from each other.

5️⃣ Use of Self-Closing Tags

  • ViewHelper self-closing syntax is preferred whenever possible (e.g <f:variable />).
<!-- Do -->
<f:variable name="name" value="value" />
<!-- Don't -->
<f:variable name="name">value</variable>

6️⃣ Whitespaces

  • Like PHP array notation, add white-spaces after opening/before closing brackets. If the list is long, use multi-line notation when needed.
<!-- Do -->
<f:render partial="Example" arguments="{ key: 'value' }" />
<!-- multiline -->
<f:render
partial="Example"
arguments="{
key: 'value',
key1: 'value1',
key2: 'value2',
key3: 'value3'
}"
/>

<!-- Don't -->
<f:render partial="Example" arguments="{key: 'value'}" />
<!-- multiline -->
<f:render partial="Example" arguments="{key: 'value', key1: 'value', key2: 'value', key3: 'value'}"
/>

📋 File Naming

  • Use descriptive and consistent file names for your templates, partials, and layouts.
  • ViewHelper template files should always follow the UpperCamelCase convention (e.g., MainMenu).
# Do
MainMenu.html, Footer.html, ContentTeaser.html

# Don't
main_menu.html, footer.html, content-teaser.html

📂 Directory structure

  • Follow a hierarchical folder structure to organize files logically.
    • The FULLHAUS best practice directory structure can be found in the composer-template repository
    • Note: This structure is a guideline and can change and extend depending on specific project requirements.
  [...]
├── Layouts
│ ├── ContentElements
│ │ ├── Container
│ │ └── Custom
│ └── Email
├── PageView
│ ├── Layouts
│ │ └── Default.html
│ ├── Pages
│ │ └── Default.html
│ └── Partials
│ └── Navigation.html
├── Partials
│ ├── ContentElements
│ │ ├── Container
│ │ └── Custom
│ └── Email
[...]
├── TemplateOverrides
│ └── typo3
│ └── cms-form
└── Templates
├── ContentElements
│ ├── Container
│ └── Custom
└── Email

💬 Template Comments for Clarity

  • Add comments where it makes sense to clarify the purpose of your templates, sections, or complex logic.
  • Comments help other developers understand your code quickly.
  • always wrap HTML comments with <f:comment><f:comment/> ViewHelper
<html data-namespace-typo3-fluid="true" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">

<f:comment>
<!-- Header Section -->
<f:debug>This does not get rendered</f:debug>
</f:comment>

<f:render partial="Header" arguments="{ logo: 'logo.png', title: 'Welcome' }" />
<!-- Rest of template content here -->

</html>

f:translate ViewHelper Usage

  • Do use the id attribute over key, as it is more versatile and future-proof. This is recommended for better readability and maintainability. As seen in core ViewHelper, the key attribute is fallback if no id was given. This means id in the end supersedes and should therefor apply even-though same attribute used in <trans-unit> XLIFF tags.
  • When fetching translation label from the frontend preserved locallang.xlf, use short syntax(id="someId") full spec (id="LLL:EXT:SomeExtensionName/Resources/Private/Language/locallang.xlf:someId")
  • When using prior named short syntax looking in locallang.xlf always provide extensionName attribute neither you are in plugin context or not! This allows you to apply e.g. partials anywhere, even if not in Extbase context, for example in page and email templates.
<html data-namespace-typo3-fluid="true" xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers">

<!-- Don't -->
<f:translate key="someKey" extensionName="SomeExtensionName"/>
<f:translate key="LLL:EXT:SomeOtherExtensionName/Resources/Private/Language/locallang.xlf:someOtherKey" />

<!-- Do -->
<f:translate id="someId" extensionName="SomeExtensionName" />
<f:translate id="someOtherId" extensionName="SomeOtherExtensionName" />

<!-- With Arguments -->
{f:translate(id: 'someId', extensionName: 'SomeExtensionName', arguments: { 0: 'dog', 1: 'fox'}, default: 'default value') }

</html>
note

Important: While the official TYPO3 documentation may sometimes use key in examples, FULLHAUS has adopted the convention of using id for the f:translate ViewHelper. This approach is preferred for better readability, maintainability, and future-proofing. The id attribute offers more versatility as it directly corresponds to the <trans-unit id="..."> within your XLIFF files. Although key can function as a fallback, id ultimately takes precedence. Therefore, consistently using id is the recommended practice within our company.

🚫 Avoid Common Mistakes

Discouraged Practices

IDE Quirks 🤔

  • When templates include inline ViewHelpers – for single namespace – only, your IDE will mark corresponding namespace definition as unused (e.g., xmlns:f). This is a known IDE issue and is safe to ignore.
note

Inline ViewHelpers and Grayscale Namespaces: In some IDEs, inline ViewHelpers might cause the namespace definition to appear grayed out. Don't worry, this is a harmless IDE quirk.

🛠️ Development Practices

1️⃣ Use Partials

  • To maintain clean and modular code, utilize partials wherever it makes sense. This approach ensures your code is:
    • More readable.
    • Easier to maintain.
  • Feel free to group partials logically, e.g. to Menu subdirectory
<f:render partial="Header" arguments="{ logo: 'logo.png', title: 'Welcome' }" />

2️⃣ Reference Repository

📋 Summary

By adhering to these guidelines, we ensure:

  • Consistency across templates.
  • Easier collaboration.
  • Improved maintainability.

🔗 Refer to the TYPO3 Docs on Fluid ViewHelpers for additional information.

Happy coding! 🚀