HTL Tutorial #1: Introduction to HTML Template Language
HTL Tutorial #1: Introduction to HTML Template Language
What is HTL?
HTL (HTML Template Language), previously called Sightly, is the recommended and preferred templating system for Adobe Experience Manager (AEM).
Why HTL?
- Built-in security: Automatic protection against XSS (Cross-Site Scripting)
- Simplicity: HTML-like syntax, easy to read and write
- Logic/presentation separation: Complex logic goes in Java/JS, not in the template
- Performance: Compiled into Java Servlets for efficient server-side execution
- Designer-friendly: Designers can work with HTML without knowing Java
Basic Syntax
HTL uses two main constructs:
1. Expressions ${...}
HTL expressions are enclosed between ${ and }:
<h1>${properties.title}</h1>Output:
<h1>Welcome to my site</h1>2. Attributes data-sly-*
HTL attributes start with data-sly- and control element behavior:
<div data-sly-test="${properties.showContent}">
<p>This content is shown only if showContent is true</p>
</div>First Complete Example
Let's create a simple HTL component to display author information:
<!--/* Simple Author Component */-->
<div class="author-card">
<!-- Title with expression -->
<h2>${properties.authorName}</h2>
<!-- Conditional paragraph -->
<p data-sly-test="${properties.bio}">${properties.bio}</p>
<!-- Link only if present -->
<a data-sly-test="${properties.website}"
href="${properties.website}">
Visit the site
</a>
</div>Component data (dialog)
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:granite="http://www.adobe.com/jcr/granite/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Proprietà Autore"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/tabs"
type="nav"/>
<items jcr:primaryType="nt:unstructured">
<properties
jcr:primaryType="nt:unstructured"
jcr:title="Informazioni Autore"
sling:resourceType="granite/ui/components/coral/foundation/container">
<layout
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/layouts/fixedcolumn"
margin="{Boolean}false"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<authorName
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Nome Autore"
name="./authorName"
required="{Boolean}true"/>
<bio
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textarea"
fieldLabel="Biografia"
name="./bio"/>
<website
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Sito Web"
name="./website"
validation="url"/>
</items>
</column>
</items>
</properties>
</items>
</content>
</jcr:root>HTML Output
With the data:
authorName: "John Smith"bio: "Senior AEM Developer"website: "https://johnsmith.com"
<div class="author-card">
<h2>John Smith</h2>
<p>Senior AEM Developer</p>
<a href="https://johnsmith.com">Visit the site</a>
</div>HTL Comments
HTL has a special type of comment that is completely removed from the output:
<!--/* This is an HTL comment */-->
<!--/*
Multi-line comment
Will not appear in the final HTML
*/-->Difference with normal HTML comments:
<!-- This appears in the HTML output -->
<!--/* This is completely removed */-->Comparison with JSP
JSP (old way):
<h1><%= properties.get("title", "") %></h1>
<% if (properties.get("showContent", false)) { %>
<p>Content</p>
<% } %>HTL (new way):
<h1>${properties.title}</h1>
<p data-sly-test="${properties.showContent}">Content</p>HTL is cleaner, safer, and more readable!
Basic Best Practices
- Always use expressions for output:
${...} - Don't put complex logic in the template: use
data-sly-useto load Java models - Leverage automatic security: HTL automatically escapes output
- Comment your code: use
<!--/* */-->to document templates
Next Lesson
In the next lesson we will dive deeper into HTL expressions, data types, and available operators.
Resources
This is lesson #1 of a complete series on HTL. Continue with the next lesson to dive deeper into expressions and syntax.