Skip to content

Styling

Layouts

A layout is a named rendering option inside a component view. Each layout stores the markup for one way of rendering a component, so a single view can offer several interchangeable renderings and the content picks the one it wants by name.

What a layout is

A layout is a kes:Layout node that holds the HTML (content.html) for a single rendering of a component. A component view can carry more than one layout, which lets the same component render in different ways without changing the component itself.

The content.html in a layout folder carries the HTL script that renders the component for this view. See Writing HTL for the template syntax, and Component Views.

Where layouts live

Layouts live inside a versioned component view, so they carry that view's version rather than being versioned on their own. A layout sits beneath the view at {component}/{library-or-framework-code}/{version}/layouts/{name}/, where each {name} folder is a kes:Layout node with its own content.html.

JCR structure
/apps/.../components/lists/card-list/   # a component
  acpl-framework/                    # library-or-framework-code
    0.2.11/                          # version
      layouts/
        default/                    # kes:Layout  (fallback rendering)
          content.html              # HTL for this rendering
        timeline/                   # kes:Layout  (an alternate rendering)
          content.html

The default layout

Every component view should include a default layout. It is the rendering a component falls back to when the content does not ask for a specific layout by name.

A default layout is effectively required. If a component view offers named layouts but no default, a request that does not name a layout resolves nothing to include, and the include fails at render time (Sling reports Path for data-sly-include is empty). Give every component view a default layout to avoid empty-include errors.

A layout node is defined by a .content.xml with a kes:Layout primary type:

Req: Y = required, Rec = recommended, blank = optional
PropertyTypeReqDescription
jcr:primaryTypeYMust be kes:Layout
jcr:titleStringRecHuman-readable name for the layout
layouts/default/.content.xml
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:jcr="http://www.jcp.org/jcr/1.0"
          xmlns:kes="http://kestros.io/kes/1.0"
          jcr:primaryType="kes:Layout"
          jcr:title="Default"/>

The matching content.html lives in the same layout directory and holds the HTL script that renders this layout of the component.

For example, the card-list component ships a default layout that renders its cards in a three-column grid:

layouts/default/content.html
<sly data-sly-use.cardList="${'io.kestros.cms.components.basic.core.lists.cardlist.CardListDataSourceComponent'}"/>
<div class="row row-cols-1 row-cols-md-3 ${cardList.inlineVariations}">
    <sly data-sly-list.card="${cardList.cards}">
        <div class="col mb-4">
            <sly data-sly-resource="${card}"/>
        </div>
    </sly>
</div>

Its stat-tiles layout binds the same model and lists the same cards, but wraps them in a compact, auto-sizing tile grid instead. Same data, different rendering:

layouts/stat-tiles/content.html
<sly data-sly-use.cardList="${'io.kestros.cms.components.basic.core.lists.cardlist.CardListDataSourceComponent'}"/>
<div class="row mb-4 ${cardList.inlineVariations}">
    <sly data-sly-list.card="${cardList.cards}">
        <div class="col-6 col-sm-4 col-md-3 col-lg-auto">
            <sly data-sly-resource="${card}"/>
        </div>
    </sly>
</div>

Selecting a layout in content

Content chooses a layout by setting a layout property to the layout's node name. If the property is absent, the component renders with the default layout.

An unknown layout name fails silently. If layout names a layout the resolved view does not have, resolution falls back to default with no error. The page still renders, so a typo or a missing layout can be easy to miss. Confirm the layout name exists in the view you expect to resolve.

Layouts and variations

Layouts and variations work together on a component view: the layout supplies the base markup for a rendering, and variations layer registered CSS classes on top of that markup. See Variations.

The default layout above already shows the connection point: its wrapper renders ${cardList.inlineVariations} (<div class="row row-cols-1 row-cols-md-3 ${cardList.inlineVariations}">). Any variation applied to the card-list component is emitted there as CSS classes on that same wrapper, so the layout's markup is unchanged whether or not a variation is set.