CSS and JavaScript to Page
Plone Theme Reference
1. CSS and JavaScript to Page
How style sheets and JavaScript reach the page.
Style sheets and JavaScript files are included in the skin section of the Plone Default theme, so the process of customizing or rewriting in general follows the concept of order of precedence described in the Skin section of this manual (i.e. placing a replacement in a higher layer in the Skin).
If you create your own style sheet, you can either put it in the custom folder of portal_skins through the web or in the skins directory of your theme on the file system.
If you like, and are feeling ambitious, you can turn your stylesheet into a resource type component by putting it in the browser directory and registering it in ZCML. Indeed, this is done for you if you create your own theme product using the paster plone3_template. There are pros and cons to the latter approach, look back at the Skin or Components section if you want to explore these further.
Resource Registries
Before the CSS and JavaScript reach the page they go through an extra step. You'll note that there are quite a few style sheets and JavaScript files available (and not all are always required). So a Registry tool picks and chooses them as required and merges only those it needs for speed and efficiency.
There's a detailed tutorial on how to use these registries in the following section.
including how to use conditions to specify that you only want a particular resource loaded in a particular context (for instance with a document view).
Registering style sheets and JavaScript
- Through the web you can add or remove style sheets and JavaScript by going to the Zope Management Interface > portal_css or portal_JavaScripts.
- On the file system, registering style sheets and JavaScript is part of the Configuration. So you'll need to look in profiles/default/jssregistry.xml and cssregistry.xml.
DTML
Some of the default Plone style sheet files have a .dtml extension, and the CSS inside is wrapped in
/* <dtml-with base_properties> */ ....... /* </dtml-with> */
DTML is another Zope templating language, which in this case is deployed so that particular variables can be picked up from a properties sheet (base_properties.props) - for example:
#portal-column-one {
vertical-align: top;
width: <dtml-var columnOneWidth missing="16em">;
border-collapse: collapse;
padding: 0;
}
We wouldn't recommend using this technique as it is likely to be phased out, but it is as well to know that it is there. You can sometimes get caught out if you're customizing an existing style sheet and accidentally delete the top or bottom "dtml-with" statement.
2. Using the Resource Registries to Control CSS and JavaScript
Plone has two neat tools for managing Cascading Stylesheets and JavaScript in a handy way. This tutorial explains some whys and hows and even has a minimal practical example of how it works.
2.1. Why do we even have these registries?
Why were the Resource Registries written, what do they do, and why are they useful?
The ResourceRegistries spring out of ( as most features in Plone ) frustrations with the state of the world before their existence: If you wanted to add a CSS style sheet or a Javascript library to your Plone site, beyond using the ploneCustom.css-file, you would have to override the header templates. This was painful from a maintenance point of view, and it also didn't allow it happening more than once. There was no way of Products supplying their own css files without massive conflicts if more than one Product attempted the same. Having several style sheets and Javascript files to make things more manageable on the filesystem was painful too.
With the existence of ResourceRegistries we were also able to split up Plone's CSS and Javascript into more manageable parts that can be turned on or off at the click of a button. We couldn't do this in earlier versions of Plone as splitting the style sheets would increase the number of separate http-requests needed to display a page incredibly.
The resource registries should:
- Make it easier to work with and supply your own Cascading Style Sheets and JavaScripts in Plone
- Make it possible/easier to add conditions to your Cascading Style Sheets and JavaScripts so they only apply when you want them to
- Make it easy for Product authors to supply Cascading Style Sheets and JavaScripts for their products without getting conflicts with other products
- Reduce the number of http-requests needed to display a Plone page in a browser
- Pack Cascading Style Sheets and JavaScripts to reduce the download sizes of files to users, and the bandwidth usage from serving a Plone site
- Make it easy to change priorities amongst Cascading Style Sheets and JavaScripts
- Make it easy to disable all or parts of Plone's default Cascading Style Sheets and JavaScripts
What are the registries?
The Resource Registries currently consist of two Plone tools living in the ZMI in the root of your Plone site. They have been part of the Plone bundle/installers since Plone 2.1. (They can be used with Plone 2.0.x as well. There is a special readme-file in the product for installation instructions for Plone 2.0.x)
How do the registries work?
Each registry has an ordered list of resources, CSS or JavaScript files, each with its own set of attributes. Entries in the registries will be linked automatically in Plone pages in the standard templates when the browser requests a page. The registries have been configured to have very sensible defaults â so for almost all use-cases (probably 90%+) it is merely the matter of adding the id of a resource you want to use.
NOTE: For experimentation, for example when reading this document, make sure to check the "debug/development mode" checkbox on the top of the configuration panel. (Read more about why in part 2.)
2.2. Conditions, merging, caching and debugging
some more details on how the ResourceRegistries function
Conditions
When a user agent (i.e a browser) makes a page request, all the resources registered in the registry are evaluated against their condition field. If the condition is true, the resource is served to the browser. If the condition evaluates to false, the resource is not served.
This gives you the ability to conditionally serve different style sheets or scripts based on logic like whether the user is logged in, whether you are in the "Human Resources"-section of your intranet of if the content-type is a news-item.
Conditions have to be TALES expressions. You can use global template variables inside them.
Merging
Whenever you click the save-button in a registry, a new set of css or javascript files are created. The registry will try to assemble the different resources into bigger lumps/files to server to the browser. This is to reduce the number of http-requests necessary and can improve performance considerably.
The rules for merging resources
- The registry will only try to merge resources that are adjacent in the list. Otherwise there's risk that the order of operations in the browser would be affected (order of code in JavaScript and the order of the cascade in CSS). This would possibly affect rendering or execution in the browser in a negative way, and is therefore not available.
- Two adjacent resources are only merged if their condition is exactly the same (more about conditions in the next chapter)
- Two adjacent resources are not merged if they don't have the 'allow merging' checkbox checked
The
magically assembled 'Files' are assigned a new random number as their
name. So you'll find entries like <link rel="stylesheet"
href="plone2341.css" /> in your html source. You can inspect how
the resources will be merged if you click the second tab in the
registry; "composition". It will present you with a list of 'magic'
files, like 'plone2341.css', and nested within them the component
resources they are constructed from. You can click each entry to
inspect what it will look like when served.
The CSS-composition UI

Each merged resource will have a small snippet in the source identifying its origin so that you can get hold of the full unmodified source if you need.
The comment stuff usually looks like the following.
/* ----- base.css ----- */
@media screen {
/* http://yourhost/plone/portal_css/base.css?original=1 */
/* */
Caching and HTTP
The merged resources are automatically served with HTTP-headers optimized for being cached a long time. Since the auto-generated number is being changed every time you save the registry settings, the browser will request the new 'files' and not use its old cached values anyway. The scheme is actually rather clever.
The potential problem with the caching scheme is that the registry doesn't know if you change the files in the skins directories unless you touch the "save" button in the registry. This is only an issue while you are working on your CSS (or JavaScripts) to get them right, but can cause massive confusion if you make changes and only see cached styles/scripts in the browser. To avoid this issue, we have added a handy "debug and development" mode to the registries.
Debug and development mode
To enable the debug and development mode, check the corresponding checkbox in the registry configuration page and click "save".This:
- Disables merging of resources (great for finding bugs and specific declarations with the inspectors and development tools like Firebug)
- Sets HTTP-headers for not caching so that you get a fresh copy every time
- Disables compression
These settings affect performance in an adverse way, so make sure to disable the debug mode when your Plone goes live.
2.3. Resource Parameters
The parameters for a registry entry in the CSS (and JavaScript) registry.
Each entry in the CSS and JavaScript registries has some parameters that can be tweaked.
- id
- The id of the style sheet or JavaScript to be used. In Plone 3.3 onwards you can specify an externally hosted resource by entering the full URL here.
- expression
- A TALES expression to be evaluated to check if the style sheet or JavaScript should be included in output or not. You can use global template variables here.
- conditionalcomment (available from Plone version 3.3 onwards)
-
A small string to be included in a conditional comment around the resource. For example, entering simply 'IE' in the field will
result in a conditional comment of:
<!--[if IE]>...<![endif]--
This behavior is currently enabled for the CSS and JavaScript registries. The KSS registry is the only registry that does not have full support for conditional comments. For more information see: http://msdn.microsoft.com/en-us/library/ms537512.aspx - media
- The media for which the style sheet should apply, normally empty or 'all'. other possible values are 'screen', 'print' etc. Read more about the media settings of CSS at w3.org
- rel
- Link relation. defaults to 'stylesheet', and should almost always stay that way. For designating alternative style sheets. This is used for the toggle between large, medium and small fonts in default Plone. Don't change this one unless you know what you are doing.
- title
- the title of an alternate stylesheet.
- rendering
- How the stylesheet is linked from the html page. This is an
advanced setting. Leave it set to the default 'import' unless you know
the effects of different ways of rendering and linking stylesheets
- import
- the default. normal css import
- link
- works better for old browsers and is needed for alternate stylesheets
- inline
- render
the stylesheet inline instead of linking it externally. Shouldn't be
used at all! It isn't possible to create sites which validate if you do.
For more information see: http://developer.mozilla.org/en/docs/Properly_Using_CSS_and_JavaScript_in_XHTML_Documents
- compression
- Whether and how much the resource should be compressed
- none
- the original content will not be changed
- safe
- the content will be compressed in a way which should be safe for any workarounds for browser bugs. Conditional code for Internet Explorer is preserved since ResourceRegistries 1.2.3 and 1.3.1.
- full
- the content will be
compressed with some additional rules.For css all comments and most
newlines are removed, this may break special browser hacks, so use with
care. For JavaScript this encodes variables with special prefixes
according to the rules described here (Special Characters):
http://dean.edwards.name/packer/usage/ The source code needs to be written according to those rules, otherwise it's more than likely that it will break. - safe-encode
- - only available for JavaScript
- 'full-encode' - only available for JavaScript. Additionally encodes keywords. This heavily compresses the JavaScript, but it needs to be decoded on the fly in the browser on each load. Depending on the size of the scripts this could lead to timeouts in Firefox. Use with special care! - applyPrefix
- - only available for CSS.
- If your stylesheet uses relative URLs in aurl()statement, e.g. to refer to another stylesheet or image, you may experience problems when using the registry in non-debug-mode, as portal_css alters the URL seen by the browser. If so, set this option to True or tick the "Replace relative paths in url() statements with absolute paths?" option in the portal_css management screen to replace any relative path inside aurl()statement with an absolute path (prefixed with the Plone site root path) during the resource merging stage. This does not modify the original stylesheet. It may have a slight performance impact, but it should not be an issue if resources get cached properly. It has no effect in debug mode.
2.4. Practical: Adding a Style Sheet to the Registry Through the Web
Basic operations of the CSS-and Javascript-registries – and a truly minimal example of how to use them in real life. As a simple example of the most basic functionality, we'll add and register a minimal stylesheet that adds to the background of your Plone a terrible red color.
To use one of the registries, you have to
- Have a resource (for example a File) in your Skin with some CSS or JavaScript in it (this could, for instance, be in the custom folder of portal_skins).
- Make an entry in the corresponding registry (for example portal_css) with the id of the resource.
Make a Style Sheet
- Go to Site Setup > Zope Management Interface and navigate to portal_skins/custom
- From the add-item menu, select File
- Give your new file an id of 'css-demo.css'
- Paste the following content into the file:
body{ background-color : red } - â¦and save it
Add it to the CSS Registry
The registries are two tools that live only in the Zope Management Interface (ZMI); they have no interface in the Plone user-interface itself. However, you can easily find them when browsing the ZMI of your Plone site - look for portal_css and portal_javascript
- Go to Site Setup > Zope Management Interface and click portal_css. Once selected, the CSS Registry ( the one we use for this example - the JavaScript one is almost exactly the same) will present an interface displaying all the registered resources (in the case of the CSS Registry, the resources are CSS files).
- Make sure that you tick the debug mode checkbox. This will ensure that you see your changes immediately.
-
Scroll to the bottom of the form, where there is a form for adding a style sheet
- In the id field, enter 'css-demo.css' (leave the other values as they are by default for now)
- Voila! â view your Plone site and you'll easily notice its (admittedly quite horrifying) shiny red background color!
The Technical Explanation
Each
entry in the registries has an id that references a resource that can
be found in the current Plone acquisition context. Technically it could be a tool or a utility or
anything that has a name and is available, but most commonly it will
be a File object ( for static CSS and JS) or a DTML Method (for dynamic
variable replacement). The Resource Registries makes no difference as
to what the object is, as long as it can be found and called, rendered
or printed as a string.
2.5. Practical: Adding a Style Sheet to the Registry in your own Theme Product
Style sheets and JavaScript are added to the registries on installation of your theme product, via Generic Setup. You simply need to write the Generic Setup XML.
Create your Style Sheet
- Create a normal CSS file [mytheme.css] using your favourite CSS editor.
- You now have two options:
- The simplest place to put your style sheet is in the skins directory of your theme product. Paster will have created a styles directory for you (skins/plonetheme_mytheme_styles).
- Paster will also have created a stylesheets directory for you in the browser directory of your theme product and will have registered this as a resource in the configure.zcml file. You can, if you like, put your style sheet in that directory instead.
Write your Generic Setup File
The relevant files for the configuration of your registries are profiles/default/cssregistry.xml and profiles/default/jsregistry.xml. Paster should have created these for you, but if they aren't there, just make them yourself.
An entry for a style sheet in the skins directory of your theme product, will look like this:
<?xml version="1.0"?> <object name="portal_css" meta_type="Stylesheets Registry"> <stylesheet title="" cacheable="True" compression="safe" cookable="True" enabled="1" expression="" id="mytheme.css" media="screen" rel="stylesheet" rendering="import"/> </object>
Note that the parameters are just the same as the through-the-web form. You need only give the ID of the style sheet; Plone will find it as it is part of the skin.
An entry for a style sheet in the browser directory of your theme product will look like this:
<?xml version="1.0"?> <object name="portal_css"> <stylesheet title="" id="++resource++plonetheme.mytheme.stylesheets/mytheme.css" media="screen" rel="stylesheet" rendering="import" cacheable="True" compression="safe" cookable="True" enabled="1" expression=""/> </object>
Note the special ++resource++plonetheme.mytheme.stylesheets syntax to refer to the directory registered as a resource in browser/configure.zcml
Once written, you can reimport the cssregistry.xml file using the portal_setup tool in the ZMI to make this change take effect. Make sure you choose the correct profile (your theme product) before importing the CSS step. Re-installing your theme product will also work, though you should be careful to guard against GenericSetup clashes. It's safer to import the individual step if your theme has been installed previously.
Plone Version 3.3 Onwards
In Plone 3.3 onwards you can also tell the CSS Registry to put conditional comments around your stylesheet:
<stylesheet title="" cacheable="False" compression="none" cookable="False" rel="stylesheet" expression="" id="IEFixes.css" media="all" enabled="1" rendering="import" conditionalcomment="IE" />
You can also specify an external resource:
<javascript cacheable="False" compression="none" cookable="False" enabled="True" expression="" id="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" inline="False" insert-before="jquery-integration.js" />
If you are using SSL and specifying an external resource, you may find it necessary to specify both an http and an ssl entry in the registry. You can use the expression parameter to decide which one will be used:
<javascript cacheable="False" compression="none" cookable="False"
enabled="True" expression="python:request.get('ACTUAL_URL','').startswith('https://')"
id="https://jqueryjs.googlecode.com/files/jquery-1.2.6.min.js"
inline="False" insert-before="jquery-integration.js" />
<javascript cacheable="False" compression="none" cookable="False"
enabled="True" expression="python:request.get('ACTUAL_URL','').startswith('http://')"
id="http://jqueryjs.googlecode.com/files/jquery-1.2.6.min.js"
inline="False" insert-before="jquery-integration.js" />2.6. Example Conditions
Some examples of limiting Style Sheets by the condition parameter, to help you get started.
In these examples we've given the condition as it would appear in profiles/default/jsregistry.xml and cssregistry.xml. If you are working through the web, then the text within the inverted commas "...." can simply be dropped into the condition box for the relevant CSS or JavaScript file in portal_css or portal_javascripts.
Content Type
If your CSS or JavaScript is only relevant to a particular content type:
expression = "python:object.meta_type == 'ATFolder'"
View
You can check a specific browser view for a property (this example is from Products.Maps):
<javascript
cacheable="True"
...
expression="object/@@maps_googlemaps_enabled_view/enabled
| nothing" />
Here's how to look up one of the global views (see the Using Other Information about your Site Section for more about these views). This example delivers the Plone RTL Style Sheet:
<stylesheet
...
expression="python:portal.restrictedTraverse
('@@plone_portal_state').is_rtl()"
id="RTL.css"
.../>
Role
The following will check whether the visitor is logged in or not - in this case it delivers the standard member.css if the visitor is not anonymous:
<stylesheet
...
expression="not: portal/portal_membership/isAnonymousUser"
id="member.css"
.../>
This example does the same, but uses the plone_portal_state view
expression="python: not here.restrictedTraverse
('@@plone_portal_state').anonymous()"
Section and/or place in the site
Note that the body tag of every page has a section and template CSS class. So you may not need to use the resource registries at all.
However, if you want to change styles for a folder that isn't at the top level of your site, or, if you want to supply some JavaScript at a specific point in the site, then you will need to write a script and call this via the resource-registry expression. The section class on the body tag in main_template is generated by a Python script getSectionFromURL. This is a good starting point for your own script.
Here's an example expression and script. This will return True for a folder of your site with the shortname 'news' and any object within it. In this case - unlike the default Plone setup - the news folder is one level down from the top level:
expression="python: here.getSectionInTree(object,1)=='news'"
## Script (Python) "getSectionInTree"
##bind container=container
##bind context=context
##bind namespace=
##bind script=script
##bind subpath=traverse_subpath
##parameters=object, position
##title=Returns a section name
##
contentPath = object.portal_url.getRelativeContentPath(context)
if not contentPath:
return ''
else:
if len(contentPath)-1 >= position:
return contentPath[position]
else:
return ''
3. How to Add New Class Styles to Kupu
This document explains how to add and define new custom class styles for use in kupu.
Pre-requisites: CSS knowledge
1. Go to Site Setup in your Plone site.
2. Select the kupu visual editor add-on product configuration icon, as seen below:

3. Scroll down to the paragraph styles box.

4. Add your new paragraph style in the box. Format is title|tag or title|tag|className, one per line. For example:
Smalltext|p|smalltext
5. Open your ZMI.
6. Make sure that your site is in debug mode when first making changes. This will allow you to see your changes right away.
7. Go to http://yoursite/portal_skins/plone_styles/ploneCustom.css/manage_main.
8. Click the customize button.
9. Enter your new paragraph style where it says âadd your custom stuff hereâ.
.smalltext {font-size: 70%;}
Note: scroll down the page for available elements. See base_properties for definitions of those elements.


Author: