Blog template markup

Last updated:

Blogs on the HubSpot CMS are made up of blog listing pages, and individual blog posts. All blog posts within a blog render using a single blog post template, and the various blog listing pages (main listing, author listing, tag listing) render using a single blog listing template. If statements are used to customize your markup based on whether you are looking for a single post or listing layout. For loops are used to iterate through your content and list different selections of posts. 

The following article will explain the standard markup for blog templates, as well as describe a few simple customizations. 

If is_listing_view statement

Standard HubSpot blog content areas are created with a master if statement that evaluates whether the user is looking at a listing page or an individual post. If you are using a drag and drop template builder template, this if statement is built into the UI of blog content module buttons.

If you are coding an HTML blog template and are using a single template for both your post and listing layouts, then you need to define this if statement. Within the if statement, you will write both your post and listing code.

HubL
{% if is_listing_view %}
    Markup for blog listing template
{% else %}
    Markup for blog post template
{% endif %}

Alternatively, you can choose to have a separate template for blog post listing pages. This allows your code to be cleaner and easier to read. The CMS boilerplate has a separate listing template and post template. If you build separate post and listing templates, this conditional is_listing_view check is not required, you only need to make sure to select the separate templates in Settings > Website > Blog > Templates

Blog settings template selection

Blog listing for loop

The listing of posts is generated by a for loop that iterates through your blog posts. Contents is a predefined sequence of content that contains all the posts contained in that blog.

HubL
{% for content in contents %}
    <div class="post-item">
        Post item markup that renders with each iteration.              
    </div>
{% endfor %}

Listing template markup

The boilerplate blog listing page contents for loop is rendered with the following markup:

HubL
{% for content in contents %}
    {# On the blog homepage the first post will be featured above older posts #}
    {% if (loop.first && current_page_num == 1 && !topic) %}
    <div class="blog-index__post blog-index__post--large">
        <a class="blog-index__post-image blog-index__post-image--large"
        {% if content.featured_image %}
            style="background-image: url('{{ content.featured_image }}')";
        {% endif %}
        href="{{ content.absolute_url }}"></a>
        <div class="blog-index__post-content  blog-index__post-content--large">
        <h2><a href="{{ content.absolute_url }}">{{ content.name }}</a></h2>
        {{ content.post_list_content }}
        </div>
    </div>
    {% else %}
    <div class="blog-index__post blog-index__post--small">
        <a class="blog-index__post-image blog-index__post-image--small"
        {% if content.featured_image %}
            style="background-image: url('{{ content.featured_image }}')";
        {% endif %}
        href="{{ content.absolute_url }}"></a>
        <div class="blog-index__post-content  blog-index__post-content--small">
        <h2><a href="{{ content.absolute_url }}">{{ content.name }}</a></h2>
        {{ content.post_list_content|truncatehtml(100) }}
        </div>
    </div>
    {% endif %}
{% endfor %}

If blog_author statement

Within the standard HubSpot blog listing markup, there is an if blog_author statement. This statement evaluates to true when you are looking at an author listing page. An author listing page is a page of posts by a single author. The standard HubSpot template includes the author's name, bio, and social media accounts.
HubL
{% if blog_author %}
  <div class="blog-header">
    <div class="blog-header__inner">
      {% if blog_author.avatar %}
      <div class="blog-header__author-avatar" style="background-image: url('{{ blog_author.avatar }}');"></div>
      {% endif %}
      <h1 class="blog-header__title">{{ blog_author.display_name }}</h1>
      <h4 class="blog-header__subtitle">{{ blog_author.bio }}</h4>
      {% if blog_author.has_social_profiles %}
        <div class="blog-header__author-social-links">
          {% if blog_author.website %}
            <a href="{{ blog_author.website }}" target="_blank">
              {% icon name="link" style="SOLID" width="10" %}
            </a>
          {% endif %}
          {% if blog_author.facebook %}
            <a href="{{ blog_author.facebook }}" target="_blank">
              {% icon name="facebook-f" style="SOLID" width="10" %}
            </a>
          {% endif %}
          {% if blog_author.linkedin %}
            <a href="{{ blog_author.linkedin }}" target="_blank">
              {% icon name="linkedin-in" style="SOLID" width="10" %}
            </a>
          {% endif %}
          {% if blog_author.twitter %}
            <a href="{{ blog_author.twitter }}" target="_blank">
              {% icon name="twitter" style="SOLID" width="10" %}
            </a>
          {% endif %}
        </div>
      {% endif %}
    </div>
  </div>
{% else %}

If tag statement

In addition to the if blog_author statement that defines markup that should only render on author listing pages, there is a tag variable that can be used to only render code on a blog topic listing. The example below is a snippet that uses the page title variable to automatically print the tag name at the top of a tag listing page. This snippet could be added to your blog listing code.

HubL
{% if tag %}
    <h3>Posts about {{ page_meta.html_title|split(' | ')|last }}</h3>
{% endif %}

If not simple_list_page statement

Within the for loop, there is an if statement that determines what to render in a simple versus regular listing. A simple listing is a listing of all your posts. The simple listing is not affected by the post limit in Blog Settings and generally just contains links to the most recent 200 blog posts. The simple listing page can be paginated like the normal listing view. The regular listing iterates through the number of posts specified in content settings and paginates accordingly.

The following code is a simplified version of this if statement that defines what should be iterated in a simple listing page. Notice the if statement uses reverse logic; therefore, the else defines the simple listing view.

HubL
{% if not simple_list_page %}
    Iterated post markup for regular listing                            
{% else %}
    <h2 class="post-listing-simple"><a href="{{content.absolute_url}}">{{ content.name }}</a></h2>
{% endif %}

Listing pagination

Blog listing pages have auto-generated pagination. Your listing template can include logic to allow visitors to easily pages through your blog posts. The boilerplate blog accomplishes simple, number pagination through the following markup:

HubL
{% if contents.total_page_count > 1 %}
<div class="blog-pagination">
    {% set page_list = [-2, -1, 0, 1, 2] %}
    {% if contents.total_page_count - current_page_num == 1 %}{% set offset = -1 %}
    {% elif contents.total_page_count - current_page_num == 0 %}{% set offset = -2 %}
    {% elif current_page_num == 2 %}{% set offset = 1 %}
    {% elif current_page_num == 1 %}{% set offset = 2 %}
    {% else %}{% set offset = 0 %}{% endif %}

    <a class="blog-pagination__link blog-pagination__prev-link {{ "blog-pagination__prev-link--disabled" if !last_page_num }}" href="{{ blog_page_link(last_page_num) }}">
    {% icon name="chevron-left" style="SOLID", width="13", no_wrapper=True %}
    Prev
    </a>
    {% for page in page_list %}
    {% set this_page = current_page_num + page + offset %}
    {% if this_page > 0 and this_page <= contents.total_page_count %}
        <a class="blog-pagination__link blog-pagination__number-link {{ "blog-pagination__link--active" if this_page == current_page_num }}" href="{{ blog_page_link(this_page) }}">{{ this_page }}</a>
    {% endif %}
    {% endfor %}
    <a class="blog-pagination__link blog-pagination__next-link {{ "blog-pagination__next-link--disabled" if !next_page_num }}" href="{{ blog_page_link(current_page_num + 1) }}">
    Next
    {% icon name="chevron-right" style="SOLID", width="13", no_wrapper=True %}
    </a>
</div>
{% endif %}

Blog post markup

All blog posts in a blog are generated by a single blog template. Content is a predefined object of data that contains information about the requested blog post. Boilerplate posts are rendered with the following markup:

HubL
<div class="content-wrapper">
  <div class="blog-post">
    <h1>{{ content.name }}</h1>
    <div class="blog-post__meta">
      <a href="{{ blog_author_url(group.id, content.blog_post_author.slug) }}">
        {{ content.blog_post_author.display_name }}
      </a>
      <div class="blog-post__timestamp">
        {{ content.publish_date_localized }}
      </div>
    </div>
    <div class="blog-post__body">
      {{ content.post_body }}
    </div>
    {% if content.tag_list %}
    <div class="blog-post__tags">
      {% icon name="tag" style="SOLID" %}
      {% for tag in content.tag_list %}
        <a class="blog-post__tag-link" href="{{ blog_tag_url(group.id, tag.slug) }}">{{ tag.name }}</a>{% if not loop.last %},{% endif %}
      {% endfor %}
    </div>
    {% endif %}
  </div>
  <div class="blog-comments">
    {% module "blog_comments" path="@hubspot/blog_comments", label="Blog Comments" %}
  </div>
</div>

Blog post author information is also available within the content data.

HubL
<img alt="{{ content.blog_post_author.display_name }}" src="{{ content.blog_post_author.avatar }}"> 
<h3>Written by <a class="author-link" href="{{ blog_author_url(group.id, content.blog_post_author.slug) }}">{{ content.blog_post_author.display_name }}</a></h3>         
<p>{{ content.blog_post_author.bio }}</p>
{% if content.blog_post_author.has_social_profiles %}
    <div class="hs-author-social-section">
        <div class="hs-author-social-links">
            {% if content.blog_post_author.facebook %}
                <a href="{{ content.blog_post_author.facebook }}" target="_blank" class="hs-author-social-link hs-social-facebook">Facebook</a>
            {% endif %}
            {% if content.blog_post_author.linkedin %}
                <a href="{{ content.blog_post_author.linkedin }}" target="_blank" class="hs-author-social-link hs-social-linkedin">LinkedIn</a>
            {% endif %}
            {% if content.blog_post_author.twitter %}
                <a href="{{ content.blog_post_author.twitter }}" target="_blank" class="hs-author-social-link hs-social-twitter">Twitter</a>
            {% endif %}
            {% if content.blog_post_author.google_plus %}
                <a href="{{ content.blog_post_author.google_plus }}?rel=author" target="_blank" class="hs-author-social-link hs-social-google-plus">Google+</a>
            {% endif %}
        </div>
    </div>
{% endif %}