3. TTW Theming II: Creating a custom theme based on Barceloneta

In this section you will:

  • Create a theme by inheriting from the Barceloneta theme.
  • Using the manifest.cfg, register a production CSS file.
  • Use an XInclude to incorporate rules from the Barceloneta theme.
  • Use ?diazo.off=1 to view unthemed versions.
  • Use conditional rules to have a different backend theme from the anonymous visitors theme.

Topics covered:

  • Inheriting from Barceloneta.
  • Diazo rule directives and attributes.
  • Viewing the unthemed version of a Plone item.
  • Creating a visitor-only theme.

Inheriting from Barceloneta

Copying Barceloneta makes your theme heavier and will likely make upgrading more difficult.

The Barceloneta theme provides many assets used by Plone’s utilities that you do not need to duplicate. Additionally new releases of the theme may introduce optimizations or bug fixes. By referencing the Barceloneta rules and styles, instead of copying them, you automatically benefit from any updates to the Barceloneta theme while also keeping your custom theme relatively small.

Exercise 1 - Create a new theme that inherits from Barceloneta

In this exercise we will create a new theme that inherits the Barceloneta rules and styles.

  1. Create a new theme

    ../_images/theming-new-theme.png

    and name it “Custom”

    ../_images/theming-new-theme2.png
  2. In the theming editor, ensure that your new theme contains the files manifest.cfg, rules.xml, index.html (from Barceloneta) and styles.less.

  • manifest.cfg, declaring your theme:
[theme]
title = mytheme
description =
development-css = ++theme++custom/styles.less
production-css = ++theme++custom/styles.css
  • rules.xml, including the Barceloneta rules:
<?xml version="1.0" encoding="UTF-8"?>
<rules
    xmlns="http://namespaces.plone.org/diazo"
    xmlns:css="http://namespaces.plone.org/diazo/css"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xi="http://www.w3.org/2001/XInclude">

  <!-- Import Barceloneta rules -->
  <xi:include href="++theme++barceloneta/rules.xml" />

  <rules css:if-content="#visual-portal-wrapper">
    <!-- Placeholder for your own additional rules -->
  </rules>

</rules>
  • a copy of index.html from Barceloneta (this one cannot be imported or inherited, it must be local to your theme).
  • styles.less, importing Barceloneta styles:
/* Import Barceloneta styles */
@import "++theme++barceloneta/less/barceloneta.plone.less";

/* Customize whatever you want */
@plone-sitenav-bg: pink;
@plone-sitenav-link-hover-bg: darken(pink, 20%);
.plone-nav > li > a {
  color: @plone-text-color;
}

Then generate the styles.css file using styles.less and the “Build CSS” button.

Your theme is ready.

Diazo rule directives and attributes

The Diazo rules file is an XML document containing rules to specify where the content elements (title, footer, main text, etc.) will be located in the targeted theme page. The rules are created using rule directives which have attributes; attribute values are either CSS expressions or XPath expressions.

CSS selector based attributes

It is generally recommended that you use CSS3 selectors to target elements in your content or theme. The CSS3 selectors used by Diazo directives are listed below:

css:theme
Used to select target elements from the theme using CSS3 selectors.
css:content
Used to specify the element that should be taken from the content.
css:theme-children
Used to select the children of matching elements.
css:content-children
Used to identify the children of an element that will be used.

XPath selector based attributes

Depending on complexity of the required selector it is sometimes necessary or more convenient to use XPath selectors instead of CSS selectors. XPath selectors use the unprefixed attributes theme and content. The common XPath selector attributes include:

theme
Used to select target elements from the theme using XPath selectors.
content
Used to specify the element that should be taken from the content using XPath selectors.
theme-children
Used to select the children of matching elements using XPath selectors.
content-children
Used to identify the children of an element that will be used using XPath selectors.

You can also create conditions about the current path using if-path.

Note

For a more comprehensive overview of all the Diazo rule directives and related attributes see: http://docs.diazo.org/en/latest/basic.html#rule-directives

Viewing the unthemed Plone site

When you create your Diazo rules, it is important to know how the content Diazo is receiving from Plone is structured. In order to see a “non-diazoed” version page, just add ?diazo.off=1 at the end of its URL.

Exercise 2 - Viewing the unthemed site

  1. Use diazo.off=1 to view the unthemed version of your site.

  2. Using your browser’s inspector, find out the location/name of some of Plone’s elements. Then try to answer the following:

    What do you think is the difference between “content-core” and “content”? There are several viewlets, how many do you count? Can you identify any portlets, what do you think they are for?

    Solution

    The “content-core” does not include the “title” and “description” while the “content” combines the “title”, “description” and “content-core”.

    Out of the box there are six viewlets (viewlet-above-content, viewlet-above-content-title viewlet-below-content-title, viewlet-above-content-body, viewlet-below-content-body, viewlet-below-content).

    There are a few footer portlets which construct the footer of the site.

Exercise 3 - the <drop> directives

  1. Add a rule that drops the “search section” checkbox from the search box. See the diagram below:

    ../_images/theming-dropping-thesearchsection.png

Conditional attributes

The following attributes can be used to conditionally activate a directive.

css:if-content
Defines a CSS3 expression: if there is an element in the content that matches the expression then activate the directive.
css:if-theme
Defines a CSS3 expression: if there is an element in the theme that matches the expression then activate the directive.
if-content
Defines an XPath expression: if there is an element in the content that matches the expression then activate the directive.
if-theme
Defines an XPath expression: if there is an element in the theme that matches the expression then activate the directive.
if-path
Conditionally activate the current directive based on the current path.

Note

In a previous chapter we discussed the Plone <body> element and how to take advantage of the custom CSS classes associated with it. We were introduced to the attribute css:if-content. Remember that we are able to determine a lot of context related information from the classes, such as:

- the current user role, and its permissions,
- the current content-type and its template,
- the site section and sub section,
- the current subsite (if any).

Here is an example

<body class="template-summary_view
             portaltype-collection
             site-Plone
             section-news
             subsection-aggregator
             icons-on
             thumbs-on
             frontend
             viewpermission-view
             userrole-manager
             userrole-authenticated
             userrole-owner
             plone-toolbar-left
             plone-toolbar-expanded
             plone-toolbar-left-expanded
             pat-plone
             patterns-loaded">

Converting an existing HTML template into an theme

In the Plone “universe” it is not uncommon to convert an existing HTML template into a Diazo theme. Just ensure that when you zip up the source theme that there is a single folder in the root of the zip file. We will explore this in more detail in the next exercise.

Exercise 4 - Convert a HTML template into a Diazo theme

In this exercise we will walk through the process of converting an existing free HTML theme into a Diazo-based Plone theme.

../_images/theming-startbootstrap-newage-theme.png

We’ve selected the free New Age Bootstrap theme. The theme is already packaged in a manner that will work with the theming tool.

Note

When being distributed, Plone themes are packaged as zip files. A theme should be structured such that there is only one top level directory in the root of the zip file. By convention the directory should contain your index.html and supporting files, the supporting files (CSS, javascript and other files) may be in subdirectories.

  1. To get started download a copy of the New Age theme as a zip file. Then upload it to the theme controlpanel.

    Hint

    This is a generic theme, it does not provide the Plone/Diazo specific rules.xml or manifest.cfg file. When you upload the zip file the theming tool generates a rules.xml. In the next steps you will add additional files including a manifest.cfg (perhaps in the future the manifest.cfg will also be generated for you).

    ../_images/theming-uploadzipfile.png

    Select the downloaded zip file.

    ../_images/theming-uploadzipfile2.png
  2. Add a styles.less file and import the Barceloneta styles.

  3. Add a manifest.cfg file, set production-css equal to styles.css

    Note

    Clean Blog is a free Bootstrap theme, the latest version is available on github https://github.com/BlackrockDigital/startbootstrap-clean-blog

    Hint

    You can identify the theme path by reading your browser’s address bar when your theme is open in the theming tool. You’ll need to include the proper theme path in your manifest.cfg, in this case it will most likely be something like ++theme++startbootstrap-new-age-gh-pages

    [theme] title = New Age prefix = ++theme++startbootstrap-new-age-gh-pages/ production-css = ++theme++startbootstrap-new-age-gh-pages/styles.css

  4. Add rules to include the Barceloneta backend utilities

       <?xml version="1.0" encoding="UTF-8"?>
    <rules
        xmlns="http://namespaces.plone.org/diazo"
        xmlns:css="http://namespaces.plone.org/diazo/css"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xi="http://www.w3.org/2001/XInclude">
    
      <!-- Include the backend theme -->
      <xi:include href="++theme++barceloneta/backend.xml" />
    
  5. Add rules to include content, add site structure, drop unneeded elements, customize the menu.

    Warning

    Look out for inline styles in this theme (i.e. the use of the style attribute on a tag). This is especially problematic with background images set with relative paths. The two issues that result are:

    • the relative path does not translate properly in the context of the theme;
    • it can be tricky to dynamically replace background images provided by inline styles.

Creating a visitor-only theme - conditionally enabling Barceloneta

Sometimes it is more convenient for your website administrators to use Barceloneta, Plone’s default theme. Other visitors would see a completely different layout provided by your custom theme. To achieve this you will need to associate your visitor theme rules with an expression like css:if-content="body.userrole-anonymous". For rules that will affect logged-in users you can use the expression css:if-content="body.:not(userrole-anonymous)".

Once you’ve combined the expressions above with the right Diazo rules you will be able to present an anonymous visitor with a specific HTML theme while presenting the Barceloneta theme to logged-in users.

Warning

The Barceloneta ++theme++barceloneta/rules.xml expects the Barceloneta index.html to reside locally in your current theme. To avoid conflict and to accomodate the inherited Barceloneta, ensure that your theme file has a different name such as front.html.

Exercise 5 - Convert the theme to be a visitor-only theme

In this exercise we will alter our theme from the previous exercise to make it into a visitor-only theme.

  1. Update the rules.xml file to include Barceloneta rules.

    Hint

    Use <xi:include href="++theme++barceloneta/rules.xml" />

  2. Add conditional rules to rules.xml so that the new theme is only shown to anonymous users, rename the theme’s index.html to front.html and add a copy of the Barceloneta index.html.

    Hint

    Copy the contents of the Barceloneta index.html file then add it to the theme as the new index.html file.

    Change rules.xml to look similar to this:

    <?xml version="1.0" encoding="UTF-8"?>
    <rules
        xmlns="http://namespaces.plone.org/diazo"
        xmlns:css="http://namespaces.plone.org/diazo/css"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:xi="http://www.w3.org/2001/XInclude">
    
      <notheme css:if-not-content="#visual-portal-wrapper" />
    
      <rules css:if-content="body:not(.userrole-anonymous)">
        <!-- Import Barceloneta rules -->
        <xi:include href="++theme++barceloneta/rules.xml" />
      </rules>
    
      <rules css:if-content="body.userrole-anonymous">
        <theme href="front.html" />
        <replace css:theme-children=".intro header h2" css:content-children=".documentFirstHeading" />
        <replace css:theme-children=".summary" css:content-children=".documentDescription" />
        <replace css:theme-children=".preamble" css:content-children="#content-core" />
      </rules>
    </rules>