Theme complete tutorial


Themes
·         1 Introduction
·         2 Version Specific Info
Introduction
Themes customize the overall look and feel of Liferay and were introduced in version 3.5 of the portal.
They are generally written using the Plugins SDK with a templating language. Since version 4.3, themes have been written primarily in Velocity. As of version 6.0, they can now also be written using Freemarker.
Children Pages
·         Accessibility Guidelines
·         Fast Theme Development
·         Row Coloring
·         Theme variations using CSS
·         Themes (WAP)
·         Themes v4.0-v4.2
·         Themes v4.3-v5.2.x
·         Themes v6.0
·         Accessibility Guidelines

Table of Contents [-]

Introduction #

Web accessibility refers to the practice of making websites usable by people of all abilities and disabilities. This page outlines the best practices for building an accessible portal in Liferay.

Hiding text #

Sometimes, you may want to hide some information in a label or a table but you may still want that information to be read by screen readers. In Liferay, we provide a css selector for doing this: aui-helper-hidden-accessible. It is different to the aui-helper-hidden because this selector will hide the text also from screenreaders.
Example:
<a href="#">Read more <span class="aui-helper-hidden-accessible"> about the Accessibility Guidelines page </span></a>
 
This link will only display "Read More" but users using a screenreader will get all the information they may need.

HTML Validation vs Performance #

If you have a look at the templates (vm files) for Liferay portal, you may find that the javascript is placed after the </body> tag. This small change brings a lot of improvements in performance, but it does not validate HTML. So, you will have to modify the vm templates if you want to change this. There is also a theme in liferay plugins repository which already validates HTML called "WCAG 2.0".

Go to content link #

By default, the classic theme and control panel theme have links at the very beginning of every page with "Skip to content" -- it automatically goes to the begining of the content (the anchor #main-content). You can add more links or change the existing one in your theme to fit your needs.

Opens in a new window#

If you use <aui:a> instead of <a> in your links, this will be done automatically for you. If your link opens a new window the html generated for your link will be like this:
<a target="_blank" href="#">
   <span class="taglib-text">RSS</span><span class="opens-new-window-accessible">(Opens New Window)</span>
</a>
All the liferay links opening a new window are like this, so you can modify the text for an image using css in the class opens-new-window-accessible.



Embedding a portlet in the theme


Table of Contents [-]

This article needs updating. For more information, see Wiki - Need Updating.

Introduction #

Themes are developed using the Velocity template language. Liferay provides tools available within Velocity's context to perform special operations such as embedding a portlet.
Here is an example of embedding the Navigation portlet into the theme.

Example #

Create the preferences for the portlet #

#set ($VOID = $velocityPortletPreferences.setValue('display-style', '1'))
#set ($VOID = $velocityPortletPreferences.setValue('portlet-setup-show-borders', 'false'))

Instanceable Portlets #

If the portlet is instanceable, then the nomenclature for the portlet must contain an Instance Id in the form of a 4 character, alpha-numeric string, such as E3j7. The goal for this value is that it should be unique among the portlets of the same type on any give page.
#set ($instanceId = 'E3j7')
This value is appended to the root portlet Id like so (In this case we are using the Navigation portlet who's portletId is '73'):
73_INSTANCE_E3j7
Hence,
#set ($myPortletId = "73_INSTANCE_${instanceId}")

Plugin Portlets #

If the portlet is from a deployable plugin, the nomenclature for the portlet must contain the Plugin Id in the form defined in Theme Id or Portlet Id references in portal-ext.properties.

Embedding: The taglibLiferay Tool #

Finally, we want to have the portlet invoked in some specific location using the taglibLiferay tool.
$taglibLiferay.runtime($myPortletId, '', $velocityPortletPreferences.toString())

Changing Parameters #

You can pass different parameters to the portlet by setting the value of the second parameter in the form of a query string:
#set ($queryString = "param1=value1&param2=value2")
$taglibLiferay.runtime($myPortletId, $queryString, $velocityPortletPreferences.toString())

Resetting Preferences #

If you plan to add more than one portlet to the page in this way, make sure to reset the preferences you created for each portlet:
#set ($VOID = $velocityPortletPreferences.reset())
You can then proceed with a different portlet.

Complete Example #

Here is a complete example:
#set ($VOID = $velocityPortletPreferences.setValue('display-style', '1'))
#set ($VOID = $velocityPortletPreferences.setValue('portlet-setup-show-borders', 'false'))
#set ($instanceId = 'E3j7')
#set ($myPortletId = "73_INSTANCE_${instanceId}")
$taglibLiferay.runtime($myPortletId, '', $velocityPortletPreferences.toString())
#set ($VOID = $velocityPortletPreferences.reset())

Fast Theme Development

Overview2 #
As a theme developer, you might find it time consuming to continuously have to compile (jar) and deploy your theme plugin during development. The following describes a methodology that can be used to assist a theme developer from having to continuously compile and deploy to the server as you refine things like CSS, JavaScript, Theme Images with this simple trick.
Currently this trick is only easily available using Liferay 5.2 and for a logged in user. Variants for any version are certainly imaginable once you understand how this works.

Instructions #

Step 1 : Create a custom attribute for your user #

Go to the control panel, and add a new custom attribute to your user. In this example I'll use a variable named "AlternatePath". As the value for "AlternatePath" set it to the patch to your local _diffs (or base directory depending upon which is relevant to you) of your theme plugin. For myself, on Mac OS, I use:
file:///Users/jklo/Documents/source/liferay-plugins/themes/my-theme/docroot/_diffs
Linux/Unix users will have a very similar file reference. Windows users will differ slightly as it will need to reference a drive letter in the path. The easiest way to get the right path, use your web browser to open a file locally within the _diffs directory. The URL in your browser should use the correct file: syntax.

Step 2 : Modify the init_custom.vm to reference the variable you just set #

You can copy and paste the code below into your init_custom.vm. Then compile and deploy your theme plugin. What it does is get the value of the AlternatePath variable we set above, and if it exists and is not empty, it disables theme caching, and then modifies the $imagePath, $javaPath, $cssPath, and $css_main_file variables so that they reference the location on your local computer, instead of the ones within the deployed theme.
#set ($altPath = $user.getExpandoBridge().getAttribute('AlternatePath'))
#if ($altPath && $altPath != "")
        #set ($ignore = $theme_display.setThemeCssFastLoad(false))
        #set ($ignore = $theme_display.setThemeImagesFastLoad(false))
        #set ($ignore = $theme_display.setThemeJsBarebone(false))
        #set ($ignore = $theme_display.setThemeJsFastLoad(false))
        
        #set ($imagePath = $theme_display.setPathThemeImage("$altPath/images"))
        #set ($javaPath = $theme_display.setPathThemeJavascript("$altPath/javascript"))
        
        #set ($cssPath = $theme_display.setPathThemeCss("$altPath/css"))
        #set ($css_main_file = $htmlUtil.escape($portalUtil.getStaticResourceURL($request, "$altPath/main.css")))
#end
You should now be able to make modifications to files within your local images, javascript, css, and main.css and the changes become instantly viewable within the portal only to yourself. Once you are satisfied with your changes you can compile and deploy your theme, and then clear the value of the AlternatePath variable you set.

Row Coloring

Problem #

Where and how do we change the colours for the backgrounds when hovered over with mouse within 'themes'? Currently when I hover over a category wihin the message portlet the background colour and text colour changes which is great, but the problem is that the background colour changes to 'yellow' for white backgrounds, and 'black' for green backgrounds.

Solution #

The default CSS/Jsp for the Brochure template looks like this for these classes (css_cached.jsp):
.portlet-section-body {
color: <%= colorScheme.getPortletSectionBody() %>;
background: <%= colorScheme.getPortletSectionBodyBg() %>;
}
.portlet-section-body-hover, TR.portlet-section-body:hover {
color: <%= colorScheme.getPortletSectionBodyHover() %>;
background: <%= colorScheme.getPortletSectionBodyHoverBg() %>;
}
 
.portlet-section-body A {
color: <%= colorScheme.getPortletSectionBody() %>;
}
 
.portlet-section-body-hover A, TR.portlet-section-body:hover A {
color: <%= colorScheme.getPortletSectionBodyHover() %>;
}
 
.portlet-section-alternate {
color: <%= colorScheme.getPortletSectionAlternate() %>;
background: <%= colorScheme.getPortletSectionAlternateBg() %>;
}
 
.portlet-section-alternate-hover, TR.portlet-section-alternate:hover {
color: <%= colorScheme.getPortletSectionAlternateHover() %>;
background: <%= colorScheme.getPortletSectionAlternateHoverBg() %>;
}
 
.portlet-section-alternate A {
color: <%= colorScheme.getPortletSectionAlternate() %>;
}
 
.portlet-section-alternate-hover A, TR.portlet-section-alternate:hover A {
color: <%= colorScheme.getPortletSectionAlternateHover() %>;
Which means if your CSS looks like this, then you need to change the values in liferay-look-and-feel.xml from your theme. There are two things that you can do, really:
1. Edit the CSS/Jsp to hard code your desired values. e.g.
.portlet-section-alternate-hover A, TR.portlet-section-alternate:hover A {
color: #SOMECOLOR;
} 
2. Edit the liferay-look-and-feel.xml file for the theme you are editing (recommended).
The Liferay look and feel file will have the following key-value pair references:
portlet-section-body=#3F3F3F
portlet-section-body-bg=#EAF2FF
 
portlet-section-body-hover=#FFFFFF
portlet-section-body-hover-bg=#5274AE
 
portlet-section-alternate=#3F3F3F
portlet-section-alternate-bg=#DBE1ED
 
portlet-section-alternate-hover=#FFFFFF
portlet-section-alternate-hover-bg=#5274AE
which affect the CSS classes you want. Notice how the names are reflected by the methods of the colorScheme object:
getPortletSectionAlternateHover() = portlet-section-alternate-hover = #FFFFFF
Edit those, redeploy the theme, or restart the server, and you should be ok.

Theme Development using the ViewDesigner Dreamweaver Plugin

Introduction #

ViewDesigner helps web designers to easily create or modify Liferay Themes. Web designers would be more comfortable with web designer tools like Dreamweaver (DW) / FrontPage(FP) to design the themes rather than using text based editors. The current approach of putting the css changes in the _diff folder, and doing an ANT to create the theme WAR is not what web-designers are used to.
ViewDesigner is an OpenSource Project licensed under CDDL. While it currently supports Windows, a Mac version will be available shortly. It will work with DreamWeaver 8, CS3 and CS4. You can download the plugin from here.

Setup #

  • Download DW from Adobe Downloads and install. Ensure that the DW Extension Manager is also installed.
  • Download the latest ViewDesigner Plugin from here
  • Install the plugin using the DW Extension Manager
    • Click File -> Install Extension -> Browse for the mxp file that you just downloaded, and click on OK
    • Accept the license, and you would get a message which says that the plugin is installed successfully.
  • Open Dreamweaver.
  • Click File -> Import. You would find "Import Web Space Theme File" menu item that is added
  • Similarily click File->Export, you would find "Export Web Space Theme File" menu item.
  • This confirms that the ViewDesigner Plugin has been installed successfully.

Downloading existing LR / Web Space Theme WAR File #

  • Using the PluginInstaller portlet , download any existing theme WAR. Add Plugin Installer Portlet -> Browse Repository Tab -> Theme Plugins Sub tab.
  • In LR 5.2 and Web Space 10.0 and above, you would have to do the above step using the Control Panel -> Plugins Installation -> Theme Plugins -> Install More themes.
  • You could alternatively download the theme WAR from plugins.liferay.com or from the SourceForge repository.

Importing the Theme WAR into Dreamweaver #

  • Click File -> Import->Import Web Space Theme File.
  • In the pop up window that appears, enter fill appropriate values for the following
    • Path to Web Space Theme file - point it to the LR / Web Space Theme-WAR that you just downloaded using the PluginInstaller.
    • Working folder of Web SpaceTheme file: - Any directory on your file system where you would want to extract the Theme WAR file.
    • Path to Java.exe: java.exe location. Once you mention this location, this value gets persisted, and shows up in this text box by default. You could change it if you want to.
  • Click on "Cancel" to close the "Import Web Space Theme File" dialog box.
  • Clicking on the "Help" button, opens up the Help page for doing the import.
  • Click on "Ok" button to import the WAR into Dreamweaver / CS.
  • The plugin now extracts the Theme WAR file in the specified Working Folder, and opens a sample preview page (index.html). This is just a preview page, and the changes made to this page wont be seen on the portal.

Modifying the Theme #

  • Now make the theme related changes that you want. The index.html page shows you a preview of the changes that you are making to the CSS files.
  • After doing all the desired changes, Click on File -> Save All.

Exporting the Theme WAR file after making changes #

  • Now click on File->Export->Export Web Space Theme File
  • Enter the following details
    • Working folder for Web Space Theme file: Folder where you extracted the Theme WAR file and made changes.
    • Save New Web Space Theme file To: Location on the Local File system where you would like the new modified WAR file to be created.
    • Path to Java.exe: Java.exe location on your local file system.
    • As soon as the user selects the "Working folder for Web Space Theme file:", the plugin reads the liferay-look-and-feel.xml and liferay-plugin-package.properties and populates the fields in the "Theme Properties:". The user might want to change them or leave them as it is before the Export operation. If the user wants to change any of the theme properties, he/she can enter the new values, and it gets persisted into the respective files.
    • Theme Id: The id of the theme.This gets persisted into the liferay-look-and-feel.xml
    • Theme Name: - The name of the theme. This is the name that gets displayed in the list of available themes. This gets persisted into the liferay-look-and-feel.xml and liferay-plugin-package.properties.
    • Theme Description: - A short description of the theme.This gets persisted into the liferay-plugin-package.properties.
    • Compatability Version: - The version of Liferay, this theme is compatible with. This gets persisted into the liferay-look-and-feel.xml
    • Author: - The author(eg company name) of the theme. This gets persisted into the liferay-plugin-package.properties.
    • Author URL: The author URL (could be the company URL). This gets persisted into the liferay-plugin-package.properties.
    • Theme Licence: The licence of the theme. This gets persisted into the liferay-plugin-package.properties.
  • Click on "Cancel" to close the "Export Web Space Theme File" dialog box.
  • Clicking on the "Help" button, opens up the Help page for doing the Export.
  • Click on Ok to export the Web Space theme WAR.
  • You would get a message confirming that the export was successful.

Deploying the Newly created Theme WAR #

  • Use the Plugin Installer Portlet to deploy this newly created theme WAR file.
    • Plugin Installer -> Upload File Tab -> Browse for the new WAR file -> Install.
    • For LR 5.2 and Web Space 10.0 and above use Control Panel -> Plugin Installations -> Theme Plugins -> Install More Themes -> Upload File -> Browse and upload this modified theme WAR
    • The new WAR file would be deployed now.
  • You could alternatively put this WAR file into LR / Web Space Hot Deploy directory and it would automatically be deployed.
  • Go to any community page, click on Manage Pages -> Look and Feel Tab. You would see the newly deployed theme in the list of available themes. Just click on the theme, to set it as the current theme for that community.

Plugin Log Messages #

  • The plugin log messages are written into ViewDesignerLogs.txt which is in <DW config folder>\Configuration\commands\WSThemingPlugin. In case of any errors during Import / Export operation, this file is automatically opened in the browser and shown to the user.

Known Issues#

  • The web designer (or the user) would have manually change the thumbnail.png and screenshot.png in the "images" folder before exporting the theme WAR file. Other wise the preview of the theme that shows in the portal page would be a stale one.
  • Currently the plugin cannot modify the vm(Velocity markup) files of the theme. We are working on building this feature into the plugin.
  • The index.html (the preview page) is a static page that the plugin adds to the theme WAR during import. The ideal way of doing this would be, that the portal creates the preview page, and packages it into the theme WAR, when we download the WAR file. We are working on this also.

Theme variations using CSS

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.
So I'll try to give a simple example for setting up a theme, named Custom Colors, with two color schemes (green and orange).

1) Create a liferay-look-and-feel.xml file in /plugins-sdk/themes/custom-colors-theme/docroot/WEB-INF:

<?xml version="1.0"?>
<!DOCTYPE look-and-feel PUBLIC "-//Liferay//DTD Look and Feel 5.2.0//EN" "http://www.liferay.com/dtd/liferay-look-and-feel_5_2_0.dtd">

<look-and-feel>
<co­mpatibility>
<version>5.2.0+</version>
</compatibility>
<theme id="custom-colors" name="Custom Colors">
<color-scheme id="01" name="Green">
<css-class>green</css-class>
</color-scheme>
<color-schem­e id="02" name="Orange">
<css-class>orange</css-class>
</color-scheme>
</theme>
</lo­ok-and-feel>

2) Create your css files:
/plugins-sdk/themes/custom-colors-theme/docroot/_diffs/css/color_schemes
-> green.css
-> orange.css

3) Open /plugins-sdk/themes/custom-colors-theme/docroot/_diffs/css/custom.css

4) Add these two lines to the top of custom.css:
@import url(color_schemes/green.css);
@import url(color_schemes/orange.css);

5) If you plan on changing out the images make sure you create:
/plugins-sdk/themes/custom-colors-theme/docroot/_diffs/images/color_schem­es
-> /green
-> /orange

6) Run the ant build for your theme and you should be good to go

The big thing to note here is that you must import your color scheme css files. I assumed that Liferay would include the appropriate CSS file for me, but that does not happen.

Themes (WAP)

Themes customize the overall look and feel of Liferay and were introduced in version 3.5 of the portal. With Liferay version 4.3, we now have a WAP theme that is designed to run on mobile devices.

Overview #

To find out where to start, look at liferay-look-and-feel.xml found in the \trunk\portal-web\docroot\WEB-INF\ folder.
        <theme id="mobile" name="Mobile">
              <root-path>/wap/themes/${theme-id}</root-path>
              <wap-theme>true</wap-theme>
       </theme>
This is very similar to our other themes except it has this attribute:
 <wap-theme>true</wap-theme>
This tells the portal that the theme was developed for a mobile device.
You also notice the addition of a wap folder in \trunk\portal-web\docroot\.
To make a theme show up correctly in a mobile device, you need this doc type:
 <?xml version="1.0"?>
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.1//EN" "http://www.wapforum.org/DTD/xhtml-mobile11.dtd">
Make sure all your tpl, jsp, and VM files adhere to this standard.
New template files have been created for mobile display. If you look at liferay-layout-templates.xml. You see entries for for *.wap.tpl files like the follow:
 <wap-template-path>/html/layouttpl/custom/1_column.wap.tpl</wap-template-path>
In the 4.3 \trunk\themes\ folder, you'll find a sample wap theme called sample-base-wap-theme.war. Use this as your template for custom wap themes.

Database Changes#

The Layout table also has addition fields for wapThemeId and wapColorSchemeId.

Themes v4.0-v4.2

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

Overview #

It is a collection of .jsp or velocity templates that contain fragments of the various components that make up the HTML sent to the client browser. Though most theme template bundles contain a variety of template files, the "required" template files are:
  • portal_normal.vm Controls the layout of portal templates for "normal" pages
  • portal_pop_up.vm Controls the layout of portal templates for "pop-up" pages
portal_init.vm is not really a required template, but by convention, it exists, and is included by both the portal_normal and portal_pop_up template.
NOTE: It appears that Velocity is now the template engine of choice. The Velocity context is created and initialized in com.liferay.taglib.util.ThemeUtil.includeVM().
A theme can have one or more "color schemes", which gives even more flexability to the look and feel of a theme. The Ant script /portal/portal-web/build.xml contains the target build-color-scheme that is capable of generating images that match a color scheme (using the services of com.liferay.portal.tools.ColorSchemeBuilder).
The themes that are available to a portal are described in WEB-INF/liferay-look-and-feel.xml (as well as WEB-INF/liferay-look-and-feel-ext.xml). These themes are read in by com.liferay.portal.service.impl.ThemeLocalUtil. Theme definitions are held in in-memory collections of com.liferay.portal.model.Theme objects (and not in the database).
Themes can be limited to certain company Ids (by including or excluding the themes in the <company-limit> section of WEB-INF/liferay-look-and-feel.xml).
Themes can be either part of the build, or "hot deployable." A "Hot deployable" theme is simply the theme(s) directory(ies) bundled up into a .WAR file with the WEB-INF directory containing the liferay-look-and-feel.xml that describes the theme(s). A hot deploy theme bundle can contain more than one theme.
The basic structure of a theme directory (whether in a .WAR, or part of the build) is: Root theme directory: /html/themes/<nameOfTheme> Image files used by theme: <themeRoot>/images Templates that describe the themes: <themeRoot>/templates
Generally speaking, themes are not layed out in tables. Best practice has placing visual elements inside of tags, then defining background, position, etc. of these elements in <themeRoot>/templates/css_cached.vm

Upgrade to 4.2.x #

Any upgrade to a theme from versions 4.0-4.1.3 to 4.2.x must change the following files:

WEB-INF/liferay-look-and-feel.xml#

1. Change version number to 4.2.1 (or whatever version you're upgrading to) resulting in:
 <version>4.2.1</version>

css_cashed.vm#

1. Add:
 .pop-up-outer { border: 1px solid #383838; background-color: #FFFFFF; }
.pop-up-inner { border: 1px solid #747474; }
.pop-up-header { background-color: #000000; height: 25px; }
.pop-up-title { color: #FFFFFF; font-weight: bold; padding-left: 10px; }
.pop-up-close a { color: #FFFFFF; margin-right: 7px; white-space: nowrap; text-decoration: underline; }
2. At this block of code:
 .portlet-box {
   height: auto;
   text-align: center;
   #if ($browserSniffer.is_ie_5_5_up($request))
     height: 100%;
     filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='$themeDisplay.getPathThemeImage()/custom/portlet-bg.png',         
     sizingmethod='scale');
   #else
     background-image: url($themeDisplay.getPathThemeImage()/custom/portlet-bg.png);
   #end
     background-color: $colorScheme.getPortletBg();
}
Delete line "text-align: center;" resulting in:
 .portlet-box {
   height: auto;
   #if ($browserSniffer.is_ie_5_5_up($request))
     height: 100%;
     filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='$themeDisplay.getPathThemeImage()/custom/portlet-bg.png',         
     sizingmethod='scale');
   #else
     background-image: url($themeDisplay.getPathThemeImage()/custom/portlet-bg.png);
   #end
     background-color: $colorScheme.getPortletBg();
}

portal_normal.vm#

1. Delete 2 lines:
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
:and
 {{{"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
}}}
2. At this block of code:
 #if ($themeDisplay.isShowPageSettingsIcon())
  <a href="$themeDisplay.getURLPageSettings().toString()">$languageUtil.get($pageContext, "page-settings")</a>
#end
:Add another link resulting in:
 #if ($themeDisplay.isShowPageSettingsIcon())
  <a href="$themeDisplay.getURLPageSettings().toString()">$languageUtil.get($pageContext, "page-settings")</a> - 
  <a href="javascript: void(0);" onClick="$themeDisplay.getURLLayoutTemplates()">$languageUtil.get($pageContext, "layouts")</a> 
 #end
3. At this block of code:
 {{{ <div id="layout-my-places">
  #set($myPlacesPortlet = $staticFieldGetter.getFieldValue("com.liferay.portal.util.PortletKeys", "MY_PLACES"))
  $taglibLiferay.runtime($myPlacesPortlet)
</div>
}}} :Add align=right to div resulting in:
 {{{ <div id="layout-my-places" align=right>
  #set($myPlacesPortlet = $staticFieldGetter.getFieldValue("com.liferay.portal.util.PortletKeys", "MY_PLACES"))
  $taglibLiferay.runtime($myPlacesPortlet)
</div>
}}}

portlet_top.vm#

1. At this block of code:
 {{{<table border="0" cellspacing="0" cellpadding="0" width="100%" onMouseOver="toggleById('portlet-small-icon-bar_$portletId', true)"   
 onMouseOut="toggleById('portlet-small-icon-bar_$portletId', true)">
}}} :Add class="portlet-header-bar" resulting in:
 {{{<table class="portlet-header-bar" border="0" cellspacing="0" cellpadding="0" width="100%" 
  onMouseOver="toggleById('portlet-small-icon-bar_$portletId', true)" onMouseOut="toggleById('portlet-small-icon-bar_$portletId',  
  true)">
}}}

Themes v4.3-v5.2.x

Introduction #

Themes customize the overall look and feel of Liferay. They since version 4.3 are written using the plugins SDK and the templating language Velocity.

Deploying a Theme#

There are two methods to deploying a theme in Liferay. First you can download a prepackaged theme from the Software Catalogue Portlet or you can deploy a theme from a packaged WAR you have downloaded.

Deploying from the Software Catalogue#

To do so place the Software Catalogue Portlet on a page. You can find the Software Catalogue by going to the Dock and selecting the Add Application from the drop down menu. When the list of applications load, you'll find Software Catalogue in the Admin section.
Alternatively, if you are running Liferay 5.2.0 you can also access the Software Catalogue in the Control Panel. Both options will require you to have the proper permissions to be able to install a theme.
From the Software Catalogue Portlet you can search or browse for a new theme.

Deploying a Packaged Theme WAR#

To deploy a packed theme WAR you'll need access to the directory that Liferay listens to for auto deployment (by default this directory is the user folder). Simply copying the theme WAR file in this directory will deploy your theme.

Developing a Theme#

Installing the Plugins SDK#

As of Liferay 5.1, themes are built on top of default "styled" and "unstyled" themes.
To build a theme start by downloading and unzipping the Liferay Plugins SDK. Also see the Liferay Plugins Development Guide to set up your plugins environment.
Create a build.{username}.properties file in your SDK directory replacing {username} with your systems username. Then, add this line to the code within the file:
  app.server.dir={path to your app server}
You are now ready to create you blank theme! From the command line, navigate to the plugins/themes directory and type:
For windows:
create <project name> "<theme title>"
For Linux/Mac:
./create.sh <project name> "<theme title>"
Where <project name> is what your theme will be called within the file structure, and <theme title> is the text that will actually be displayed within the liferay portal in the Available Themes list. The second parameter must have quotes around it to allow spaces in the name of the theme.

Writing Your Theme#

Now that your new theme has been created, you're ready to modify the default styling.
Inside the newly created theme you'll find several directories, one of which is called _diffs (located in docroot). In here you can overwrite any of the files that would be automatically created for your theme. Below are some of the files that can be overwritten.
/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)
At the very least you'll need to modify the custom.css file to change the way your theme looks. We highly recommend that all changes be made to custom.css since the other css files are used to provide structure to your theme. To do this, in the _diffs folder create the "css" folder and save "custom.css" into this directory.
Likewise, for any javascript functionality creating the javascript.js file will also get included in your theme.

Browser/OS Consistency#

As a theme developer you'll notice the inconsistency of how your theme is rendered in multiple browsers (and even operating systems). If you find that you need to make a browser, or OS specific modification, these CSS class selectors are available to use:
Selecting different browsers would be like so:
  .ie h1{}
  .gecko h1{}
  .safari h1{}
  .ie6 h1{}
  .ie7 h1{}
  .konqueror h1{}
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{}

Velocity Templates#

Velocity templates control the different HTML of the portal using Apache Velocity Templates. We recommend that you view their docs to see how they are written.
  • portal_normal.vm - This file controls the basic skeleton HTML of the page Liferay will serve.
  • dock.vm - This provides the drop down dock on the page.
  • init_custom.vm - This file allows you to override and define new velocity variables.
  • navigation.vm - This file is called by portal_normal.vm and provides the HTML to make the navigation bar.
  • portal_pop_up.vm - This file handles the pop up notification for Liferay.
  • portlet.vm - This file wraps the content of very portlet.
With the combination of HTML and Velocity you can restructure how the HTML is served.

Properties#

You probably have already noticed that there is another directory besides the _diffs folder in your theme. The WEB-INF could hold many important configuration files but we'll be looking at one important properties file.
You'll notice that the create script automatically created a liferay-plugin-package.properties file. Opening it with your favorite text editor will allow you to edit such information as the license, author, etc. You'll notice that some of the information has been auto populated.
The first thing you'll want to do is replace your name with for "Liferay, Inc." on the author field.
Change as many values as you'd like and save this file.

Finished!#

You should now have completed your first theme. To deploy your theme type,
ant deploy
from the command line in your theme folder. This will deploy your theme for you and all your users to enjoy.
Note: it is much easier to develop your theme if you first deploy the blank template and modify the files in the webapps folder of your Liferay installation and copy them back into the _diffs folder. If you choose to take this approach be sure to turn caching off for Liferay on your development machine. See Liferay Developer Mode for more information.

Quality Control#

These are the steps to ensure that your theme will look good in some of the less visable areas of Liferay Portal.

Presentation and Legibility#

Thankfully, Liferay portal has been designed so that majority of the themed elements share properties, making the styling process very quick. That being said, there are certain portlets that are good to check on while you are theming to get a sampling of the whole.
  • Calendar Portlet - theming the tabs and dates of the summary, month, and week tabs
  • Page Comments Portlet - theming the heading and odd and even fields
  • Currency Converter - theming the table
  • Document Library - theming the iframe that is used for the classic uploader
Also if you choose light colored text or dark backgrounds in your theme you will want to check these portlets/elements:
  • Add Application module
  • Layout Template module
  • Quick Note Portlet
  • Sign In Portlet when signed out
  • Success and failure messages
  • Dock controls

Advanced#

Color Schemes#

See Theme variations using CSS for instructions on how to create a color scheme.

Theme Conventions#

CSS Conventions#

Here are CSS formatting conventions that will make sure your code is consistent, and easily readable:
  • Outside of selector bodies:
    • Group selectors under the common element that they style using comment tags
    • Keep global selectors towards the top, and more specific selectors towards the bottom
    • Keep only 1 endline between all selectors and comments
  • Inside selector bodies:
    • Insert 1 space between selector name and opening "{"
    • For using multiple selectors for the same body of declarations, separate selectors with "," and 1 endline
    • All declarations are indented by one tab
    • Keep all declarations in alphabetical order within the declaration body
    • For each declaration, be sure to put 1 space between the property and the value, after the ":"
    • Colors should only be specified by using their hexidecimal value.
    • Use all caps for hexidecimal values, and condense to 3 digits whenever possible
    • For the "background" property, make sure there is no space between "url" and opening "("
    • No quotes are required when using url() or for font names, unless using fonts that aren't browser-safe
    • Insert spaces after commas between font names
    • When using urls, always use a relative address instead of absolute
    • Condense all padding,margin, and border values whenever possible, leaving out measurement units on "0" values (i.e. px, pt, em, % etc)
    • Comments are only used to head and divide each section of the code appropriately. Comments without any content below it are not necessary.
    • Use shorthand properties where applicable.

Filename Conventions#

  • Use Conventional names when saving image files
  • Use underscores only in file names - no dashes

Related Articles#


Themes v6.0

Introduction #

Themes customize the overall look and feel of Liferay. They are written using the plugins SDK and, since version 6.0, can be written using one of the templating languages, Freemarker or Velocity.

Deploying a Theme#

There are two methods to deploying a theme in Liferay. First you can download a prepackaged theme from the Software Catalogue or you can hot deploy a theme from a WAR.

Using the Software Catalogue#

You can also access the Software Catalogue in the Control Panel under "Plugins Installation". From there you can search or browse for a new theme.

Hot Deploying a WAR#

To deploy a packed theme WAR you'll need access to the directory that Liferay listens to for auto deployment (by default this directory is the user folder). Simply copying the theme WAR file in this directory will deploy your theme.

Developing a Theme #

Prerequisites #

  • Plugins SDK for your Liferay version.
    • The plugins SDK is needed because it generates a framework. You don't need to use any fancy editors or install anything crazy though -- an SDK is simply a bunch of files and scripts that make your life easier. You can download the SDK from the Liferay main page, unzip it, set up the file called build.username.properties, and you're good to go. You simply need it to do the first step -- everything after that is what you already know: CSS in your editor of choice. Don't get scared because it's called an SDK!
  • Good understanding of CSS (you cannot edit the HTML -- only CSS can be modified to style Liferay)

Recommended Tools #

Writing your Theme #

  1. Navigate using command prompt or terminal to the $PLUGINS_SDK/themes folder. Run:
 create newtheme "My New Theme" 
or, on Linux/Mac:
 
./create.sh newtheme "My New Theme"
  1. Navigate to the newly created $PLUGINS_SDK/themes/newtheme/_diffs and add some customizations to the default theme. The way to do this is to create a directory called 'css' in _diffs, then add/edit the file css/custom.css. Liferay doesn't allow you to directly modify the "base" CSS -- you can however hide elements at will using CSS (display:none;) and move them around to your liking. This follows the principle for separation of content and style.
  2. Issue 'ant all' in the $PLUGINS_SDK/themes/newtheme folder to build and deploy.
  3. Log in into Liferay and check out your new creation.
Your modifications to the theme should go into the css/custom.css file in the _diffs folder. All the changes you make in other css files will be overwritten when you deploy the theme again.
Side tip for non-noobs (power users): If you want your theme to be developed from an existing theme other than the classic plain theme, you can modify the file build.xml (inside the folder of the theme) and change the parent.theme attribute to the id of the theme you want it to be copied from (for example, classic) and then deploy again. Generally you just want to use the basic plain Liferay setup however, because it's pretty empty and you style everything yourself.
The theme's folder is set up like this:
/THEME_NAME/
    /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

Additional Notes #

  • Liferay's theming process is pretty unique: a pre-made theme, the "_unstyled" theme (default) is applied first when you create a new theme (when you do create newtheme "My New Theme"). In fact, try creating a theme but not adding any _diffs files -- you'll see that the site is still styled! That's because it's the "_unstyled" theme, which does give your site minimal structure. It looks very plain though. That's because it's ready for you to make your modifications.
  • On top of the classic theme's code, you add your own styles, images, dock customizations and et cetera by creating the above directory structure in your theme _diffs folder. If you don't want to overwrite a file (you like the classic/default way it looks), you don't have to. If you want to rewrite everything, you can do that too. Liferay is super flexible. Say you want to change something in the dock. Open up dock.vm from the classic theme, and make your modifications. Save it to your _diffs (take care that you put it in the right directory, e.g custom.css goes in yourtheme/_diffs/css/custom.css) and you should have a functional theme.

Dockbar #

A lot of questions are asked about the Dockbar. Starting in Liferay 6.0.x, the dock was moved to being a portlet instead of something directly in themes. What that means is that dock.vm no longer exists: instead, to edit dockbar requires that you create a hook or ext plugin that overrides the dockbar's JSP or whatever else you're seeking to change. It sounds involved, but it really isn't hard -- once you've created the new hook, you simply overwrite whatever you want on the JSP or other files.
Styling the dockbar is easy still too, since the CSS is all in dockbar.css.
Creating the links on the dockbar while removing the dockbar itself is a common request also. For more information on linking dockbar items, see Link to Dockbar

Link to Dockbar


Introduction #

For a lot of Liferay implementations, the dockbar needs to be hidden and the "Add Application" button and the "Layout Templates" button need to be placed on the site body. Unfortunately, doing that has not been the easiest thing to figure out. Fortunately, there does exist an easy way to do it.

Code #

If you place this code anywhere in portal_normal.vm, it links to the "Add Application" container as well as the "Layout Templates" container.
<!-- This can be placed anywhere in the portal_normal.vm -->
<a href="javascript:;" id="addApplications">Add Application</a>
<a href="javascript:;" id="layoutTemplates">Layout Templates</a>
<script type="text/javascript">
        AUI().use(
               'aui-dialog',
               'liferay-layout-configuration',
               function(A) {
                       // Create the Add Applications dialog
                       var addApplicationsDialog = new A.Dialog({
                               title: 'Add Application',
                               width: 280,
                               visible: false
                       }).plug(A.Plugin.IO, {
                               after: {
                                      success: function(event, id, obj) {
                                              Liferay.LayoutConfiguration._dialogBody = addApplicationsDialog.get('contentBox');
                                              Liferay.LayoutConfiguration._loadContent();
                                      }
                               },
                               autoLoad: false,
                               data: {
                                      doAsUserId: themeDisplay.getDoAsUserIdEncoded(),
                                      p_l_id: themeDisplay.getPlid(),
                                      p_p_id: 87,
                                      p_p_state: 'exclusive'
                               },
                               showLoading: false,
                               uri: themeDisplay.getPathMain() + '/portal/render_portlet'
                       });
 
                       // Attach the click listeners to the links
                       A.one('#addApplications').on('click', function(event) {
                               addApplicationsDialog.render().show().io.start();
                       });
 
                       A.one('#layoutTemplates').on('click', function(event) {
                               Liferay.LayoutConfiguration.showTemplates();
                       });
               }
        );
</script>

Using Custom Permissions in Theme

Introduction #

Our goal is to add a custom permission to Liferay that can be used to control access/visibility to resources in the Velocity templates in a custom theme. This allows an administrator to manage access through the front-end of the software, in a manner they are probably already familiar with. In our example, we'll create a role that will be used to determine if a user can see the dock, but these principles could be applied to many other scenarios
This article assumes that you have already configured your Plugins SDK environment and downloaded the Liferay Portal source code.

Creating a custom theme #

  • From a command prompt, navigate to the plugins/themes directory
  • Create a new them using the following command:
create dock-permissions "Dock Permissions"
  • Change your directory to dock-permissions-theme and deploy your new theme using the following command:
ant deploy
  • Watch the command window and the console to ensure the theme is deployed and registered successfully and available for use.
  • Log in to Liferay and from the Dock, select Manage Pages.
  • Select the Look and Feel tab and choose your new Dock Permissions theme.
  • The theme will change to a very unstyled look and feel
You have now created and deployed a new custom theme. At this point, it's not very usable because it has no styling associated with it. For the purposes of this example, we're going to copy the styling that's applied to the Liferay classic theme.
  • Using your file explorer, navigate to your portal source code folder,
  • Copy the contents of the portal-web\docroot\html\themes\classic\_diffs directory to plugins\themes\dock-permissions-theme\docroot\_diffs
  • From the command prompt, deploy the dock-permission-theme again.
  • Refresh your browser and you should see the dock-permission-theme looks just like the Liferay Classic theme.

Customizing the Resource Actions #

We'll be making use of Liferay's Permission System to control who will see the Dock in our custom theme. Liferay's Permissions system is based on the concepts of actions and resources. In our case, we'll be adding the action VIEW_DOCK to the com.liferay.portal.model.Layout resource.
The resource-actions for a portlet are stored in the /resource-actions/$portletname.xml file. We need to modify the resource actions that are associated with the communities portlet, so we'll be modifying the /resource-actions/communities.xml file. This file is embedded in the portal-impl.jar, and should not be modified. Instead, we will create a new communities.xml file in the /WEB-INF/classes/resource=actions folder of our Liferay installation.
  • In a command prompt window, navigate to your /webapps/ROOT/WEB-INF/lib folder.
  • In this folder is the portal-impl.jar file. To extract the communities.xml file from this .jar, issue the following command:
jar xvf portal-impl.jar resource-actions/communities.xml
  • The communities.xml file will be extracted to a resource-actions folder in the lib directory.
  • Copy the resource-actions folder from the lib directory to /webapps/ROOT/WEB-INF/classes
  • Open /webapps/ROOT/WEB-INF/classes/resource-actions/communities.xml with a text editor.
  • Add the following line to the <supports> section of the <model-resource> section (approximately line 28):
<action-key>VIEW_DOCK</action-key> 
  • Save the file, then stop and restart Liferay.

Creating a custom role #

The VIEW_DOCK permission is now part of the My Communities portlet and can be added to any existing role. For this example, we'll create a new role called Dock-Users and assign this new permission.
  • Navigate to the Control Panel and select Roles under the Portal heading.
  • Click the Add button
  • Enter Dock-Users for the name and provide a description.
  • Click Save.
  • Click the Actions button that corresponds to the Dock-Users role and select Define Permissions.
  • Click the Add Portlet Permissions, and select the My Communities portlet.
  • In the Page section, find the action.VIEW_DOCK entry and set the scope to Enterprise.
  • Click Save, then click the Roles link in the breadcrumb trail.
  • Click the Actions button that corresponds to the Dock-Users role again and this time select Assign Members.
  • Assign some users to this new role and save.

Checking Permissions in a Theme #

The last step is to check for our new permission inside our custom theme. This would be done in one of the Velocity templates. In our example, we want to hide the entire Dock for users that don't have the VIEW_DOCK permission, so we'll create a variable called $show_dock that can be used to determine if the Dock should be displayed.
  • Create a new folder called templates at plugins/themes/dock-permissions-theme/docroot/_diffs
  • Copy init_custom.vm and portal_normal.vm from plugins/themes/dock-permissions-theme/docroot/templates to /themes/dock-permissions-theme/docroot/_diffs/templates
  • Add the following line to _diffs/templates/init_custom.vm:
#set ($show_dock = $layoutPermission.contains($permissionChecker, $getterUtil.getLong($plid), "VIEW_DOCK"))
  • In the _diffs/templates/portal_normal.vm, replace the following code:
#parse ("$full_templates_path/dock.vm")
with
#if ($show_dock)
  #parse ("$full_templates_path/dock.vm")
#end
  • Re-deploy your theme.
Prior to log in, the Dock should no longer be visible. Once logged in, users that are members of the Dock-Users role will now be able to see the Dock. For all others, the Dock should not be visible.
Note, if you hide the Dock from users, you will have to provide some other means for them to sign out.

References #

Plugins SDK
http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Plugins+SDK
Using Liferay's Permissions System from a portlet
http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Using+Liferay%27s+Permission+System+from+a+portlet
Overwrite Liferay Portlet Permissions
http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Overwrite+Liferay+Portlet+Permissions
Permissioning Explained
http://www.liferay.com/web/guest/community/wiki/-/wiki/Main/Permissioning%20Explained


72 comments:

  1. can you explain about .sass-cache folder in theme. When I build theme with maven build, the .sass-cache folder contains some css files which are NOT same as my source css files e.g: mainstyle.css. It contains different code in it. Sometimes it loads css files from that folder instead of my source css files. This conflict leads me to do server restart which is havoc. Can you please explain a solution ?

    ReplyDelete
    Replies
    1. I use liferay 6.2.0 sp1 enterprise edition

      Delete
  2. Awesome post about liferay its really great...

    ReplyDelete
  3. Theme customization is the major part of website creation segment.Choosing correct themes only give the exact layout and structure to the website.
    Web Design Company | Website Designing Companies

    ReplyDelete
  4. Very Helpful post.
    Great work Himanshu.

    ReplyDelete
  5. I appreciate your efforts in writing a long post to help the developers.
    It is a very informative post to learn liferay theme Development.

    ReplyDelete
  6. Very nice post thanks for this information
    we are custom facebook apps developer you can contact to JaK Technology .
    Thanks you

    Custom Facebook Apps Development

    ReplyDelete
  7. Thank you for sharing such useful stuff and very much appreciable.
    http://cctvinstallation.in

    ReplyDelete
  8. Thanks for this collection :) it always help to make new creative ideas and designs

    ReplyDelete
  9. Very nice and help ful for Service builder i found this one also helpful
    http://liferayiseasy.blogspot.in/search/label/service%20builder

    ReplyDelete
  10. Fantastic information. Thanks regarding offering people such a helpful information
    check writing software | inventory management software dubai

    ReplyDelete
  11. If you want some tutorial on liferay hook you may visit
    http://liferayiseasy.blogspot.in/search?q=hook

    ReplyDelete
  12. Nice tutorial!
    I have make some new liferay theme, you can download free at www.liferaytheme.com

    ReplyDelete
  13. http://edusparkle.com
    http://quizexpo.com
    http://patnauniversity.quizexpo.com

    ReplyDelete
  14. Amazing post dude.It will be very helpful for begginers like me.Thank you very much for this important post.Waiting for your next post.You can visit our site to get awesome
    html templates

    ReplyDelete
  15. Thanks for the post. Hope so that this tutorial of yours work well for me. People who are finding it difficult to design their front end may also take help from the after effects templates that are specially designed according to the needs and the demand of the project. They are more impressive and effective then any other normal template.

    ReplyDelete
  16. Thanks for sharing such unique information which are in actual fact as well as helpful for us.Keep it up.....
    Web Design Bangalore | Web Design Companies Bangalore

    ReplyDelete
  17. Positive site, where did u come up the information on this have read a few of the on your website now, and I really like your style. Thanks a million and please keep up the effective work.
    SEO services pakistan

    ReplyDelete
  18. Hi I have created a dashboard theme and how to connect with Single page application.
    Please help me.

    ReplyDelete
  19. How to integrate social login and sharing on my Magento e-commerce site?
    Magento Hide Price

    ReplyDelete
  20. Very Great Post..Am impressed..and also am learned lots of information in your article..Thank you sharing the useful information....Website Designing Services Bangalore | Website Development Services in Bangalore

    Nexevo Technologies Blog: Website Design Company in Bangalore | Website Development Company in Bangalore

    ReplyDelete

  21. Thanks for give me this information really this product is very effective.

    Custom Software Development India - Nintriva

    ReplyDelete
  22. I really appreciate information shared above. It’s of great help. If someone want to learn Online (Virtual) instructor lead live training in liferay, kindly contact us http://www.maxmunus.com/contact
    MaxMunus Offer World Class Virtual Instructor led training on liferay. We have industry expert trainer. We provide Training Material and Software Support. MaxMunus has successfully conducted 100000+ trainings in India, USA, UK, Australlia, Switzerland, Qatar, Saudi Arabia, Bangladesh, Bahrain and UAE etc.
    For Demo Contact us.
    Nitesh Kumar
    MaxMunus
    E-mail: nitesh@maxmunus.com
    Skype id: nitesh_maxmunus
    Ph:(+91) 8553912023
    http://www.maxmunus.com/


    ReplyDelete
  23. Thank you for sharing such an informative news with us. Keep on sharing Contents like this. You can also share this content on various sites like the Automation Associates LLC site.

    ReplyDelete
  24. Thank you for sharing this excellent post. The post is handy and useful. You can also share these type of posts in the platforms like Wordpress, the famous Blogspot site, the all favorite Tumblr site and also in the location like Medium and lastly to the Live Journal site.

    ReplyDelete
  25. This is the kind of post I was searching for today. Awesome post and very useful and easy to read. Thank you for sharing this wonderful; post. You can also share these post on the Social media's like Google Plus, the all time hit Facebook, the notorious Twitter, the business sharing site LinkedIn and lastly to the famous Infographic site Pinterest to gain more traffic to your blog post.

    ReplyDelete


  26. Really nice information. It is very useful and informative post. Thanks for sharing.


    Mobile & Analytics

    ReplyDelete
  27. Thanks For Your valuable posting, it was very informative
    toshiba q300 interne ssd

    ReplyDelete
  28. • Nice and good article. It is very useful for me to learn and understand easily. Thanks for sharing your valuable information and time. Please keep updatingAzure Online course Hyderabad

    ReplyDelete
  29. It is extremely nice to see the greatest details presented in an easy and understanding manner.
    Web Development Services in Bangalore
    Website Design and Development Services in Bangalore

    ReplyDelete
  30. Hi,

    Thanks for sharing a very interesting article about Theme complete tutorial. This is very useful information for online blog review readers. Keep it up such a nice posting like this.

    From,
    Maestro Infotech,
    Web Design Company Bangalore

    ReplyDelete
  31. Thanks for the post, I am techno savvy. I believe you hit the nail right on the head. I am highly impressed with your blog.
    It is very nicely explained. Your article adds best knowledge to our Java Online Training from India.
    or learn thru Java Online Training from India Students.

    ReplyDelete
  32. Thanks for sharing amazing information !!!!!!
    Please keep up sharing.

    ReplyDelete
  33. Amazing post.Thanks for your details and explanations..I want more information from your side.Thank you
    Trading erp software in chennai

    ReplyDelete
  34. thank you so much, sir for Sharing this informative blog

    ReplyDelete
  35. It is nice blog Thank you porovide important information and i am searching for same information to save my time Ruby on rails Online

    ReplyDelete
  36. Hi! Thank you for the share this information. This is very useful information for online blog review readers. Keep it up such a nice posting like this.
    Website Design
    SEO Company

    ReplyDelete
  37. Hi! Thank you for the share this information. This is very useful information for online blog review readers. Keep it up such a nice posting like this.
    Website Design
    SEO Company

    ReplyDelete
  38. Amazing Article ! I have bookmarked this article page as i received good information from this. All the best for the upcoming articles. I will be waiting for your new articles. Thank You ! Kindly Visit Us @ Coimbatore Travels | Ooty Travels | Coimbatore Airport Taxi | Coimbatore taxi

    ReplyDelete
  39. Your very own commitment to getting the message throughout came to be rather powerful and have consistently enabled employees just like me to arrive at their desired goals.
    Best Devops Training in pune
    Data science training in Bangalore

    ReplyDelete
  40. Useful information.I am actual blessed to read this article.thanks for giving us this advantageous information.I acknowledge this post.and I would like bookmark this post.Thanks
    Selenium training in Chennai
    Selenium training in Bangalore
    Selenium training in Pune
    Selenium Online training

    ReplyDelete
  41. This comment has been removed by the author.

    ReplyDelete
  42. Information from this blog is very useful for me, am very happy to read this blog Kindly visit us @ Luxury Watch Box | Shoe Box Manufacturer |  Candle Packaging Boxes | Wallet Box

    ReplyDelete
  43. I have to search sites with relevant information on given topic and provide them to teacher our opinion and the article.

    state employee cashless treatment scheme

    ReplyDelete
  44. Truly, this article is really one of the very best in the history of articles. I am a antique ’Article’ collector and I sometimes read some new articles if I find them interesting. And I found this one pretty fascinating and it should go into my collection. Very good work!

    senior citizen saving scheme

    ReplyDelete
  45. An effective setup could be venues providing testing infrastructure and sending data to the event app. virtualedge and thank you for attending birthday party

    ReplyDelete
  46. css founder is the right way to build your business website. We are known as the best Web Design Company in Navi Mumbai, we have delivered 4500+ projects across the world. You may connect with us for more information.

    ReplyDelete
  47. We are providing the best smartphone insurance. Connect with us (Your Mobile Insurance) to get the best and fast replacement and repair service.

    ReplyDelete
  48. We are the best provider of tent rental in Dubai, UAE. Connect with us if you are looking for the best tents for rent. We can be the right choice for you.
    Outdoor Sun Shades Rental Dubai

    ReplyDelete
  49. We are known as the best web design company in navi mumbai that have delivered many successful projects across the world. We can be the right choice for you. Connect with us for more information.

    ReplyDelete
  50. Really amazing information, thanks for your efforts for this blog. Thank you so much for sharing this post
    Car Parking Shades Supplier

    ReplyDelete
  51. Connect with the best SEO Company in Mumbai that can provide you fully digital marketing solution at an affordable price. Connect with us for more information.

    ReplyDelete
  52. Need professional WordPress Web Design Services? We're experts in developing attractive mobile-friendly WordPress websites for businesses. Contact us today! https://just99marketing.com/wordpress-web-design

    ReplyDelete
  53. “Though fancy may be the patient’s complaint, necessity is often the doctor’s. Medical Centre in Dublin - Thorndale Medical Clinic

    ReplyDelete
  54. Use CSS Founder's website price calculator and check your Website development cost free.

    ReplyDelete
  55. Article intéressant et très instructif sur Liferay. Aide beaucoup. Nous proposons également les services Liferay Angular. Contactez-nous pour obtenir plus de détails

    ReplyDelete
  56. Welcome to VisitsVisa, your trusted source for all things related to India visa applications. As one of the leading visa service providers, we understand the importance of a seamless and hassle-free visa application process. Whether you are traveling for business or leisure, obtaining an India visa is an essential step.

    ReplyDelete
  57. To attract customers, a web design company in Pune should prioritize an attractive and user-friendly interface. The website should convey the brand identity intuitively using attractive graphics and intuitive navigation. Responsive design is important to ensure optimal performance across all devices. Including strategic calls-to-action and easy-to-find contact information increases user engagement.

    ReplyDelete