Contact Us
Python BlogDjango BlogBig DataSearch for Kubernetes AWS BlogCloud Services



Flexible Tile Layouts in Plone Using Mosaic

May 1, 2020

Mosaic ( provides the ability for Plone site editors to build custom layouts without having to edit templates or build custom views.

As a developer, you can construct the building blocks (tiles) that are available to the editors in the site. But the process for creating new tiles isn’t very straightforward.

For complex custom tiles (tiles with a schema and logic), these are the pieces you need:

Here's an example of how you'll create an Accordion Tile in Plone 5.2 running on Python 3. This tile will be using Bootstrap’s Collapse component so that a block heading is displayed with or without a background image. Clicking on the block heading will expand the tile to show rich text content:

Note: this post was written with = 2.2.1 and plone.jsonserializer = 0.9.9

I recommend starting with the ZCML:

<include package="plone.tiles" file="meta.zcml" />


The name will be referenced later in the registry.xml. class and schema point to the pieces you will set up next.

You'll build the tile’s schema. In

from import _PMF as _
from import RichText
from import RelatedItemsFieldWidget
from plone.autoform import directives as form
from plone.supermodel.model import Schema
from zope import schema

class IAccordion(Schema):
    title = schema.TextLine(
        title=_(u"Accordion title"),
    body = RichText(
        title=_(u"Accordion body"),
        description=_(u"Text to appear within the accordion panel"),
    image = schema.Choice(
        title=_(u"Select an existing image"),
            'recentlyUsed': True,
            'selectableTypes': ['Image'],

The image field uses the RelatedItemsFieldWidget, which will allow you to select an image from the Plone site.

Then the class:

from plone.i18n.normalizer.interfaces import IIDNormalizer
from plone.tiles import Tile
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.component import getUtility

class Accordion(Tile):
    template = ViewPageTemplateFile('templates/')

    def __call__(self):
        return self.template()

    def update(self):
        self.title ='title', '')
        self.body ='body', '')
        self.tile_id = getUtility(IIDNormalizer).normalize(self.title)
        img_uid ='image', None)
        if img_uid is None:
            self.image_url = None
            self.image_url = api.content.get(UID=img_uid).absolute_url()

The update() is doing a couple custom things. One is to create a custom tile_id that will be used by the JS for expanding and collapsing the tiles. (Note, you can also use the tile’s id for this). Second is to get the image’s url by using the UID that is stored in the field.

Now that the building blocks are in place, you'll need to make the tile addable in a Mosaic layout. Add the following into your registry.xml

<?xml version="1.0"?>
  <record name="">
    <value purge="false">
  <records prefix=""
    <value key="name">mysite.accordion</value>
    <value key="label">Accordion</value>
    <value key="category">advanced</value>
    <value key="tile_type">app</value>
    <value key="default_value"></value>
    <value key="read_only">false</value>
    <value key="settings">true</value>
    <value key="favorite">true</value>
    <value key="rich_text">false</value>
    <value key="weight">10</value>

Some important pieces to note here:

Make sure to import the registry settings after making these changes.

Finally, you can put the template together as follows:

<div tal:define="image view/image_url;
                 noimage python:not image and 'noimage' or '';
                 id view/tile_id" 
        class="accordion-block ${noimage}">
    <div class="panel-group" aria-multiselectable="true" role="tablist">
        <div class="panel panel-default">
            <a aria-controls="collapse-${id}" aria-expanded="false" class="collapsed"
               data-toggle="collapse" href="#collapse-${id}" role="button">
                <div class="panel-heading" id="heading-${id}" role="tab" 
                        style="background-image: url('${image}');">
                    <h4 class="panel-title">
                    <span tal:replace="view/title" />
                    <span class="fa fa-plus right" aria-hidden="true"></span>
                    <span class="fa fa-minus right" aria-hidden="true"></span>
            <div aria-labelledby="heading-${id}" class="panel-collapse collapse" id="collapse-${id}" role="tabpanel">
                <div class="panel-body">
                    <div tal:replace="structure view/body/output" />

Two very important elements here, which can be easy to miss, are the html and body tags! Mosaic will not display the template on the layout edit screen if these are missing.

This template code is made to work with Bootstrap’s Collapse component. Make sure to import the Bootstrap code, or wire up your own styles and interactions.

With all these pieces in place, you should have an addable Accordion tile in your Mosaic pages!

Tell us about the goals you’re trying to accomplish.
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.