Custom blocks

Custom blocks allow you to present custom links to internal or external resources on the Home page.

Custom blocks, like content blocks and contact blocks, are configurable through theme settings. You can control both the content of the blocks as well as their look-and-feel and layout.

Blocks

Presenting categories in blocks or cards is a popular choice, particularly on the Home page.

Blocks with grow on hover effect
View code
<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns) {
    var classNames = 'col-12';
    if (numberColumns >= 2) classNames += ' md:col-6';
    if (numberColumns >= 3) classNames += ' lg:col-4';
    if (numberColumns >= 4) classNames += ' xl:col-3';
    return classNames;
  } %>
  <div class="container text-<%= alignment %>">
    {{~#if settings.custom_blocks_heading}}
      <h2 class="flex align-items-baseline mt-6" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{~#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if~}}
      </h2>
    {{/if~}}
    <ul class="list-unstyled row row-sm justify-content-center mb-0">
      <% blocks.forEach(function(block, index) { %>
        <li class="<%= getColumnClasses(numberColumns) %>">
          <a class="block link-plain text-inherit p-5 h-full transition-fast hover:bg-<%= color %> hover:text-<%= color %>-inverse hover:grow hover:shadow-lg" href="<%= block.html_url %>"
            x-data="{ hover: false }"
            @mouseover="hover = true"
            @mouseleave="hover = false">
            <% if (imageHeight) { %>
              <img alt="" src="<%= images[index] || images[0] %>" style="height: <%= imageHeight %>; width: auto;" />
            <% } %>
            <% if (block.name) { %>
              <h2 class="<% if (numberColumns > 3) { %> h3<% } %>" :class="{ 'text-inherit': hover }">
                <%= block.name %>
              </h2>
            <% } %>
            <% if (block.description) { %>
              <p>
                <%= block.description %>
              </p>
            <% } %>
          </a>
        </li>
      <% }) %>
    </ul>
  </div>
</template>
Blocks with translucent hover effect
View code
<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns) {
    var classNames = 'col-12';
    if (numberColumns >= 2) classNames += ' md:col-6';
    if (numberColumns >= 3) classNames += ' lg:col-4';
    if (numberColumns >= 4) classNames += ' xl:col-3';
    return classNames;
  } %>
  <div class="container">
    {{~#if settings.custom_blocks_heading}}
      <h2 class="flex align-items-baseline mt-6" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{~#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if~}}
      </h2>
    {{/if~}}
    <ul class="list-unstyled justify-content-center row my-5">
      <% blocks.forEach(function(block, index) { %>
        <li class="hover:img-grow <%= getColumnClasses(numberColumns) %>" style="animation-delay: calc(150ms * <%= index %>);" data-animation="show">
          <div class="card card-body h-full text-<%= alignment %> text-inherit transition border-transparent hover:bg-translucent hover:border-<% if (color === 'white') { %>translucent<% } else { %><%= color %><% } %>">
            <% if (imageHeight) { %>
              <img class="my-4 <% if (alignment === 'left') { %>mr-auto<% } else { %>mx-auto<% } %>" alt="" src="<%= images[index] || images[0] %>" style="height: <%= imageHeight %>; width: auto;" />
            <% } %>
            <% if (block.name) { %>
              <h2 class="h3">
                <% if (block.html_url) { %>
                  <a class="link-stretched text-inherit transition-fast hover:no-underline hover:text-<% if (color === 'white') { %>inherit<% } else { %><%= color %><% } %>" href="<%= block.html_url %>">
                    <%= block.name %>
                  </a>
                <% } else { %>
                  <%= block.name %>
                <% } %>
              </h2>
            <% } %>
            <% if (block.description) { %>
              <p class="font-size-md">
                <%= block.description %>
              </p>
            <% } %>
          </div>
        </li>
      <% }) %>
    </ul>
  </div>
</template>

Cards

Card with border on hover
View code
<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns) {
    var classNames = numberColumns === 'auto' ? 'col-auto' : 'col-12';
    if (numberColumns >= 2) classNames += ' md:col-6';
    if (numberColumns >= 3) classNames += ' lg:col-4';
    if (numberColumns >= 4) classNames += ' xl:col-3';
    return classNames;
  } %>
  <div class="container text-<%= alignment %> py-{{#is settings.bg_color settings.bg_color_custom_blocks}}2{{else}}4{{/is}}">
    {{#if settings.custom_blocks_heading}}
      <h2 class="inline-flex align-items-baseline mt-6" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if}}
      </h2>
    {{/if}}
    <ul class="list-unstyled row row-sm justify-content-start mt-4 mb-0 text-<%= alignment %>">
      <% blocks.forEach(function(block, index) { %>
        <li class="mb-4 <%= getColumnClasses(numberColumns) %>">
          <div class="card card-body text-base bg-white h-full<% if (block.html_url) { %> transition-fast hover:border-<%= color %><% } %>">
            <div class="justify-content-between<% if (imageHeight) { %> align-items-center<% } %>">
              <% if (imageHeight) { %>
                <% var src = images.length > index ? images[index] : images[images.length - 1] %>
                <img class="my-2 text-primary fill-current" src="<%= src %>" alt="" style="height: <%= imageHeight %>; width: auto;" />
              <% } %>
              <% if (block.name) { %>
                <h2 class="my-2<% if (numberColumns > 3 || !imageHeight) { %> h3<% } %>">
                  <% if (block.html_url) { %>
                    <a class="link-stretched text-inherit hover:text-inherit hover:no-underline" href="<%= block.html_url %>">
                      <%= block.name %>
                    </a>
                  <% } else { %>
                    <%= block.name %>
                  <% } %>
                </h2>
              <% } %>
              <% if (block.description) { %>
                <p class="my-2">
                  <%= block.description %>
                </p>
              <% } %>
            </div>
          </div>
        </li>
      <% }) %>
    </ul>
  </div>
</template>
Card with border and transition effect
View code
<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns) {
    var classNames = 'col-12';
    if (numberColumns >= 2) classNames += ' md:col-6';
    if (numberColumns >= 3) classNames += ' lg:col-4';
    if (numberColumns >= 4) classNames += ' xl:col-3';
    return classNames;
  } %>
  <div class="container text-<%= alignment %>py-{{#is settings.bg_color settings.bg_color_custom_blocks}}2{{else}}4{{/is}}">
    {{#if settings.custom_blocks_heading}}
      <h2 class="inline-flex align-items-baseline font-size-2xl mt-4" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if}}
      </h2>
    {{/if}}
    <ul class="list-unstyled row row-sm justify-content-start mb-0{{#unless settings.custom_blocks_heading}} mt-4{{/unless}}">
      <% blocks.forEach(function(block, index) { %>
        <li class="mb-6 <%= getColumnClasses(numberColumns) %> text-<%= alignment %>">
          <div class="card border-gray-300 border-radius h-full bg-white shadow-sm overflow-hidden transition-fast hover:shadow-none hover:sink">
            <a class="card-body border-left border-left-4 border-<%= color !== 'white' ? color : 'primary' %> font-size-lg hover:no-underline" href="<%= block.html_url %>">
              <% if (imageHeight) { %>
                <img class="my-4 text-primary fill-current" src="<%= images.length > index ? images[index] : images[images.length - 1] %>" alt="" style="height: <%= imageHeight %>; width: auto;" />
              <% } %>
              <% if (block.name) { %>
                <h2 class="mt-4<% if (numberColumns > 3) { %> h3<% } %>">
                  <%= block.name %>
                </h2>
              <% } %>
              <% if (block.description) { %>
                <p class="text-base">
                  <%= block.description %>
                </p>
              <% } %>
            </a>
          </div>
        </li>
      <% }) %>
    </ul>
  </div>
</template>
Featured card layout
View code
<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns) {
    var classNames = 'col-12';
    if (numberColumns >= 2) classNames += ' md:col-6';
    if (numberColumns >= 3) classNames += ' lg:col-4';
    if (numberColumns >= 4) classNames += ' xl:col-3';
    return classNames;
  } %>
  <div class="container text-<%= alignment %>py-{{#is settings.bg_color settings.bg_color_custom_blocks}}2{{else}}4{{/is}}">
    {{#if settings.custom_blocks_heading}}
      <h2 class="inline-flex align-items-baseline font-size-2xl mt-4" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if}}
      </h2>
    {{/if}}
    <% var hasFeatured = blocks.length === 3 && numberColumns === 3; %>
    <ul class="list-unstyled relative row row-sm justify-content-center my-0<% if (hasFeatured) { %> my-6<% } %>">
      <% blocks.forEach(function(block, index) { %>
        <% var isFeatured = hasFeatured && index === 1; %>
        <li class="flex mb-4 <%= getColumnClasses(numberColumns) %> text-<%= alignment %><% if (isFeatured) { %> lg:-mt-4 lg:-mb-2<% } %>">
          <a class="card bg-white shadow-xs border-transparent text-inherit transition w-full h-full lg:h-auto hover:no-underline hover:shadow-sm hover:float hover:text-<% if (color === 'white') { %>primary<% } else { %><%= color %><% } %> <% if (color !== 'white') { %> hover:border-<%= color %><% } %>" href="<%= block.html_url %>">
            <div class="card-body py-4<% if (isFeatured) { %> lg:py-6 lg:scale-110<% if (alignment === 'left') { %> lg:px-7<% } %><% } %>">
              <% if (imageHeight) { %>
                <img class="mt-4 fill-current<% if (isFeatured) { %> lg:scale-110<% } %>" src="<%= images.length > index ? images[index] : images[images.length - 1] %>" alt="" style="height: <%= imageHeight %>; width: auto;" data-inline-svg />
              <% } %>
              <% if (block.name) { %>
                <h3 class="text-inherit mb-3">
                  <%= block.name %>
                </h3>
              <% } %>
              <% if (block.description) { %>
                <p class="text-gray-600">
                  <%= block.description %>
                </p>
              <% } %>
            </div>
          </a>
        </li>
      <% }) %>
    </ul>
  </div>
</template>

Tiles

<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns, index) {
    var classNames = 'col-12';
    if (numberColumns >= 2) {
      classNames += ' md:col-6';
      if (index === 1 || index === 3) classNames += ' md:border-left';
      if (index > 1) classNames += ' md:border-top';
    }
    if (numberColumns === 3) {
      classNames += ' lg:col-4';
      if (index === 2) classNames += ' lg:border-left lg:border-top-0';
      if (index === 3) classNames += ' lg:border-top lg:border-left-0';
    }
    if (numberColumns >= 4) {
      classNames += ' xl:col-3';
      if (index > 0) classNames += ' xl:border-left xl:border-left-1 xl:border-top-0';
    }
    return classNames;
  } %>
  <div class="container text-<%= alignment %>">
    {{~#if settings.custom_blocks_heading}}
      <h2 class="inline-flex align-items-baseline mt-6" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{~#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if~}}
      </h2>
    {{/if~}}
    <ul class="list-unstyled row row-sm justify-content-start m-0">
      <% blocks.forEach(function(block, index) { %>
        <li class="<%= getColumnClasses(numberColumns, index) %>">
          <div class="card p-4 h-full border-0 lg:p-5">
            <div class="media flex-column align-items-center text-center<% if (alignment === 'left') { %> sm:flex-row sm:text-left<% } %>">
              <% if (imageHeight) { %>
                <a class="flex align-self-center p-5 mx-3 align-items-center justify-content-center link-stretched circle transition bg-gray-100 hover:bg-gray-200<% if (alignment === 'left') { %> sm:mr-6 sm:align-items-center<% } %>" href="<%= block.html_url %>">
                  <img alt="<%= block.name %>" src="<%= images[index] || images[0] %>" style="height: <%= imageHeight %>; width: auto;" />
                </a>
              <% } %>
              <div class="media-body">
                <% if (block.name) { %>
                  <h2 class="mt-4 mb-2<% if (numberColumns > 3) { %> h3<% } %>">
                    <%= block.name %>
                  </h2>
                <% } %>
                <% if (block.description) { %>
                  <p class="font-size-lg text-gray-600">
                    <%= block.description %>
                  </p>
                <% } %>
              </div>
            </div>
          </div>
        </li>
      <% }) %>
      <% if (blocks.length == 3) { %>
        <li class="md:col-auto md:border-top md:border-left<% if (numberColumns === 3) { %> lg:hidden<% } %><% if (numberColumns === 4) { %> xl:hidden<% } %>"></li>
      <% } %>
      <% if (blocks.length === 4 && numberColumns === 3) { %>
        <li class="lg:col-auto lg:border-top lg:border-left"></li>
      <% } %>
    </ul>
  </div>
</template>

Lists and list groups

List group with icons
View code
<template id="tmpl-custom-blocks">
  <% var getColumnClasses = function(numberColumns) {
    var classNames = 'col-12';
    if (numberColumns >= 2) classNames += ' md:col-6';
    if (numberColumns >= 3) classNames += ' lg:col-4';
    if (numberColumns >= 4) classNames += ' xl:col-3';
    return classNames;
  } %>
  <div class="container text-<%= alignment %>">
    {{~#if settings.custom_blocks_heading}}
      <h2 class="flex align-items-baseline mt-6" x-data="{ src: Theme.assets['custom-blocks-heading'] }">
        <template x-if="src">
          <img class="svg-icon mr-2" src="{{asset 'placeholder.png'}}" alt="" aria-hidden="true" :src="src" />
        </template>
        {{~#if settings.use_translations}}
          {{dc settings.custom_blocks_heading}}
        {{else}}
          {{settings.custom_blocks_heading}}
        {{/if~}}
      </h2>
    {{/if~}}
    <div class="list-group list-group-flush border border-radius overflow-hidden bg-white shadow-xs my-6">
      <div class="row row-flush align-items-stretch text-<%= alignment %>">
        <% blocks.forEach(function(block, index) { %>
          <a class="list-group-item list-group-item-action <%= getColumnClasses(numberColumns) %>" href="<%= block.html_url %>">
            <div class="media h-full p-5<% if (alignment === 'center') { %> flex-column<% } %><% if (numberColumns >= 2) { %> md:flex-column<% } %>">
              <% if (imageHeight) { %>
                <div class="circle border p-5 bg-gray-100 link-stretched transition hidden md:flex hover:bg-white hover:border-<%= color %> <% if (alignment === 'left') { %>align-self-center mx-2<% } else { %>mx-auto mb-4<% } %><% if (numberColumns >= 2) { %> md:mb-4 md:align-self-<% if (alignment === 'left') { %>start<% } else { %>center<% } %><% } %>">
                  <img class="inline-flex" src="<%= images[index] || images[images.length - 1] %>" alt="" style="height: <%= imageHeight %>; width: <%= imageHeight %>;" />
                </div>
              <% } %>
              <div class="media-body align-self-center w-full px-4">
                <% if (block.name) { %>
                  <h3 class="my-2 text-<%= color %>">
                    <%= block.name %>
                  </h3>
                <% } %>
                <% if (block.description) { %>
                  <p class="mb-2">
                    <%= block.description %>
                  </p>
                <% } %>
              </div>
              <% if (alignment === 'left') { %>
                <svg class="svg-icon ml-2 align-self-center font-size-sm text-<%= color %> fill-current<% if (numberColumns >= 2) { %> hidden<% } %>" viewBox="0 0 190 323" xmlns="http://www.w3.org/2000/svg">
                  <path d="M190,162 C190,168 187,174 183,178 L38,317 C34,321 28,323 23,323 C17,323 11,321 7,317 C-2,308 -2,294 7,285 L135,162 L7,39 C-2,31 -2,16 7,7 C15,-2 29,-2 38,7 L183,146 C187,150 190,156 190,162 Z"></path>
                </svg>
              <% } %>
            </div>
          </a>
        <% }) %>
      </div>
    </div>
  </div>
</template>

By default custom blocks are displayed on the Home page, however you can use them anywhere in the help center.

You can display custom blocks on the Home page using theme settings.

The following settings, found within the Custom blocks setting group, are available in the to use in every theme when customizing custom blocks:

Setting Description
Custom blocks style The style of custom blocks to display.
Custom blocks color The color palette used for custom blocks.
Custom blocks background color The background color applied to the custom blocks section.
Custom blocks heading The heading to display above the custom blocks.
Custom blocks number The maximum number of custom blocks to display.
Custom blocks columns The maximum number of columns to display per row.
Custom blocks alignment The alignment of content within custom blocks.
Custom blocks image height The height (in px) for custom block images.

Select a style from the Custom blocks style setting to have the custom blocks appear.

To display custom blocks on any page in the help center other than the Home page:

  1. Select the “Custom template” option from the Custom blocks style setting in the Custom blocks setting group to ensure that there’s not a conflict with an existing micro-template.

  2. Copy the HTML hook below into the position where you’d like the custom blocks to appear.

     <div class="custom bg-custom-blocks" id="custom-blocks">
       <script type="text/javascript">
         ready(function() {
           Util.renderTemplate(document.getElementById('custom-blocks'), 'custom-blocks', Theme.customBlocks);
         })
       </script>
     </div>
    
  3. Copy-and-paste your selected pattern micro-template into the bottom of the footer.hbs template.

The title, description, URL and image of each block is configurable through theme settings.

Custom actions

Using custom JavaScript on the page, it’s possible to have certain URLs (like those starting with a hash tag) trigger actions.

For example, if you wanted the Web Widget to be hidden by default and then revealed when a user clicks on the Chat with us block, you could configure the block’s URL to be #show-widget and then add something like the following custom JavaScript code to the Home page template (home_page.hbs):

<script type="text/javascript">

  // Shows the Zendesk Web Widget
  function showWebWidget(e) {
    zE('webWidget', 'show');
    e.preventDefault();
  }

  document.addEventListener("DOMContentLoaded", function() {
  
    // Hide the Zendesk Web Widget on page load
    zE('webWidget', 'hide');

    // Add the required event listeners
    var links = Array.prototype.slice.call(document.querySelectorAll('a[href="#show-widget"]'));
    links.forEach(function(a) {
      a.addEventListener('click', showWebWidget, false);
    });
  });
</script>

Related patterns