Community Wiki

Print Properties
Themes

Themes customize the overall look and feel of Liferay and were introduced in version 3.5 of the portal.

Directory Structure

The directories in themes have been changed to be easier to navigate and understand. Currently, here is how the new directory structure looks like:
 /THEME_ID/ *
    /css/
      base.css
      custom.css
      main.css
      navigation.css
      forms.css
      portlet.css
      deprecated.css
      tabs.css
      layout.css
    /images/
      (many directories)
    /javascript/
      javascript.js
    /templates/
      dock.vm
      navigation.vm
      portal_normal.vm
      portal_popup.vm
      portlet.vm
 /WEB-INF
 /META-INF
* (the name/theme id of the theme, which is specified in WEB-INF/liferay-look-and-feel.xml)

HTML

Since version 4.3, many of the templates in the templates directory have been consolidated. There are no longer 2 files for portlet_top.vm and portlet_bottom.vm, but now are combined into portlet.vm. The portlet.vm file, at its most simplistic, could look something like this:
  
  $portlet_content
  

The HTML now defaults to standards mode, but can be switched to quirks mode easily by removing the doctype from portal_normal.vm.

Here are the descriptions for each of the templates:

portal_normal.vm
this file contains the overall site structure, from opening HTML tag to closing. It includes the header, and footer, and includes the two templates (i.e., dock.vm and navigation.vm) and it also includes the system files needed by the liferay core
dock.vm
this file contains all of the HTML for the dock.
navigation.vm
this file contains all of the html for the navigation
portal_pop_up.vm
this file contains the entire html structure for popup windows.
portlet.vm
this file contains the HTML that wraps every portlet, including the portlet title and portlet-icons.

Some people are not required to use Velocity. If they feel more comfortable with JSP, they can use JSP, however they won’t have access to the velocity variables. The Velocity API defines what macros, variables and methods can be used from velocity. Find the 4.3.0 version here: http://content.liferay.com/4.3/misc/theme-api-4.3.0.html

CSS

Here are the descriptions for each of the CSS files:
main.css
this file includes all of the other css files. This file can be edited, but probably should not be.
custom.css
This file is where the developer should place all of their css that is different from the other files, unless they’re not concerned about upgrading their theme later on. By placing their custom CSS in this file, and not touching the other files, they can be assured that the upgrading of their theme later on will be much smoother.
base.css
This file contains all of the base styling that is fairly generic, such as the styling for all elements not directly related to another aspect of the site, such as the forms or navigation or dock.
forms.css
This file contains all css styling related to form elements on the page.
layout.css
This file contains all of the styling related to the layouts. It is fairly low level, and should most likely not be edited, unless there is something specific they need.
navigation.css
This file contains all of the styling related to the navigation, as well as the dock.
portlet.css
This file contains all of the styling related to the portlets, including the JSR-168 class-names.
tabs.css
This file includes all of the styling related to the tabs in the portlets.
deprecated.css
This file contains styles that are deprecated, but included for compatibility. It can most likely be safely ignored.

You can now easily reference your themes images directory from your css without the use of obscure variables. To reference your images directory, you would just put the relative path like so: h1 {background-image: url(../images/custom/bg.gif);}

Also, you can now easily feed different CSS styles to different browsers or operating systems, and even different browser versions. The way to select different browsers would be like so:

  .ie h1{}
  .gecko h1{}
  .safari h1
  .ie6 h1{}
  .ie7 h1{}
  .konqueror h1{}
  etc.

To feed rules to different operating systems you would do

  .win h1 {}
  .linux h1{}
  .mac h1{}

You can also feed rules to users who have javascript on like so:

  .js h1{}

You can also combine any of these rules by “chaining” the css selectors, like so:

  .firefox.mac h1 {} 
  .js.firefox h1{}

And you can do this with the different color schemes like this:

  .safari.js .blue h1{}

This method is both valid CSS, and supported in all browsers, and fails gracefully.

JavaScript

Liferay now includes the jQuery javascript library, and theme developers can include any plugins that jQuery supports, however the $ variable is not supported (for better compliance with different portlets). Inside of the javascript.js file, you will find three different function calls, like this:
  jQuery(document).ready(
        function() {
        //Custom javascript goes here	
        }
  );
  Liferay.Portlet.ready(
        function(portletId, jQueryObj) {
        //Custom javascript goes here	
        }
  );
  jQuery(document).last(
        function() {
                 //Custom javascript goes here
        }
  );

jQuery(document).ready(fn);
gets passed a function (it can be a defined function, or an anonymous one like above), and the function gets executed as soon as the HTML in the page has finished loading (minus any portlets loaded via ajax).
Liferay.Portlet.ready(fn);
gets passed a function (it can be a defined function, or an anonymous one like above), and the function gets executed after each portlet has loaded. The function that gets executed gets passed in two variables, portletId and jQueryObj. portletId is the id of the current portlet that has loaded, and jQueryObj is the jQuery object of the current portlet element.
jQuery(document).last(fn);
gets passed a function (it can be a defined function, or an anonymous one like above), and the function gets executed after everything, including AJAX portlets, gets loaded onto the page.

Besides theme-wide JavaScript there is also support for page specific JavaScript. The Page Settings form provides three separate JavaScript pieces that you can insert anywhere in your theme. Use the following to include the code from these settings:

 $layout.getTypeSettingsProperties().getProperty("javascript-1")
 $layout.getTypeSettingsProperties().getProperty("javascript-2")
 $layout.getTypeSettingsProperties().getProperty("javascript-3")

NB! The content of the JavaScript settings fields are stored in the database as Java Properties. This means that each field can only have one line of text. For multiline scripts, the newlines should be escaped using \, just as in a normal .properties file.

Settings

Each theme can define a set of settings to make it configurable.

The settings are defined in the liferay-look-and-feel.xml using the following syntax:

 <settings>
   <setting key="my-setting" value="my-value />
   ...
 </settings>

These settings can be accessed in the theme templates using the following code:

 $theme.getSetting("my-setting")

Color Schemes

Color schemes are not done in the same way in Liferay 4.3. Instead of specifying the individual HEX codes for colors, you now specify a css class name, with which you can not only change colors, but also choose different background images, different border colors, etc.

In your liferay-look-and-feel.xml (located in WEB-INF), you would specify the class names like so:

  <theme id="my_theme" name="My Theme">
                <root-path>/my_theme</root-path>
                <templates-path>${root-path}/templates</templates-path>
                <images-path>${root-path}/images</images-path>
                <template-extension>vm</template-extension>
                <color-scheme id="01" name="Blue">
                        <css-class>blue</css-class>
                        <color-scheme-images-path>${images-path}/color_schemes/${css-class}</color-scheme-images-path>
                </color-scheme>
                <color-scheme id="02" name="Green">
                        <css-class>green</css-class>
                </color-scheme>
  </theme>

The way you would style your different color schemes is like so:

Inside of your css directory, create a folder called “color_schemes”. Inside of that directory, place a css file for each of your color schemes. In the case above, we would could either have just one called green.css and let the default styling handle the first color scheme, or you could have both blue.css and green.css.

Now, inside of your custom.css, you would place the following lines:

  @import url(color_schemes/blue.css);
  @import url(color_schemes/green.css);

The way you would identify the styling for the css is this way: In blue.css you would prefix all of your css styles like this:

  .blue a {color: #06C;}
  .blue h1 {border-bottom: 1px solid #06C}

And in green.css you would prefix all of your css styles like this:

  .green a {color: #0C6;}
  .green h1 {border-bottom: 1px solid #0C6}

Example

Let's imagine we need to create two themes that are exactly the same except for some changes in the header. One of the themes has more details while the other is smaller (and takes less screen real state). Instead of creating two different themes, we are going to create only one and use a setting to choose which header we want.

While developing the theme we get to the header. In the portal_normal.vm template we write:

  if ($theme.getSetting("header-type") == "detailed") {
    #parse("$full_templates_path/header_detailed.vm")
  } else {
    #parse("$full_templates_path/header_brief.vm")
  }

Then when we write the liferay-look-and-feel.xml, we write two different entries, that refer to the same theme but have a different value for the 'header-type' setting:

  <theme id="beauty1" name="Beauty 1">
    <root-path>/html/themes/beauty</root-path>
    <templates-path>${root-path}/templates</templates-path>
    <images-path>${root-path}/images</images-path>
    <template-extension>vm</template-extension>
    <settings>
      <setting key="header-type" value="detailed" />
    </settings>
    <color-scheme id="01" name="Blue">
      <css-class>blue</css-class>
      <color-scheme-images-path>${images-path}/color_schemes/${css-class}</color-scheme-images-path>
    </color-scheme>
    ...
  </theme>
  <theme id="beauty2" name="Beauty 2">
    <root-path>/html/themes/beauty</root-path>
    <templates-path>${root-path}/templates</templates-path>
    <images-path>${root-path}/images</images-path>
    <template-extension>vm</template-extension>
    <settings>
      <setting key="header-type" value="brief" />
    </settings>
    <color-scheme id="01" name="Blue">
      <css-class>blue</css-class>
      <color-scheme-images-path>${images-path}/color_schemes/${css-class}</color-scheme-images-path>
    </color-scheme>
    ...
  </theme>

Theme variations using CSS

For details on how to create several small variations of a theme using CSS tricks, see Theme variations using CSS

Portal predefined settings

The portal defines some settings that allow the theme to determine certain behaviors. So far there are only two predefined settings but this number may grow in the future:

portlet-setup-show-borders-default

If set to false, the portal will turn off borders by default for all the portlets.

The default is true.

Example:

 <settings>
   <setting key="portlet-setup-show-borders-default" value="false" />
 </settings>

This default behavior can be overridden through for individual portlets using:

  • liferay-portlet.xml
  • Portlet CSS popup setting

bullet-style-options

The value must be a comma separated list of valid bullet styles to be used by the navigation portlet.

The default is an empty list. The navigation portlet will not show any option in the portlet configuration screen.

Example:

 <settings>
   <setting key="bullet-style-options" value="classic,cool,tablemenu" />
 </settings>

The bullet styles referred to in the setting are defined in any of the CSS files of the theme following this pattern:

 .nav-menu-style-{BULLET_STYLE_OPTION} {
    ... CSS selectors ...
 }

Here is an example of the HTML code that you would need to style through the CSS code. In this case the bullet style option is 'cool':

 
   <h3><a href="/web/guest/community">Community</a></h3>
   <ul class="layouts">
     <li class=""><a class="" href="/web/guest/community/documentation">Documentation</a></li>
     <li class=""><a class="" href="[http://wiki.liferay.com"] target="_blank"> Wiki</a></li>
     <li class=""><a class="" href="/web/guest/community/forums"> Forums</a></li>
   </ul>
 

Using your CSS skills and, if desired, some unobstrusive Javascript it's possible to implement any type of menu.

Upgrade Theme to 4.3

There are a few main issues regarding upgrading/creating themes to be compatible with Liferay portal 4.3:
  • images in the images/ directory must be converted to .png, unless they're images that are not used in the Liferay core.
  • Color schemes no longer work like before, so those will break
  • css_cached.vm is no longer included by default, so they either need to place a
      <style>
      #parse("$templates_folder/css_cached.vm")
      </style>
or move their styles to css/custom.css or any of the other files.
  • portlet_top.vm and portlet_bottom.vm into portlet.vm and where they'd like their portlet content to be in the HTML, they need to add this:
      $portlet_content

Developing a Theme

With the introduction of Liferay 4.3 there is a new way to develop themes that will be extended off of the default Classic theme. This process allows for people to build a theme from the default Classic one, that can be maintained and more easily upgraded in the future.

To build a theme, you have a few options. You will want to start by downloading and unzipping the Liferay Plugins SDK. Also see the Liferay Plugins Development Guide.

Create a build.{username}.properties file in the exploded SDK directory and add two lines to it:

  app.server.dir=<path to Tomcat or another app server you are using>
  auto.deploy.dir=<path to the Liferay auto deployment directory - e.g. ${user.home}/liferay/deploy>

Navigate to the plugins/themes directory, and from the command line (Windows), type in:

 create.bat <project name> "<theme title>"

Example:

 create.bat hello-world "Hello World"

For Linux and Mac:

 ./create.sh hello-world "Hello World"

This will create a theme called "Hello World" with a theme id of hello-world. This will also place this theme into hello-world-theme as well as deploy the theme to your application server. This second parameter must have quotes around it to allow having spaces in the name of the theme.

If you're not able to run batch scripts, or would prefer to run the ant calls directly, you can enter: ant -Dtheme.name=hello-world -Dtheme.display.name="Hello World" create

To deploy your newly created theme, go to the newly created theme directory, and run

  ant deploy

You can go to your deploy (webapps) directory and see the new theme folder being created there.

Once your theme has been deployed, and you're ready to modify the CSS, use the custom.css file to change and override the default styling, leaving all of the other CSS files alone. You can modify any of the javascript files, image files, and template files, but the CSS changes should be restricted to custom.css.

This only applies to themes that will be bundled with Liferay. For other themes, the best process is to modify the CSS files directly, as this is much quicker. For bundled themes, we restrict the process to using custom.css so that theme display can be easily upgraded in the future.

Once you're done modifying your files, you must place them in your _diffs directory with the same directory structure as the actual theme. To keep with the "Hello World" example above, we'll assume that you've modified the custom.css file, an image file in the dock, and two template files: portal_normal.vm and portlet.vm. With those files, your _diffs directory would look like this:

plugins/themes/hello-world-theme/

 _diffs/
     css/
         custom.css
     images/
         dock/
             menu_bar.png
     templates/
         portal_normal.vm
         portlet.vm

The order in which your theme is built goes something like this:

It creates the directory and adds the appropriate build files, and XML files needed. It then copies all of the files from the _unstyled/ directory, and after that, the files from _styled/ are copied over, and the last step is that your files in the _diffs directory are copied over. So this means you will place all of your new files and changed files into the _diffs directory.

FAQ

What Can I Put in a Template?

Any HTML

A Velocity expression

$var.property

$var.method()

${var.method().chainedMethod()}

Foreach loop

Velocity Variables Available in Liferay

By far the easiest way is simply to look at the variables used in the sample Velocity themes that ship with Liferay. These templates use most (if not all) the variables you'll need. Specified in VelocityVariables.java, all velocity variables are documented in this spreadsheet. or http://content.liferay.com/4.3/misc/theme-api-4.3.0.html

To further discover what properties are available in each object, you must look in the Java source for the public properties of the object. For example, to include the user’s first name in a Velocity template, you would look up the source for com.liferay.portal.model.impl.UserImpl and find that there is a getFirstName() method. Thus, you can use $user.getFirstName() in your template. There is an additional set of variables that are derived by the "init.vm" template when the template is first run. See the file /portal-web/docroot/html/themes/_unstyled/init.vm for details. Init Example

Note: One extremely useful utility is the staticFieldGetter, whereby you can access any static field in Liferay using this class.

Checklist for Making Themes

  1. Run the command prompt and "create" your theme.
  2. Find a theme from an Open Source site or create a custom theme.
  3. Launch Tomcat and login to http://localhost:8080 and go to "Page Settings" on the welcome drop down menu.
  4. Go to Look-and-Feel and select your look-and-feel from the menu.
  5. Add 7 pages to the theme using each of the layout options excluding freeform (unless your theme calls for one specific layout).
  6. On each page add 6 portlets. You must have the Calendar portlet and the Directory portlet added to each of the pages as they represent the largest and most complex portlets. (Note: Neither portlets will expand properly in smaller columns and the styles of both portlets must be altered to fit the theme.)
  7. Start customizing your theme.
    • Make all css changes in the custom.css document
    • Place images in the most appropriate sub-folder of "images" (overwrite any existing image when possible).
  8. Periodically check your edits primarily in Internet Explorer 6 then in Firefox. Internet Explorer 6 is the browser that is used by the majority and must display your theme at full capacity.
  9. Change the liferay-plugin-package.xml file in your WEB-INF folder to match the licensing agreement and tags that your theme requires.
    • Make a best effort to find the open-source license of which you based your theme on. If you are certain that the license is open-source but cannot find the exact license use "Unknown" and link to the location where the theme is found.
    • Add new tags that clearly state which layout your themes are most compatible with (i.e. "freeform", "1-column", "2-column", "3-column", "1-2-1-column", etc.)
  10. Check the liferay-look-and-feel.xml file in your WEB-INF folder and change it so that it matches the latest version of compatibility.
  11. Make a thumbnail screen shot of your theme that is 160 pixels x 120 pixels, with a 1px solid black border, and saved as .png.
  12. Compare your theme with the defaults of the theme, "Classic", and place all modified files in the "_diffs" folder.
  13. Test your theme by deploying it.
  14. If no abnormality is observed, open up your repository program and commit the theme.

Checklist for Functional Themes

To know if the theme will work properly we suggest the following:

Overall

  • Be sure that the theme looks visually similar on both Firefox and Internet Explorer(IE6) and that all checks below work in both primary browsers.
    • Both browsers will read certain CSS styles differently so adjust them accordingly.
  • Make a thumbnail screen shot of your theme.
    • 160 pixels x 120 pixels, with a 1px solid black border, saved as .png is the Liferay standard.
  • Keep all CSS changes and/or updates in the Custom.css document.

Portlets

  • Check to see if the following portlets are displayed properly especially when changed: Calendar, Directory,(mainly portlets with tables and tabs) etc.
  • Make sure that the portlets on each page blend well with the layout of each page (e.g. the calendar portlet needs a layout with a large column to fully widen; if it is in a smaller column the td's and content can overlap).

Navigation

  • Add multiple pages on the navigation bar. Be sure to check that your navigation is properly displayed when the page is the first, middle and last item on the list.
  • Check to see if the margins and padding change properly on hovered links in both Firefox and Internet Explorer.
  • Check the welcome dock and list container to see if all text is visible and the margins of the list container align with the dock.
  • Check the sub list in the My places menu item so that it is completely visible.

Layouts

  • Make sure if you edit any of the columns in CSS that every column combination fits the theme when used.
    • Be sure to change around the layout of each page to make sure that each layout matches your theme.

Images

  • Use conventional names when creating or saving your theme's image files so that the theme's source is portable and easy to reproduce.
  • Make sure that when you point to images in CSS that you are pointing to the correct folder within your theme build.

Licensing

  • Be sure to change the liferay-plugin-package.xml file in your WEB-INF folder to match the licensing agreement and tags that your theme requires.
  • Check the liferay-look-and-feel.xml file in your WEB-INF folder and change it so that it matches the latest version of compatibility.

Deployment

  • Deploy your theme to verify functionality.

How do I create a URL to a portlet?

Often you want to create a URL to a portlet. Let's use as an example the common case of linking to the Language portlet to change the language of the page (and then returning to this same page, in this case).

To create the URL you have to use the portletURLFactory variable and pass four parameters:

  • The request object: $request
  • The portlet name: for example "82"
  • The identifier of the current page (get it with $page.getPlid()) or of the page where you want the target portlet to be shown.
  • Whether the URL will be an action URL (true) or a render URL (false)

Afterwards you can use use setters to change the windowState, portletMode or set parameters. Here is the complete code:

 #set ($change_language_url = $portletURLFactory.create($request, "82", $page.getPlid(), true))
 $change_language_url.setWindowState("normal")
 $change_language_url.setPortletMode("view")
 $change_language_url.setParameter("struts_action", "/language/view")
 $change_language_url.setParameter("redirect", "$portalUtil.getCurrentURL($request)")
 $change_language_url.setParameter("languageId", "en_US")

Now you have a variable called $change_language_url that you can use as many times as you want. For example:

 <a href="$change_language_url">English</a>

Best Practices

I also learned yesterday a trick from the nice folks at the Liferay meet-up in SoCal that the recommended best Practice is to put ONLY the differences of your theme into a _diff directory. Have to play with it to provide further feedback -- but felt this deserved mentioning.
9300 Views, 0 Attachments 0 Attachments

  • Comments