A blog pattern is used to display a collection of blog articles in a grid layout. Each article can include a title, image, description, author(s), and publication date.
The blog pattern supports two content loading strategies:
The pattern offers two layout variants based on the number of articles:
The blog pattern is composed of the following elements:
| Element | Description |
|---|---|
| Title (required) | Title text (using h4 with muted heading style) |
| Articles | 3 or 4 blog article blocks, each containing a 16:9 cover image, title, description, and citation metadata. |
For scenarios where articles need to be loaded asynchronously (e.g., from a blog API), the pattern provides a template mode. This mode creates a template structure that can be populated by external modules like @canonical/latest-news. See the next section for setup instructions.
To use static content instead, see static content.
Using dynamic content mode introduces some slight variations in pattern usage.
articles is assumed to be loaded from an asynchronous data source. The pattern creates .article-image, .article-title, .article-link, .article-excerpt, .article-author, and .article-time objects inside a template element, which should then be populated by JavaScript.template_config.layout ("3-blocks" or "4-blocks")By default, the pattern assumes a 4-block layout, just like in static content mode.
To show a 3-block layout, the template_config.layout parameter must be set to "3-blocks".
To use the blog pattern with the latest-news module, follow the following steps.
Install @canonical/latest-news and configure it, following its usage instructions.
You must use version 2.1.0 or later, as earlier versions do not support the imageClasses option needed for proper article image styling.
Enable template mode in the blog pattern by passing template_config.
This generates the template structure and prepares it for dynamic content.
{{ vf_blog(
title={"text": "Latest from our blog"},
template_config={
"enabled": True,
"layout": "3-blocks", # Must specify layout "3-blocks" or "4-blocks" in template mode.
"template_container_id": "articles",
"template_id": "template"
}
) }}
Populate the template with the latest news articles by calling canonicalLatestNews.fetchLatestNews().
Be sure to match articlesContainerSelector with template_container_id, articleTemplateSelector with template_id, and set limit to "3" or "4".
canonicalLatestNews.fetchLatestNews({
// Make sure you add `p-image-container__image` to ensure the article image receives the correct styling.
imageClasses: ["p-image-container__image"],
// Use `3` with `template_config.layout="3-blocks"` or `4` with `template_config.layout="4-blocks"`
limit: "3",
articlesContainerSelector: "#articles",
articleTemplateSelector: "#template",
excerptLength: 180
});
After following the above steps, the blog pattern will render with articles fetched and populated by the latest-news module.
The pattern can also render static articles passed into the articles parameter.
The layout (3-block or 4-block) is automatically determined based on the number of articles provided.
The default layout displays four articles in a grid. On large screens, the title spans the full width while articles are arranged in a 4-column grid.
When exactly three articles are provided, the pattern automatically adjusts to a 3-column grid layout.
Each article can specify its own cover image. If no image is provided, a fallback image is used.
The vf_blog Jinja macro can be used to generate a blog pattern. The API for the macro is shown below.
| Name | Required? | Type | Default | Description |
|---|---|---|---|---|
title
|
No |
object
|
{}
|
Title configuration with text and optional link_attrs (link attributes)
|
articles
|
No |
Array<object>
|
[]
|
List of article configurations (for static content) |
template_config
|
No |
object
|
{}
|
Dynamic content configuration: - enabled: Enable template mode- template_container_id: Container ID- template_id: Template ID- layout: "3-blocks" or "4-blocks" (required in template mode)
|
padding
|
No |
One of:"default","deep","shallow"
|
"default"
|
Section padding variant |
top_rule_variant
|
No |
One of:"default","muted"
|
"default"
|
Top rule (horizontal line) style |
fallback_image_url
|
No |
string
|
"https://assets.ubuntu.com/v1/94c82a15-blog_fallback_image.png"
|
URL to use for article images when none is provided |
Each article in the articles array accepts the following configuration:
| Name | Required? | Type | Description |
|---|---|---|---|
title
|
Yes |
object
|
Title configuration for the article |
title.text
|
Yes |
string
|
The title text |
title.link_attrs
|
No |
object
|
Link attributes object, see attribute forwarding |
title.attrs
|
No |
object
|
Title attributes object, see attribute forwarding |
title.heading_level
|
No |
integer
|
Heading level applied to title. One of 3 or 4. Default is 3See heading classes |
image
|
No |
object
|
Image configuration for the article |
image.attrs
|
No |
object
|
Image attributes object (src, alt, etc.), see attribute forwarding |
description
|
No |
object
|
Description configuration for the article |
description.text
|
Yes |
string
|
The description text |
description.attrs
|
No |
object
|
Paragraph attributes object, see attribute forwarding |
description.class
|
No |
string
|
Additional classes for the description |
citation
|
No |
object
|
Citation configuration for the article |
citation.authors
|
No |
Array<object>
|
List of author objects |
citation.authors[].text
|
Yes |
string
|
Author name |
citation.authors[].link_attrs
|
No |
object
|
Link attributes object, see attribute forwarding |
citation.date
|
No |
object
|
Date configuration |
citation.date.text
|
Yes |
string
|
Date text |
citation.date.attrs
|
No |
object
|
Time element attributes object, see attribute forwarding |
To import the Blog Jinja macro, copy the following import statement into your Jinja template.
{% from "_macros/vf_blog.jinja" import vf_blog %}
View the building with Jinja macros guide for macro installation instructions.
Since Patterns leverage many other parts of Vanilla in their composition and content, we recommend importing the entirety of Vanilla for full support.