-
Notifications
You must be signed in to change notification settings - Fork 754
HTL Style Guide
Style guide for HTL, the HTML templating language used in the Adobe Experience Manager Core Components.
HTML comments are rendered in the final markup, so unless there is a specific need, HTL comments are always preferred.
<!-- Don't use HTML comments -->
<!--/* Do use HTL comments */-->
Style guide for HTL Block Statements.
<!--/* Instead of */-->
<div data-sly-include="content.html" data-sly-unwrap></div>
<!--/* Use */-->
<sly data-sly-include="content.html"></sly>
<!--/* Instead of */-->
<div data-sly-resource="${item @ selectors='event'}" data-sly-unwrap></div>
<!--/* Use */-->
<sly data-sly-resource="${item @ selectors = 'event'}"></sly>
<!--/* Instead of */-->
<div data-sly-test="${event.hasDate}" data-sly-unwrap>
...
</div>
<!--/* Use */-->
<sly data-sly-test="${event.hasDate}">
...
</sly>
<!--/* Instead of */-->
<sly data-sly-test.title="${component.title}">
<h1>${title}</h1>
</sly>
<!--/* Use */-->
<h1 data-sly-test.title="${component.title}">${title}</h1>
Rather than <sly/>
, use <sly></sly>
, as the sly
element is neither a void nor foreign element. See html5 start tags.
Use data-sly-repeat
over data-sly-list
, in order to avoid creating unnecessary sly
tags.
<!--/* Instead of */-->
<sly data-sly-list.child="${container.children}">
<div data-sly-resource="${child}"></div>
</sly>
<!--/* Use */-->
<div data-sly-repeat.child="${container.children}" data-sly-resource="${child}"></div>
If a data-sly-test
is used multiple times, define a variable and re-use it, for performance reasons.
<!--/* Instead of */-->
<h1 data-sly-test="${component.textEnabled}">${component.title}</h1>
...
<p data-sly-test="${component.textEnabled}">${component.description}<p>
<!--/* Use */-->
<h1 data-sly-test.textEnabled="${component.textEnabled}">${component.title}</h1>
...
<p data-sly-test="${textEnabled}">${component.description}<p>
Defining HTL block statements first means that variables are available for use in the regular HTML attributes, and that block statements (particularly data-sly-test
, data-sly-list
and data-sly-repeat
) statements are prominent.
<!--/* Instead of */-->
<h1 class="cmp-component__title" data-sly-test="${component.title}">${component.title}</h1>
<!--/* Use */-->
<h1 data-sly-test="${component.title}" class="cmp-component__title">${component.title}</h1>
Since data-sly-use
identifiers are always global, the data-sly-use
attribute should be placed on top-level elements - making it easier to see name clashes and preventing multiple initialization of same Object.
<!--/* Instead of */-->
<div class="cmp-teaser">
<h3 data-sly-use.teaser="com.example.models.Teaser">${teaser.title}</h3>
</div>
<!--/* Use */-->
<div data-sly-use.teaser="com.example.models.Teaser" class="cmp-teaser">
<h3>${teaser.title}</h3>
</div>
To improve readability, use meaningful identifier names. Fullwords rather than shorthands or acronyms are preferred.
<!--/* Instead of */-->
<sly data-sly-use.comp="com.example.models.Teaser">
...
</sly>
<!--/* Use */-->
<sly data-sly-use.teaser="com.example.models.Teaser">
...
</sly>
<!--/* Instead of */-->
<sly data-sly-use.bc="com.example.models.breadcrumb">
...
</sly>
<!--/* Use */-->
<sly data-sly-use.breadcrumb="com.example.models.Breadcrumb">
...
</sly>
<!--/* Instead of */-->
<sly data-sly-use.languagenavigation="com.example.models.LanguageNavigation">
...
</sly>
<!--/* Use */-->
<sly data-sly-use.languageNavigation="com.example.models.LanguageNavigation">
...
</sly>
Usually these block statements can be avoided, leading to cleaner, more easily read code.
<!--/* Instead of */-->
<div data-sly-element="${teaser.titleElement}">${teaser.title}</div>
<a data-sly-attribute.href="${teaser.link}" href="#"></a>
<p data-sly-text="${teaser.description}"></p>
<!--/* Use */-->
<h2>${teaser.title}</h2>
<a href="${teaser.link}"></a>
<p>${teaser.description}</p>
Style Guide for HTL Expression Language.
<!--/* Instead of */-->
<div class="${cssClass ? cssClass : 'my-class'}"></div>
<!--/* Use */-->
<div class="${cssClass || 'my-class'}"></div>
In most cases the display context can be left out as it is determined automatically.
<!--/* Instead of */-->
<a href="${component.link @ context = 'uri'}"></a>
<!--/* Use */-->
<a href="${component.link}"></a>
See HTL URL Manipulation.
<!--/* Instead of */-->
<a href="${component.link}.html"></a>
<!--/* Use */-->
<a href="${component.link @ extension = 'html'}"></a>
Java getter functions such as getTitle()
or isActive()
can be accessed without the get
or is
prefixes and lowering the case of the following character. All properties should be accessed this way for consistency and readability.
<!--/* Instead of */-->
<p>${component.getTitle}</p>
<!--/* Use */-->
<p>${component.title}</p>
<!--/* Instead of */-->
<a href="${item.link}" data-sly-unwrap="${item.isActive}">...</a>
<!--/* Use */-->
<a href="${item.link}" data-sly-unwrap="${item.active}">...</a>
<!--/* Instead of */-->
<sly data-sly-use.clientlib="${'/libs/granite/sightly/templates/clientlib.html'}">
...
</sly>
<!--/* Use */-->
<sly data-sly-use.clientlib="/libs/granite/sightly/templates/clientlib.html">
...
</sly>