
Theme variations using CSS
Table of Contents [-]
Introduction #
This entry is an extension to the Wiki entry on building themes (see Themes v4.3-v5.2.x). There are two nice sections on that page on using theme specific "Settings" and "Color Schemes" for creating variations of themes. There is also an example that shows how one can create a variation on a theme by including different sections in a template.
The technique documented here was inspired by that idea of having two theme "color schemes" registered, but having only a single source set. You should be familiar with that technique before reading this entry.
The example document here was used in a theme where it was desired to have a variation of a theme where the portlet borders are turned off universally. While its true that one could instruct users to go to each portlet's configuration, and "turn off" border display manually, that may impractical on sites with large numbers of portlets and/or pages. What if the end user wanted to switch back and forth between the two looks and decide which they liked better?
Theme Variations #
The technique documented here creates a "color scheme" that has the borders turned off, but preserves the other attributes of the theme, and does so with a single CSS source set (allowing for easier maintenance). It uses a CSS design pattern known as "CSS sub-class selectors." Note that this technique can be used for more than just borders. It can be used when you have several very small variations on a single theme, and you want to keep all of those variations in a single source file.
1. Per the known technique of creating a color scheme, we create a color scheme for the default theme registered in liferay-look-and-feel.xml:
<theme id="customTheme" name="My custom theme"> <color-scheme id="01" name="Default"> <css-class>default</css-class> <color-scheme-images-path>${images-path}/color_schemes/default</color-scheme-images-path> </color-scheme> </theme>
2. Separate out all color settings and image selections into a special CSS file (in this example, put it in css/color_schemes/default.css. Here are a few sample entries in the file:
.default #portlet-wrapper, .default #portlet-wrapper- { background-color: white; } .default .portlet-title { color: black; } .default .portlet, .default .portlet-topper, .default .portlet-content, .default .portlet-title { background-image: url(../../images/color_schemes/default/portlet/portlet_bg.png); }
3. Now, here is the "new" technique: We want EVERYTHING in the theme, colors and all, to be identical, with a single exception: we don't want borders. So, a NEW entry in liferay-look-and-feel.xml following the above "default" definition:
<color-scheme id="02" name="Default with no portlet borders"> <css-class>default noborders</css-class> <color-scheme-images-path>${images-path}/color_schemes/default</color-scheme-images-path> </color-scheme>
Important to note in the above: the "css-class" entry is defined as the SAME css class as the first one, followed by a space, then the name of the theme's "sub-class" (in this case, "noborders"). Next, the "color-scheme-images-path" is defined as the SAME path as the original "default" scheme. Thus, there is no need to duplicate the image files either.
4. This is the only new CSS that needs to be added to the "default.css" file:
.default.noborders .portlet, .default.noborders .portlet-topper, .default.noborders .portlet-content, .default.noborders .portlet-title { background-image: none; background-color: white; }
Notice that the initial CSS selector is ".default.noborders", with NO space between them. That is CSS for "must have both of these classes".
Since in the liferay-look-and-feel.xml, the "css-class" has the space, the Liferay theme system generates class="default noborders" in the HTML of the portal. All of the CSS that is namespaced with JUST the selector ".default" will be applied to BOTH themes - the "Default", and the "Default with no borders" theme. All CSS selectors that are namespaced with ".default.noborders" will apply ONLY if the "no borders" theme is selected.
5. We could create a third and forth theme like this:
<color-scheme id="03" name="Default with no portlet borders, blue background"> <css-class>default noborders blue-bg</css-class> <color-scheme-images-path>${images-path}/color_schemes/default</color-scheme-images-path> </color-scheme> <color-scheme id="04" name="Default with no portlet borders, red background"> <css-class>default noborders red-bg</css-class> <color-scheme-images-path>${images-path}/color_schemes/default</color-scheme-images-path> </color-scheme>
and add this to the CSS
.default.noborders.blue-bg .portlet { background-color: blue; } .default.noborders.red-bg .portlet { background-color: red; }
We now have FOUR theme variations with only a couple of lines in the CSS file. The selector ".default" applies to ALL FOUR themes. The selector ".default.noborders" applies to three of the four (those without borders). The selector ".default.noborders.blue-bg" applies only to that with the blue background.
It would be fairly easy to make a large number of permutations on this: a "blue background WITH borders" for example, using a similar technique. The selector ".default.blue-bg" will apply to all elements that are default and blue background, regardless of if they have a border or not.