The HTML structure of pages and renderings

Current version: 1.5

SXA separates structure (HTML) from design (CSS) to make it easier to change the design of websites. To make this possible, SXA provides a stable well-structured HTML code that is the same for every page. Users can apply different styling without changing the underlying code.

This topic describes the basic structure for:

Page HTML

All SXA pages use the following layout structure:

RequestResponse
<html>
<head>
  <!-- meta renderings placeholder "head" -->
</head>
<body>
  <!-- meta renderings placeholder "body-top" -->
  <div id="wrapper">
    <div id="header" class="main clearfix">
      <!-- header components -->
    </div>
    <div id="content" class="main clearfix">
      <!-- content components -->
    </div>
    <div id="footer" class="main clearfix">
      <!-- footer components -->
    </div>
  </div>
  <!-- meta renderings placeholder "body-bottom" -->
</body>

All regular renderings can be placed in the following containers:

  • Header

  • Content

  • Footer

Meta renderings can be placed on Meta Partial Designs in the following containers:

  • Head

  • Body-top

  • Body-bottom

Designers can use page splitters to generate additional columns or rows inside the header, content, or footer containers.

There are two types of splitters:

  • Column splitters – generates divs with proper grid classes wrapped by the row container. Grid values specify the column widths.

    RequestResponse
    <div class='row'>
      <div class='grid-6'></div>
      <div class='grid-6'></div>
    </div>
  • Row splitters – generates empty row divs that fill the full width of the available parent container.

    RequestResponse
    <div class='row'></div>
    <div class='row'></div>
    <div class='row'></div>

You can add classes for both columns and rows. You can also mark specific splitter sections and style them differently than the other sections. This can be useful for styling a page part that breaks the grid system. However, you can only override grid behavior for specific rows.

Rendering HTML

All SXA renderings are designed to be easily styled. Because the HTML is very standard, it is easy for theme developers to apply CSS and JavaScript.

The following example uses the Accordion rendering. The HTML structure for renderings is wrapped by div with the component class and the component name accordion. You can add CSS class variants for styling purposes.

RequestResponse
<div class="component accordion {custom classes}" data-properties='{"expandOnHover":false,"expandedByDefault":false,"speed":5000,
"easing":"easeInOutBounce","canOpenMultiple":false,"canToggle":false}'
>
  <div class="component-content">
    <div>
      <ul class="items">
        <li class="item">
          <div class="toggle-header">
            <div class="label">
              Header content
            </div>
          </div>
          <div class="toggle-content">
              Section content
          </div>
        </li>       </ul>
    </div>
  </div>
</div>
Note

Use classes for styling. Do not use IDs. Div IDs are used by Sitecore and cannot be changed.

The following properties are used by JavaScript to control rendering behavior:

  • expandedByDefault – first accordion tab is visible.

  • expandOnHover – expand tab on mouse enter and close on mouse leave events (the canOpenMultiple property is not used in this case).

  • canOpenMultiple – open multiple tabs at the same time (the canToggle property is always active and cannot be disabled).

  • speed and easing – can be used everywhere to define transition method and time.

Every SXA rendering contains the same wrapping structure:

RequestResponse
<div class='component <component-name>'
  <div class='component-content'>
      <!-- component html -->
  </div>
</div>

The code inside will be different for each rendering. Often, there will be an additional wrapping div with a unique ID that describes the specific rendering used by Sitecore. CSS/JS scripts should not use these IDs.

Note

The inner rendering structure uses clean markup with dash-separated class convention. There are a few exceptions: some elements, such as forms, use additional Sitecore modules (for example, Web Forms for Marketers) and generate HTML that looks different (camelCase class names, and tables in some cases). You cannot modify this HTML.

Every HTML rendering is part of a platform and you cannot change it for a single project or site, except where the HTML is shaped by rendering variants.

JavaScript

Complex renderings have their own JavaScript. These scripts are located in the JavaScript framework in the main themes folder. The framework provides public methods, such as register and init, to register renderings and additional helpers, such as cookies.

All back-end properties used by JavaScript are placed in the data-properties attribute inside the rendering wrapping div. They are encoded in JSON format.

RequestResponse
<div class='component accordion' data-properties='{"expandOnHover":false,"expandedByDefault":false,"speed":5000,
"easing":"easeInOutBounce","canOpenMultiple":false,"canToggle":false}'
</div>

The following is a clipped version of the JavaScript framework:

RequestResponse
var XA = XA || (function ($, document) {
    var api = {}, onPreInitHandlers, onPostInitHandlers, modules = {};
    onPreInitHandlers = new Array();
    onPostInitHandlers = new Array();
    /*
     * Register new module
     * @params name - name of the module
     * @params api - API object of the module
     * @params init - init function for module, if not defined api.init will be used
     */
    api.register = function (name, api, init) {
        modules[name] = {
            name: name,
            api: api,
            init: init || api.init || (function () { })
        };
    };
    api.registerOnPreInitHandler = function (handler) { onPreInitHandlers.push(handler); };
    api.registerOnPostInitHandler = function (handler) { onPostInitHandlers.push(handler); };
    var initScheduled = false;
    /*
     * Initializes all registered modules
     */
    api.init = function () {
        if (!initScheduled) {
            initScheduled = true;
            XA.ready(function () {
                try {
                    for (var name in modules)
                        if (modules.hasOwnProperty(name)) {
                            $xa.each(onPreInitHandlers, function (i, h) { h.process(name, modules[name]); });
                            modules[name].init();
                            $xa.each(onPostInitHandlers, function (i, h) { h.process(name, modules[name]); });
                        }
                }
                finally {
                    initScheduled = false;
                }
            });
        }
    };
    /*
     * Wrapper around $(document).ready - fires given function when (or if) document is ready
     */
    api.ready = function (fn) {
        $(document).ready(fn);
    };
    // namespace for components
    api.component = {};
    // namespace for different connectors (e.g., Google Maps JS API connector, Bing maps connector)
    api.connector = {};
    api.cookies = {
        createCookie: function (name, value, days) {
            if (days) {
                var date = new Date();
                date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
                var expires = "; expires=" + date.toUTCString();
            }
            else {
                expires = "";
            }
            document.cookie = name + "=" + value + expires + "; path=/";
        },
        readCookie: function (name) {
            var nameEQ = name + "=";
            var ca = document.cookie.split(';');
            for (var i = 0; i < ca.length; i++) {
                var c = ca[i];
                while (c.charAt(0) == ' ') {
                    c = c.substring(1, c.length);
                }
                if (c.indexOf(nameEQ) == 0) {
                    return c.substring(nameEQ.length, c.length);
                }
            }
            return null;
        },
        removeCookieWarning: function () {
            var cookieWarning = $xa(".privacy-warning");
            cookieWarning.remove();
        }
    };
    api.queryString = {
        getQueryParam: function (variable) {
            if (variable != null) {
                variable = variable.toLocaleLowerCase();
            }
            var query = window.location.search.substring(1);
            var vars = query.split("&");
            for (var i = 0; i < vars.length; i++) {
                var pair = vars[i].split("=");
                if (decodeURIComponent(pair[0].toLocaleLowerCase()) === variable) {
                    return decodeURIComponent(pair[1]);
                }
            }
            return null;
        }
    };
    return api;
})($, document);
XA.init();
var ZG = (function ($, document) {
    var api = {},
        modules = {};
    /*
     * Register new module
     * @params name - name of the module
     * @params api - API object of the module
     * @params init - init function for module, if not defined api.init will be used
     */
    api.register = function (name, api, init) {
        modules[name] = {
            name: name,
            api: api,
            init: init || api.init || function () {}
        };
    };
    var initScheduled = false;
    /*
     * Initializes all registered modules
     */
    api.init = function () {
        if (!initScheduled) {
            initScheduled = true;
            ZG.ready(function () {
                try {
                    for (var name in modules) if (modules.hasOwnProperty(name)) {
                        modules[name].init();
                    }
                } finally {
                    initScheduled = false;
                }
            });
        }
    };
    /*
     * Wrapper around $(document).ready - fires given function when (or if) document is ready
     */
    api.ready = function (fn) {
        $(document).ready(fn);
    };
    return api;
})($, document);

CSS

You can replace a single class to change rendering behavior, for example, to change from standard navigation to mobile navigation. You can also create your own rendering variant by adding CSS classes and add styling and JavaScript functionality. You must adhere to naming conventions. Classes for specific renderings always start with the name of rendering. Add words that explain the functionality of the new class using the dash name convention. For example: .navigation-mobile, .navigation-main-horizontal, .navigation-sidebar.

Do you have some feedback for us?

If you have suggestions for improving this article,