The Liferay CMS provides built-in layout templates which are sufficient for most of the requirements of a portal page. Sometimes we may need to design a custom page template that meets our requirements. We can achieve this with the Liferay layout template plugin.
In this article, we will learn about the Liferay layout templates and how to create custom layout templates.
Version details: Liferay 6.2
Table of Contents
- Creating the liferay layout template
- Designing the layout template
- Complete liferay template code
- Testing the output
- Conclusion
Creating the liferay layout template
We will use the Liferay Developer Studio(LDS) IDE to create the Liferay layout template.
Create a new plugin project from File >> New >> Liferay Plugin Project. Enter the project name, select the plugin type as Layout Template, and click on the Finish button.

The below image shows the folder structure of the Liferay layout template.

A few of the files of the Liferay layout template project are listed below.
- liferay-layout-templates.xml: This is the file that specifies the name and the location of the template files. The file also specifies the thumbnail image location.
- projectname.tpl : Generates the HTML structure(myLayoutTemplate.tpl).
- projectname.wap.tpl : Generates the HTML structure for mobile devices(myLayoutTemplate.wap.tpl).
- projectname.png : The thumbnail image for layout template in the .png format(myLayoutTemplate.png).
- liferay-plugin-package.properties : Defines the plugin project properties.
Designing the layout template
Initially, the generated layout template project files are empty.
With the Liferay IDE, we can use the default layout templates as a reference and modify them according to our requirements.
We can select the design mode of the .tpl file to add the available sample design to our template file while using the LDS IDE.
Designing the custom template
To create the template structure manually, open the .tpl file, add an element as shown below. The element should include class, id, and role attributes.
Also, the element value of the <div> tag’s id attribute value should be “main-content” and the role attribute value as “main“. The class attribute can be any custom value.
<div class="myLayoutTemplate" id="main-content" role="main"> ... </div>
To add a row, add an element inside the created element, as shown below. The element class attribute value should be “portlet-layout row-fluid”.
<div class="portlet-layout row-fluid"> ... </div>
To add the layout columns, add an <div> element for each column inside the layout row element as shown below. Each column should have a unique ID attribute.
The convention is to use the id value with the format column-x, where x is an integer in the incremental order.
<div class="portlet-column portlet-column-only span12" id="column-1"> ... </div>
Each column must specify the CSS class called portlet-column.
If a column is a first column or the last column, or the only column in a row, that column must use either the portlet-column-first, portlet-column-last or the portlet-column-only CSS class, respectively.
Each column’s class attribute must also specify a CSS class called the span[width], where the width can be in the range 1 to 12(In the Liferay 6.2 layout, templates use Bootstrap’s 12 column grid system).
Finally, with each column element, you must include a Velocity template directive to render each of the column’s portlets, as shown below.
$processor.processColumn("column-1", "portlet-column-content portlet-column-content-first")
The above method takes two arguments, the column id and the list of CSS classes.
The CSS class attribute value “portlet-column-content” must be passed as the second argument of the above method.
If the column is the first, last, or only column in a row, we have to pass both the portlet-column-content and the portlet-column-content-[first|last|only] in the second argument, separated by a space.
Complete liferay template code
The complete code for a 1-3-1 Liferay layout template is given below.
<div class="myLayoutTemplate" id="main-content" role="main"> <div class="portlet-layout row-fluid"> <div class="portlet-column portlet-column-only span12" id="column-1"> $processor.processColumn("column-1", "portlet-column-content portlet-column-content-only") </div> </div> <div class="portlet-layout row-fluid"> <div class="portlet-column portlet-column-first span4" id="column-2"> $processor.processColumn("column-2", "portlet-column-content portlet-column-content-first") </div> <div class="portlet-column portlet-column-last span4" id="column-3"> $processor.processColumn("column-3", "portlet-column-content portlet-column-content-only") </div> <div class="portlet-column portlet-column-last span4" id="column-4"> $processor.processColumn("column-4", "portlet-column-content portlet-column-content-last") </div> </div> <div class="portlet-layout row-fluid"> <div class="portlet-column portlet-column-only span12" id="column-5"> $processor.processColumn("column-5", "portlet-column-content portlet-column-content-only") </div> </div> </div>
Finally, below is the created Liferay template design.

Embedding portlets to the layout template
To embed portlet to Liferay template, we need the following attributes.
- portlet id : This is the value of the tag of the portlet.xml file. For core portlets, check the file liferay-portal/portal-web/docroot/WEB-INF/liferay-portlet.xml
- Instanceable: Specify whether multiple instances of the portlet can exist in the portal. This is specified with the keyword _INSTANCE_xxxx where XXXX is a random alphanumeric value. A custom instantiable portlet’s value may look like: portletID_WAR_webAppContext_INSTANCE_instanceID
- Web Application Context: Web context name of the portlet.
We also need to pass the fully qualified portlet id and we can copy this from the advanced styling section of the custom plugin portlets.
The below is an example implementation.
//Core portlet(Search): $processor.processPortlet("3") //Instanceable core portlet(Navigation): $processor.processPortlet("71_INSTANCE_abc8") //Custom Portlet: $processor.processPortlet("myCustomPortlet_WAR_myCustomPortletportlet_INSTANCE_abc1") //Instanceable custom portlet: $processor.processPortlet("myCustomPortlet_WAR_mycustomportlet_INSTANCE_abc1")
Finally, the complete code of the Liferay layout template implementation is listed below.
<div class="myLayoutTemplate" id="main-content" role="main"> <div class="portlet-layout row-fluid"> <div class="portlet-column portlet-column-only span12" id="column-1"> $processor.processColumn("column-1", "portlet-column-content portlet-column-content-only") </div> </div> <div class="portlet-layout row-fluid"> <div class="portlet-column portlet-column-first span4" id="column-2"> $processor.processPortlet("3") $processor.processColumn("column-2", "portlet-column-content portlet-column-content-first") </div> <div class="portlet-column portlet-column-last span4" id="column-3"> $processor.processPortlet("71_INSTANCE_abc8") $processor.processColumn("column-3", "portlet-column-content portlet-column-content-only") </div> <div class="portlet-column portlet-column-last span4" id="column-4"> $processor.processPortlet ("myCustomPortlet_WAR_myCustomPortletportlet_INSTANCE_abc1") $processor.processColumn("column-4", "portlet-column-content portlet-column-content-last") </div> </div> <div class="portlet-layout row-fluid"> <div class="portlet-column portlet-column-only span12" id="column-5"> $processor.processPortlet("AB_WAR_ABportlet") $processor.processColumn("column-5", "portlet-column-content portlet-column-content-only") </div> </div> </div>
Testing the output
Deploy the created custom Liferay layout template and apply the template to the portal page.
The below image shows the portal page that uses our custom template layout.

Conclusion
In this article, we learned about the Liferay layout template.
We also learned how to create a custom Liferay layout template.
Finally, we applied our custom Liferay layout template to the portal page.