Partials

Partial templates are a powerful concept that permit site architects to divide a design up into sections, and then freely rearrange and reuse those designs throughout the site.

Most pages that can be divided up into discrete sections (such as a header, content area – or collection of various content areas in order, and a footer) should be implemented using partials.

Setup

The partial loop

Partials are rendered by a partial loop that exists in the base Jinja template (/views/base.html). The partial loop resembles the following (though, your actual partial loop should have more logic to control the conditional display of partials).

/views/base.html
{% set partials = doc.partials or doc.collection.partials %}
{% for partial in partials if partial.partial %}
  {% set template = '/views/partials/{}.html'.format(partial.partial) %}
  {% include template with context %}
{% endfor %}

Templates

Create templates in the /views/partials directory.

/views/partials/hero.html
<div class="hero {{partial.class}}">
  {% if partial.title %}
    <div class="hero__title">
      {{partial.title}}
    </div>
  {% endif %}
  {% if partial.body %}
    <div class="hero__body">
      {{partial.body}}
    </div>
  {% endif %}
</div>
/views/partials/person.html
<div class="person {{partial.class}}">
  <div class="person__name">
    <div class="person__name__avatar">
      <img src="{{partial.avatar.url.path}}">
    </div>
    <div class="person__name__title">
      {{partial.title}}
    </div>
  </div>
</div>

Content

Add structured content to your content document's front matter.

/content/pages/index.yaml
$view: /views/base.html

partials:

- partial: hero
  title: Welcome
  body: This website's body copy is here.

- partial: person
  title: Scott
  avatar: !g.static /source/images/home/scott.png

- partial: person
  title: Adelaide
  avatar: !g.static /source/images/home/adelaide.png

- partial: person
  title: Steven
  avatar: !g.static /source/images/home/steven.png

In this example, the index page renders a hero, and three person partials. The hero, and person templates can subsequently be reused on other pages.

If the same content is reused, put partial content documents into the /content/partials folder, and then import them into pages.

/content/partials/header.yaml
partial: header
logo:
  title: My Site
  image: !g.static /source/images/logo.png
nav:
- doc: !g.doc /content/pages/index.yaml
- doc: !g.doc /content/pages/about.yaml
- url: https://www.github.com/grow/grow
/content/pages/about.yaml
partials:
- !g.yaml /content/partials/header.yaml

For content which you know is on every page, modify the partial loop and add rendering of an additional set of partials either before or after. This is typically reserved for the global header and footer.

{% with partial = g.doc('/content/partials/header.yaml') %}
  {% if partial.partial %}
    {% set template = '/views/partials/{}.html'.format(partial.partial) %}
    {% include template with context %}
  {% endif %}
{% endwith %}

{# ... the partial loop ... #}

{% with partial = g.doc('/content/partials/footer.yaml') %}
  {% if partial.partial %}
    {% set template = '/views/partials/{}.html'.format(partial.partial) %}
    {% include template with context %}
  {% endif %}
{% endwith %}

Styles

Create corresponding styles encapsulated into a single Sass file.

/source/sass/partials/_hero.sass
.hero
  margin: 20px 0

.hero__title
  +font-h2

.hero__body
  +font-body

Reuse

Partials can be easily reused across pages, making it easy to implement a modular design or design system. If several pages all leverage the same or similar modules, the selective application and mixing and matching of partials make it possible to easily build a large, templatized site.

/content/pages/about.yaml
partials:

- partial: hero
  ...
- partial: columns
  ...
- partial: columns
  ...
- partial: carousel
  ...
- partial: people
  ...
/content/pages/products.yaml
partials:

- partial: hero
  ...
- partial: carousel
  ...
- partial: columns
  ...
- partial: gallery
  ...

Avoid duplicated partials

Avoid duplicating a partial when a variation can be easily created through obvious configuration or by adding a simple class.

For example, instead of creating two partials (i.e. two-columns and three-columns), create one partials column and automatically infer the number of columns based on the data.

/content/pages/index.yaml
...
- partial: columns
  columns:
  - body: Column 1.
  - body: Column 2.
  - body: Column 3.
...
/views/partials/columns.html
<div class="columns {{partial.class}}">
  {% for column in columns %}
    <div class="columns__column">
      <div class="columns__column__body">
        {{column.body}}
      </div>
    </div>
  {% endfor %}
</div>

Another way to create variations is to add classes. For example, if you wanted to create a variation of the columns partial where the first class is large, leverage the top-level class key.

/content/pages/index.yaml
...
- partial: columns
  class: columns--large
...
/source/sass/partials/_columns.sass
.columns

.columns--large
  .columns__column
    font-size: huge

Naming

Guidelines

Choose an obvious, memorable name.

Partials should be named in a concise yet descriptive way. Naming is hard – be generic, but not too generic. For example, if a design has a commonly-used "top" or "hero" module, name it hero. Or a commonly used column module, name it columns.

Avoid coupling the partial's name to a specific page, unless the partial's design cannot be applied elsewhere. If there is a slight variation between two pages, use a generic name. If a module is unique to a page and will always be for the forseeable future, you may prefix the partial's name with the page's basename.

If using the specific page's name would help you or others remember and refer to the partial, disregard the previous rule. For example, if a new column module is created for the "foo page", and if the design is henceforth referred to as the "foo columns", just name the partial "foo columns".

Avoid names that include "count numbers". For example, a two-column partial may eventually grow to be an x-column partial.

Example names

basement Also known as a "fat footer", a basement usually has navigational links for accessibility/SEO purposes and appears above or below a footer.
chapter A single instance of a "chapter" (a series of icons, eyebrow, title, body copy, buttons, etc.)
header Your website's global header.
footer Your website's global footer.
hero The main module that appears front and center, above the fold.

Conditional rendering

In the partial loop example earlier, a partial can be disabled by setting the top-level partial key to null. This permits use of Grow's YAML tagging to conditionally render partials (such as varying by locale or environment).

/content/pages/index.yaml
partials:

# Not displayed in the `prod` deployment.
- partial: columns
  [email protected]: ~
  ...

# Not displayed in the `ja_JP` locale.
- partial: columns
  partial@ja_JP: ~
  ...

# Only displayed in the `fr_FR` locale.
- partial@fr_FR: columns
  ...