In Plone versions 4.3 and higher you
can edit your website theme through web browser in Plone’s site setup control panel.
Only HTML, CSS and little XML knowledge needed as the prerequisitements.
This guide explains how to use this feature of Plone.

A “theme” makes a website (in this case, one powered by Plone) take on a
particular look and feel.

Diazo (formerly known as XDV) is a technology that can be used to theme
websites. It is not specific to Plone per se, but has been created by the Plone
community and, as of Plone 4.3, provides the default way to apply a theme to a
Plone site. You can learn more about Diazo at http://diazo.org.

Diazo themes may be a little different to themes you have created in other
systems, and indeed to themes you may have created for earlier versions of
Plone. A Diazo theme is really about transforming some content - in this case
the output from “vanilla” Plone - into a different set of HTML markup by
applying a set of rules to combine a static HTML mock-up of the end result you
want with the dynamic content coming from Plone.

In comparison, the previous way to theme a Plone site (like the way many other
content management systems are themed) relies on selectively overriding the
templates and scripts that Plone uses to build a page with custom versions
that produce different HTML markup. The latter approach can be more powerful,
certainly, but also requires much deeper knowledge of Plone’s internals and
command of server-side technologies such as Zope Page Templates and even Python.
Diazo themes, by contrast, are easy to understand for web designers and non-
developers alike.

A Diazo theme consists of three elements:

One or more HTML mockups, also referred to as theme files, that represent
the desired look and feel.

These will contain placeholders for content that is to be provided by the
Plone content management system. Mockups usually reference CSS, JavaScript
and image files by relative path. The most common way to create a theme is to
use desktop software like Dreamweaver or a text editor to create the relevant
markup, styles and scripts, and test the theme locally in a web browser.

The content that is being themed. In this case, that is the output from
Plone.

A rules file, which defines how the placeholders in the theme (i.e. the
HTML mockup) should be replaced by relevant markup in the content.

The rules file uses XML syntax (similar to HTML). Here is a very simple
example:

Here, we are replacing the contents (child nodes) of a placeholder element
with HTML id main in the theme file (theme.html, found in the same
directory as the rules.xml file, as referenced by the <theme /> rule)
with the contents (children) of the element with the HTML id content in
the markup generated by Plone.

When this theme is applied, the result will look very much like the static
HTML file theme.html (and its referenced CSS, JavaScript and image
files), except the placeholder that is identified by the node in the theme
with id main will be filled by Plone’s main content area.

Plone ships with an example theme called, appropriately, Example theme, which
uses the venerable Twitter Bootstrap
to build a simple yet functional theme exposing most of Plone’s core
functionality. You are advised to study it - in particular the rules.xml
file - to learn more about how Diazo themes work.

After installation of the Diazo theme support package in a Plone site, the
Theming control panel will appear in Plone’s Site setup.

The main tab of this control panel, Themes, will show all available themes,
with buttons to activate/deactivate, modify, copy or delete each, as well as
buttons to create new themes or bring up this help text.

Click on a theme preview image to open a preview of that theme in a new tab
or window. The preview is navigable, but form submissions and some advanced
features will not work.

To apply an existing theme, simply click the Activate button underneath the
theme preview. The currently active theme will be highlighted in yellow. If
you deactivate the currently active theme, no Diazo theme will be applied, i.e.
“vanilla” Plone theming will apply.

Note: The Theming control panel is never theemd, ensuring that you can
always deactivate an errant theme that could render the control panel unusable.
Thus, you may not see any difference immediately after enabling a theme. Simply
navigate to another page in the Plone site, though, and you should see the
theme applied.

Click the New theme button at the top of the Themes tab in the Theming
control panel and enter a title and description in the form that appears.
A bare-bones theme will be created, and you will be taken to the Modify
theme screen (see below), where you can edit or create theme and rules files.

Click the Copy button underneath any existing theme and enter a title and
description in the form that appears. A new theme will be created as a copy
of the existing theme, and you will be taken to the Modify theme (see
below), where you can edit or create theme and rules files.

Themes can be distributed as Zip files, containing the HTML mockup and rules
file. To download an existing theme, click the Download button underneath the
theme on the Themes tab of the Theming control panel.

To upload such a Zip file into another site, use the Upload Zip file button
on the Themes tab of the Theming control panel. You can choose whether or
not to replace any existing theme with the same name (based on the name of the
top-level directory contained within the Zip file).

You can also upload a Zip file of a static HTML mockup that does not contain a
rules file, such as a design provided by a Plone-agnostic web designer.

In this case, a basic rules.xml file will be added for you to start building
up a theme from using the Modify theme screen (see below). The
generated rules file will assume the main HTML mockup file is called
index.html, but you can change this in rules.xml.

Once you have successfully uploaded a theme Zip file, you will be taken to the
Modify theme screen (see below), where you can edit or create theme files.

Hint: If you get an error message like “The uploaded file does not contain
a valid theme archive”, this usually means that you have uploaded a Zip file
that contains multiple files and folders, rather than a single top level
folder with all the theme resources in it. This could happen if you compressed
a theme or HTML mockup by adding its files and folders directly a Zip archive,
rather than compressing the directory in which they were found. To fix this,
simply unzip the archive on your computer into a new directory, move up a level,
and compress this directory on its own into a new Zip file, which you can then
upload.

You can modify a theme by clicking Modify theme underneath a theme in the
Themes tab of the Theming control panel. This screen is also launched
automatically when you create or upload a new theme.

Note: Only themes created or uploaded through the Theming control panel can
be modified through Plone. Themes installed by third-party add-ons or
distributed on the filesystem cannot, although changes made on the filesystem
will be reflected immediately if Zope is running in debug mode. To modify a
filesystem theme, you can copy it to a new in-Plone theme by clicking the Copy
button underneath the theme in the Theming control panel.

The Modify theme screen initially shows a file manager, with a file tree on
the left and an editor on the right. Click on a file in the file tree to open an
editor or preview: HTML, CSS, JavaScript and other text files can be edited
directly through the editor. Other files (e.g. images) will be rendered as a
preview.

Note: The advanced editor with syntax highlighting is not available in
Microsoft Internet Explorer.

Click New folder to create a new folder. You can also right-click on a folder
in the file tree to bring up this action.

Click New file to create a new text file. You can also right-click on a folder
in the file tree to bring up this action.

Click Upload file to upload a file from your computer. You can also right-
click on a folder in the file tree to bring up this action.

Click Preview theme to preview the theme as it will be applied with the mockup
and rules as currently saved. The preview is navigable, but forms and certain
advanced features will not work.

To save the file currently being edited, click the Save file button, or use
the keyboard shortcut Ctrl+S (Windows/Linux) or Cmd+S (Mac).

To rename or delete a file or folder, right-click on it in the file tree and
select the appropriate action.

The theme inspector provides an advanced interface for discovering and building
up the rules of a Diazo theme. It can be launched by clicking the Show
inspectors button on the Modify theme screen for in-Plone themes, or by
clicking the Inspect theme button underneath a filesystem theme on the
Themes tab of the Theming control panel.

The theme inspector consists of two panels:

The HTML mockup. If there are several HTML files in the theme, you can switch
between them using the drop-down list underneath the HTML mockup panel.

The Unthemed content. This shows Plone without any theme applied.

Either panel can be maximised by clicking the arrows icon at the top right of
either.

The HTML mockups and Unthemed content panels can be switch to source view,
showing their underlying HTML markup, by clicking the tags icon at the top right
of either.

As you hover over elements in the HTML mockup or Unthemed content panels,
you will see:

An outline showing the element under the cursor.

A CSS or XPath selector in the status bar at the bottom if the panel which
would uniquely identify this element in a Diazo rule.

Click on an element or press Enter whilst hovering oveer an element to
select it. The most recently selected element in each panel is shown in the
bottom right of the relevant status bar.

Press Esc whilst hovering over an element to select its parent. This is
useful when trying to select “invisible” container elements. Press Enter
to save this selection.

The contents of the HTML mockup or (more commonly) Unthemed content panels
can be navigated, for example to get to a content page that requires specific
theme rules, by disabling the inspector. Use the toggle switches at the bottom
right of the relevant panel to enable or disable the selector.

Click the Build rule button near the top of the Modify theme or Inspect
theme screen to launch an interactive rule building wizard. You will be asked
which type of rule to build, and then prompted to select the relevant elements
in the HTML mockup and/or Unthemed content panels as required. By default,
this will use any saved selections, unless you untick the Use selected
elements box on the first page if the wizard.

Once the wizard completes, you will be shown the generated rule. You can edit
this if you wish. If you click Insert, the newly generated rule will be
inserted into the rules.xml editor at or near your current cursor position.
You can move it around or edit it further as you wish.

Click Preview theme to preview the theme in a new tab or window. Don’t forget
to save the rules.xml file if you have made changes.

Note: In readonly mode, you can build rules and inspect the HTML mockup and
theme, but not change the rules.xml file. In this case, the Insert button
of the rule builder (see below) will not be available either.

Note: The ability to insert rules from the Build rule wizard are not
available in Microsoft Internet Explorer, although you will be given the option
to copy the rule to the clipboard when using this browser.

The Theming control panel also contains a tab named Advanced settings. Here
be dragons.

The Advanced setings tab is divided into two areas. The first, Theme
details, contains the underlying settings that are modified when a theme is
applied from the Themes control panel. These are:

Whether or not Diazo themes are enabled at all.

The path to the rules file, conventionally called rules.xml, either
relative to the Plone site root or as an absolute path to an external
server.

The prefix to apply when turning relative paths in themes (e.g. references to
images in an <img /> tag’s src attribute) into absolute ones at
rendering time.

The HTML DOCTYPE to apply to the rendered output, if different to the default
XHTML 1.0 Transitional.

Whether or not to allow theme resources (likes rules.xml) to be read from
the network. Disabling this gives a modest performance boost.

A list of host names for which a theme is never applied. Most commonly, this
contains 127.0.0.1, allowing you to view an unthemed site through
http://127.0.0.1:8080 and a themed one at http://localhost:8080 during
development, say.

A list of theme parameters and the TALES expressions to generate them
(see below).

The second, Theme base, controls the presentation of the unthemed content, and
apply even if no Diazo theme is being applied. These are the settings that used
to be found in the Themes control panel in previous versions of Plone.

To build and test a theme, you must first create a static HTML mockup of the
look and feel you want, and then build a rules file to describe how Plone’s
content maps to the placeholders in this mockup.

The mockup can be created anywhere using whatever tool you feel most comfortable
building web pages in. To simplify integration with Plone, you are recommended
to make sure it uses relative links for resources like CSS, JavaScript and image
files, so that it will render properly when opened in a web browser from a local
file. Plone will convert these relative links to the appropriate absolute paths
automatically, ensuring the theme works no matter which URL the user is viewing
when the theme is applied to a Plone site.

There are several ways to get the theme into Plone:

On the filesystem

If you used an installer or a standard “buildout” to set up your Plone site,
you should have a directory called resources in the root of your Plone
installation (this is created using the resources option to the buildout
recipe plone.recipe.zope2instance. See
http://pypi.python.org/pypi/plone.recipe.zope2instance for more details.)

You can find (or create) a theme directory inside this directory, which is
used to contain themes. Each theme needs its own directory with a unique name.
Create one (e.g. resources/theme/mytheme) and put your HTML files and any
references resources inside this directory. You can use subdirectories if you
wish, but you are recommended to keep the basic theme HTML files at the top
of the theme directory.

You will also need a rules file called rules.xml inside this directory. If
you haven’t got one yet, start with an empty one:

Provided you are running Zope in debug mode (e.g. you start it up with
bin/instance fg), changes to the theme and rules should take effect
immediately. You can preview or enable the theme through the Themes control
panel, and then iteratively modify the rules.xml file or the theme mockup
as you wish.

Through the web

If you prefer (or do not have filesystem access), you can create themes entirely
through the Plone control panel, either by duplicating an existing theme, or
starting from scratch with a near-empty theme.

See the instructions on using the control panel above for more details.

Once a theme has been created, you can modify it through the Theming
control panel. See above for more details.

As a zip file

Themes can be downloaded from Plone as Zip files, which can then be uploaded
into other sites.

See the instructions on using the control panel above for more details.

In fact, you can create valid theme zip archives by compressing a theme
directory on the filesystem using a standard compression tool such as 7-Zip or
Winzip (for Windows) or the built-in Compress action in the Mac OS X Finder.
Just make sure you compress exactly one folder that contains all the theme files
and the rules.xml file. (Do not compress the contents of the folder
directly: when unpacked, the zip file should produce exactly one folder which
in turn contains all the relevant files).

In a Python package (programmers only)

If you are creating a Python package containing Plone customisations that you
intend to install into your site, you can let it register a theme for
installation into the site.

To do this, place a directory called e.g. theme at the top of the package,
next to the Zope configure.zcml file, and add a <plone:static />
declaration to the configure.zcml file:

It is possible to give additional information about a theme by placing a file
called manifest.cfg next to the rules.xml file at the top of a theme
directory.

This file may look like this:

[theme]
title = My theme
description = A test theme

As shown here, the manifest file can be used to provide a more user friendly
title and a longer description for the theme, for use in the control panel.
Only the [theme] header is required - all other keys are optional.

You can also set:

rules = http://example.org/myrules.xml

to use a different rule file name than rules.xml (you should provide a URL
or relative path).

To change the absolute path prefix (see Advanced settings), use:

prefix = /some/prefix

To employ a DOCTYPE in the themed content other than XHTML 1.0
Transitional, add e.g.:

doctype = <!DOCTYPE html>

To provide a user-friendly preview of your theme in the Theming control panel,
add:

preview = preview.png

Here, preview.png is an image file relative to the location of the
manifest.cfg file.

Extensions to the Diazo theming engine can add support for additional blocks of
configurable parameters.

Each rule is represented by an XML tag that operates on one or more HTML
elements in the content and/or theme. The elements to operate on are indicated
using attributes of the rules known as selectors.

The easiest way to select elements is to use a CSS expression selector, such as
css:content="#content" or css:theme="#main .content". Any valid CSS 3
expression (including pseudo-selectors like :first-child may be used.

The standard selectors, css:theme and css:content, operate on the
element(s) that are matched. If you want to operate on the children of the
matched element instead, use css:theme-children="..." or
css:content-children="..." instead.

If you cannot construct a suitable CSS 3 expression, you can use XPath
expressions such as content="/head/link" or theme="//div[@id='main']"
(note the lack of a css: prefix when using XPath expressions). The two
approaches are equivalent, and you can mix and match freely, but you cannot
have e.g. both a css:theme and a theme attribute on a single rule. To
operate on children of a node selected with an XPath expression, use
theme-children="..." or content-children="...".

By default, every rule is executed, though rules that do not match any elements
will of course do nothing. You can make a rule, set of rules or theme reference
(see below) conditional upon an element appearing in the content by adding an
attribute to the rule like css:if-content="#some-element" (to use an XPath
expression instead, drop the css: prefix). If no elements match the
expression, the rule is ignored.

Tip: if a <replace /> rule matches an element in the theme but not in
the content, the theme node will be dropped (replaced with nothing). If you do
not want this behavior and you are unsure if the content will contain the
relevant element(s), you can use css:if-content conditional rule. Since
this is a common scenario, there is a shortcut: css:if-content="" means
“use the expression from the css:content attribute”.

Similarly, you can construct a condition based on the path of the current
request by using an attribute like if-path="/news" (note that there is no
css:if-path ). If the path starts with a slash, it will match from the root
of the Plone site. If it ends with a slash, it will match to the end of the URL.
You can set an absolute path by using a leading and a trailing slash.

Finally, you can use arbitrary XPath expressions against any defined variable
using an attribute like if="$host = 'localhost'" . By default, the variables
url , scheme , host and base are available, representing the
current URL. Themes may define additional variables in their manifests.

Choose the theme file to be used. The href is a path relative to the rules
file. If multiple <theme /> elements are present, at most one may be given
without a condition. The first theme with a condition that is true will be used,
with the unconditional theme, if any, used as a fallback.

<notheme /> can be used to specify a condition under which no theme
should be used. <notheme /> takes precedence over <theme />.

Tip: To ensure you do not accidentally style non-Plone pages, add a
condition like css:if-content="#visual-portal-wrapper" to the last theme
listed, and do not have any unconditional themes.

Inserts the matched element(s) from the content before or after the matched
element(s) in the theme. By using theme-children , you can insert the
matched content element(s) as the first (prepend) or last (append) element(s)
inside the matched theme element(s).

Remove element(s) from the theme or content. Note that unlike most other rules,
a <drop /> or <strip /> rule can operate on the theme or
content , but not both. <drop /> removes the matched element(s) and
any children, whereas <strip /> removes the matched element(s), but leaves
any children in place.

<drop /> may be given a whitespace-separated list of attributes to
drop. In this case, the matched element(s) themselves will not be removed. Use
attributes="*" to drop all attributes.

These rules operate on attributes. <merge /> will add the contents of the
named attribute(s) in the theme to the value(s) of any existing attributes with
the same name(s) in the content, separated by whitespace. It is mainly used to
merge CSS classes.

<copy /> will copy attributes from the matched element(s) in the content
to the matched element(s) in the theme, fully replacing any attributes with
the same name that may already be in the theme.

The attributes attribute can contain a whitespace-separated list of
attributes, or the special value * to operate on all attributes of the
matched element.

Rules may operate on content that is fetched from somewhere other than the
current page being rendered by Plone, by using the href attribute to specify
a path of a resource relative to the root of the Plone site:

<!-- Pull in extra navigation from a browser view on the Plone site root -->
<after
css:theme-children="#leftnav"
css:content=".navitem"
href="/@@extra-nav"
/>

It is possible to pass arbitrary parameters to your theme, which can be
referenced as variables in XPath expressions. Parameters can be set in Plone’s
theming control panel, and may be imported from a manifest.cfg file.

For example, you could have a parameter mode that could be set to the
string live or test. In your rules, you could do something like this
to insert a warning when you are on the test server:

The path segment of the inbound URL. This will not include any virtual
hosting tokens, i.e. it is the path the end user sees.

base

The Zope base url (the BASE1 request variable).

You can add additional parameters through the control panel, using TALES
expressions. Parameters are listed on the Advanced tab, one per line, in
the form <name> = <expression>.

For example, if you want to avoid theming any pages that are loaded by Plone’s
overlays, you can make use of the ajax_load request parameter that they
set. Your rules file might include:

<notheme if="$ajax_load" />

To add this parameter as well as the mode parameter outlined earlier, you
could add the following in the control panel:

ajax_load = python: request.form.get('ajax_load')
mode = string: test

The right hand side is a TALES expression. It must evaluate to a string,
integer, float, boolean or None: lists, dicts and objects are not
supported. python:, string: and path expressions work as they do
in Zope Page Templates.

The following variables are available when constructing these TALES expressions:

context

The context of the current request, usually a content object.

request

The current request.

portal

The portal root object.

context_state

The @@plone_context_state view, from which you can look up additional
values such as the context’s URL or default view.

portal_state

The @@plone_portal_state view, form which you can look up additional
values such as the navigation root URL or whether or not the current
user is logged in.

See plone.app.layout for details about the @@plone_context_state and
@@plone_portal_state views.

Theme parameters are usually integral to a theme, and will therefore be set
based on a theme’s manifest when a theme is imported or enabled. This is done
using the [theme:parameters] section in the manifest.cfg file. For
example:

When Zope is in development mode (e.g. running in the foreground in a console
with bin/instance fg), the theme will be re-compiled on each request. In
non-development mode, it is compiled once when first accessed, and then only re-
compiled the control panel values are changed.

Also, in development mode, it is possible to temporarily disable the theme
by appending a query string parameter diazo.off=1. For example:

http://localhost:8080/Plone/some-page?diazo.off=1

Finally, you can get an overlay containing your rules, annotated with how
many times the conditions matched both the theme and the document. Green
means the condition matched, red means it didn’t. The entire rule tag will
be green (i.e. it had an effect) so long as all conditions within are green.

Plone’s “resource registries”, including the portal_css tool, can be used
to manage CSS stylesheets. This offers several advantages over simply linking
to your stylesheets in the template, such as:

Detailed control over the ordering of stylesheets

Merging of stylesheets to reduce the number of downloads required to render
your page

On-the-fly stylesheet compression (e.g. whitespace removal)

The ability to include or exclude a stylesheet based on an expression

It is usually desirable (and sometimes completely necessary) to leave the
theme file untouched, but you can still use portal_css to manage your
stylesheets. The trick is to:

Register your theme’s styles with Plone’s portal_css tool (this is
normally best done when you ship a theme in a Python package - there is
currently no way to automate this for a theme imported from a Zip file or
created through the web)

There is one important caveat, however. Your stylesheet may include relative
URL references of the following form:

background-image: url(../images/bg.jpg);

If your stylesheet lives in a resource directory (e.g. it is registered in
portal_css with the id ++theme++my.theme/css/styles.css), this
will work fine so long as the registry (and Zope) is in debug mode. The
relative URL will be resolved by the browser to
++theme++my.theme/images/bg.jpg.

However, you may find that the relative URL breaks when the registry is put
into production mode. This is because resource merging also changes the URL
of the stylesheet to be something like:

/plone-site/portal_css/Suburst+Theme/merged-cachekey-1234.css

To correct for this, you must set the applyPrefix flag to true when
installing your CSS resource using cssregistry.xml. There is a
corresponding flag in the portal_css user interface.

It is sometimes useful to show some of Plone’s CSS in the styled site. You
can achieve this by using an Diazo <after /> rule or similar to copy the
CSS from Plone’s generated <head /> into the theme. You can use the
portal_css tool to turn off the style sheets you do not want.

However, if you also want the site to be usable in non-themed mode (e.g. on a
separate URL), you may want to have a larger set of styles enabled when Diazo
is not used. To make this easier, you can use the following expressions as
conditions in the portal_css tool (and portal_javascripts if relevant),
in portal_actions, in page templates, and other places that use TAL
expression syntax:

request/HTTP_X_THEME_ENABLED | nothing

This expression will return True if Diazo is currently enabled, in which case
an HTTP header “X-Theme-Enabled” will be set.

If you later deploy the theme to a fronting web server such as nginx, you can
set the same request header there to get the same effect, even if
plone.app.theming is uninstalled.

1.1a2 (2012-08-30)

Protect the control panel with a specific permission so it can be
delegated.
[davisagli]

Advise defining ajax_load as request.form.get('ajax_load') in
manifest.cfg. For instance, the login_form has an hidden empty
ajax_load input, which would give an unthemed page after submitting
the form.
[maurits]

Change theme editor page templates to use main_template rather than
prefs_main_template to avoid inserting CSS and JavaScript too early
under plonetheme.classic.
[danjacka]

1.1a1 (2012-08-08)

Replace the stock “Themes” control panel with a renamed “Theming” control
panel, which incorporates the former’s settings under its “Advanced” tab.
[optilude]

1.0b9 - 2011-11-02

1.0b8 - 2011-07-04

Evaluate theme parameters regardless of whether there is a valid context or
not (e.g. when templating a 404 page).
[lentinj]

1.0b7 - 2011-06-12

Moved the views and overrides plugins out into a separate package
plone.app.themingplugins. If you want to use those features, you need
to install that package in your buildout. Themes attempting to register
views or overrides in environments where plone.app.themingplugins is not
installed will install, but views and overrides will not take effect.
[optilude]

1.0b6 - 2011-06-08

Support for setting arbitrary Doctypes.
[elro]

Upgrade step to update plone.app.registry configuration.
[elro]

Fixed plugin initialization when applying a theme.
[maurits]

Query the resource directory using the ‘currentTheme’ name instead
of the Theme object (updating the control panel was broken).
[maurits]

Fix zip import (plugin initialization was broken.)
[elro]

1.0b5 - 2011-05-29

Make sure the control panel is never themed, by setting the X-Theme-Disabled
response header.
[optilude]

Add support for registering new views from Zope Page Templates and
overriding existing templates. See README for more details.
[optilude]