Create a different look and feel for different sections of your web site

by Winn King last modified Oct 31, 2009 03:04 PM
Learn how to create a different look and feel for your site, using only CSS sleight-of-hand.

Plone provides a sectional styling hook

The body tag on a Plone site has an HTML class attribute that allows you to theme different sections of the site with different styles. This is accomplished via a Python script called getSectionFromURL.

This script gives us a class name prefix of "section-" followed by the shortname (partial URL) of the item in the root folder. For example, you might have a CSS style called: .section-about-us if the shortname of your section is about-us, and you can then create CSS styles specific to .section-about-us.

Be warned that classes in CSS are not allowed to have spaces in them but shortnames in Plone may contain spaces and are usually hyphenated automatically by Plone. Use Firebug to introspect the body element of your page to be certain that you have the correct shortname.

Out-of-the-box, sectional styles can only be written for the folders immediately under the root folder, but you can also customize the getSectionFromURL script appropriately so that you can also modify deeper folders. This script is available in CMFPlone/skins/plone_scripts, which is the base product that constitutes Plone. 

Sectional styling does not work for areas of the site such as Site Map or Search, which are driven off of views, not templates.

How it works

In the main template there is a script incuded that generates, on the fly, a class for each section of the site. The script is called "getSectionFromURL".

If you have a section on your website called, say, "Products", and you look at the page source for one of the pages in that section, you'll see that Plone has created a class in the body tag called "section-products". It uses the shortname of the folder, which is also its object name in the database.

In your stylesheets, prefix whatever style you want to be different for that section with:

.section-foldername {your styles here;}

replacing "foldername" with the id or shortname of the folder in question. For example, this code would change the background image for the Products section of your site.

body.section-products {
    background-image: url(gradient2.png);
}

You must have your website's portal_css set to "debug" mode in order for your CSS to take effect automatically. You should never leave portal_css in "debug" mode on a production site, as it will slow your site down tremendously. For more information, look here.

Modify the Code for the Portal Logo

If you're doing this on version 3.x and want to make this change on the filesystem, you'll need to look into how to override viewlets here. Assuming you know how to override viewlets, we can proceed.

We want to modify the code in the logo viewlet such that it doesn't output a dynamically generated logo.jpg found in the root of your site. Instead, it can be configured to spit out a CSS class that can then be styled.

By default, Plone ships with this code:

<a metal:define-macro="portal_logo"
   id="portal-logo"
   accesskey="1"
   tal:attributes="href view/navigation_root_url"
   i18n:domain="plone">
    <img src="logo.jpg" alt=""
         tal:replace="structure view/logo_tag" /></a>

Change this code such that you comment out the existing code and add this new banner code:

<a href="#"
    tal:define="portal_url context/@@plone_portal_state/portal_url;"    
    tal:attributes="href string:${portal_url}/your-destination-url"
    class="banner">
		<span tal:attributes="src string:${portal_url}/banner.jpg;" />
</a>

The second snippet will return whatever the stylesheet has specified for the .banner class. Add CSS to support this code (note that you can use getSectionFromURL to do more than just adjust your logo.

You can affect almost any element on your page using this kind of styling. The only weak issue to be aware of is that if you change the shortname of your section, your styling will be broken. This is usually something that can be handled by educating your end users. For example, this is specific to a section with a shortname of "foo":

.section-foo .banner { margin: 1em; background-image: url(banner-foo.gif); background-repeat: no-repeat; }

Alternately, you can specify a more generic base CSS class.

.banner { background-image:url(&dtml-portal_url;/banner.jpg); }

and then inside each of your folders on your site (on the end user side, not in the ZMI), add an image named banner.jpg. Plone's ability to acquire will pick up the nearest "banner.jpg" it finds. Typically, you'll want to do this using your CSS (the first example above) instead of via acquisition, as it is preferable to keep content on the filesystem or on the end user (content) side of Plone instead of in the ZMI.

If you want to do more than change the logo or banner, the getSectionFromURL script comes in even more handy.

Examples of Other Things You Can Change in Your Stylesheets

body { background-image: url(gradient.png); }

/* this is specific to a section with a shortname of foo */ body.section-foo { background-image: url(gradient2.png); }

#visual-portal-wrapper { background-color:#000; }

/* this is specific to a section with a shortname of foo */ .section-foo #visual-portal-wrapper { background: white; margin: auto; width: 883px; position: relative; }

#portal-logo { margin: 1em; background-image: url(logo.jpg); background-repeat: no-repeat; }

/* this is specific to a section with a shortname of foo */ .section-foo #portal-logo { margin: 1em; background-image: url(logo-foo.gif); background-repeat: no-repeat; }

and so on...