Front-end strategy in eZ Publish. Part 1: Cascading Style Sheets and Javascript

by Val | August 23, 2013 2:34 pm

This blog post is going to describe best practices about the organization of styles and scripts in eZ Publish.

Our subsequent recommendations of eZ Publish front-end tricks will be based on some known css/js basic standards.


The following standards are described generally to help understand the proposed front-end strategy.

1. Styles should be stored to a file and be included into head html tag on the page:

Source code [1] [2] [3] 
  1. <link rel="stylesheet" type="text/css" href="/path/to/styles.css" />

2. And should NOT be defined directly to elements.
For example you should not do like this:

Source code [4] [5] [3] 
  1. <input style=”float: left” />

3. Scripts should be also be packed to files and be included into head in general.

Source code [6] [7] [3] 
  1. <script type="text/javascript" src="/path/to/scripts.js" charset="utf-8"></script>

4. And also should NOT be defined in elements directly.
It is not so good practice:

Source code [8] [9] [3] 
  1. <button onclick=”alert(‘test’); return false/>

5. All files with styles or scripts should be packed to one result css or js file.
So only one include of a file should be used instead of thousands.

Source code [10] [11] [3] 
  1. <script type="text/javascript" src="/path/to/scripts.packed.js" charset="utf-8"></script>

instead of thousands:

Source code [12] [13] [3] 
  1. <script type="text/javascript" src="/path/to/script_1.js" charset="utf-8"></script>
  2. <script type="text/javascript" src="/path/to/script_2.js" charset="utf-8"></script>
  3. ...
  4. <script type="text/javascript" src="/path/to/script_n.js" charset="utf-8"></script>

6. Styles or scripts which are not used on the current page should not be included at all.

These are generally accepted standards for web development. Google it if you don’t believe us ;)

These basic standards will help us to build flexible, scalable and quality solutions.

With the theroretical basis now understood, we can proceed with utilizing eZ Publish.

eZ JS Core

eZ Publish has inbuilt technology to handle styles, javascripts generally and ajax particularly.
It is distributed as standalone extension named ezjscore.

Let’s define its primary features.

1. eZ JS Core extension provides a mechanism for on demand script / css loading and json / xml encoding content.

Firstly it contains ezscript_load and ezcss_load template operators to load (include) scripts and styles.
Arguments of these operators are a list of eZ Publish design files.

For example:

Source code [14] [15] [3] 
  1. <html>
  2.     <head>
  3.         {ezcss_load( array( ‘styles_1.css’, ‘styles_2.css’ ) )}
  4.         {ezscript_load( array( ‘scripts_1.js’, ‘scripts_2.js’ ) )}
  5.     </head>
  6.     <body></body>
  7. </html>

Secondly using ezscript, ezscript_require and ezcss, ezcss_require template operators we can choose how we would want to include scripts and styles: inline or where ezcss_load, ezscript_load operators called (usually means to include js/css files to a page).

Using ezscript_require and ezcss_require operators would allow to include only files which needed for current page, and do not include another ones to prevent mess up and huge list of unused scripts or styles on a page.

Usually eZ Publish developers define list of needed js and css files to ini settings:

Source code [16] [17] [3] 
  1. [JavaScriptSettings]
  2. FrontendJavaScriptList[]=scripts_1.js
  3. FrontendJavaScriptList[]=scripts_2.js
  5. [StylesheetSettings]
  6. FrontendCSSFileList[]=styles_1.css
  7. FrontendCSSFileList[]=styles_2.css

after that they include all scripts and styles in one scope.

Source code [18] [19] [3] 
  1. <head>
  2.     {ezcss_load(
  3.         array(
  4.             ezini( 'StylesheetSettings', 'FrontendCSSFileList', 'design.ini' )
  5.         )
  6.     )}    
  8.     {ezscript_load( 
  9.         array( 
  10.             ezini(  'JavaScriptSettings', 'FrontendJavaScriptList', 'design.ini' ) 
  11.         ) 
  12.     )}
  13. </head>

This is the common eZ Publish way to include scripts and styles. However it leads every page on the frontend having the same list of scripts and styles. Our goal is to have just needed ones. Each page should contain only files which are used in that page.

To fix this issue need to figure out which styles and functionalities will be common for whole site and move it to common files. Those files can be defined in ini settings.

Other functionalities and styles should be logically split out and stored to separate files.

I believe that it is possible to find some logic layers in any serious solution where each layer requires each own list of javascripts and styles which are not shared between others layers.
If some functionality should be shared, just move it to higher layer.

It is very easy to demonstrate. For example, assume there is a template folder.tpl and it includes super.tpl that contains unique styles and functionality that are not used by another templates and folder.tpl level.

Logically it would be good idea to include js and css files only for this template.


Source code [20] [21] [3] 
  1. {ezscript_require( array( 'unique.js' ))}
  2. {ezcss_require( array( 'uniue.css' ))}


Source code [22] [23] [3] 
  1. {include uri="design:super.tpl"}

But if there is common styles or scripts, just need to move includes up to folder.tpl level:


Source code [24] [25] [3] 


Source code [26] [27] [3] 
  1. {ezscript_require( array( 'unique.js' ))}
  2. {ezcss_require( array( 'uniue.css' ))}
  4. {include uri="design:super.tpl"}

That helps to test and change front-end functionality quickly because you do not need to spend time finding needed scripts or styles in a big list of includes.

Also there is no a need to do additional configuration via ini settings. If you need some functionality in your template you just create a file and include it from the template.

Imagine if you have big project with a lot of templates and front-end functionalities.
There would be a need to group these files by level, layer or logic. And named properly:
Seems names like “scripts.js”, “my_func.js”, “lib1.js” are not so cool. You can find better names just by thinking what tasks each file is supposed to solve.

For example if you have special calendar and its template is located by path wizard/parts/widgets/calendar.tpl

It would be not a bad idea to name and place js handlers using the same path.


Source code [28] [29] [3] 
  1. {ezcss_require( array( 'wizard/parts/widgets/calendar.js' ))}

2. eZ JS Core extension is mainly used for merging and packing javascript or stylesheet files together to reduce size and number of files (as in reduces client connections).


Source code [30] [31] [3] 
  1. [eZJSCore]
  3. # Disables/enables js / css packer (for debugging Apache rewrite rules)
  4. # Normally controlled by [TemplateSettings]DevelopmentMode for convenience,
  5. # but can also be specifically controlled by this setting if set.
  6. # Force packer level by setting integer from 0 to 3 instead of [dis|en]abled
  7. Packer=disabled

Even if you create one css and js file per template there would be an ability to pack it to one result file.


- eZ JS Core provides mechanism to control design and script files. It can be added inline or to header.
– Packs css and js which decreases the number of calls to the server.
– Allows to include only files which needed for current page, and do not include another ones to prevent mess up and huge list of unused styles or scripts.
– That helps to test and change front-end functionality because you do not need to spend a time to find needed scripts or styles if you have really huge project.
– There is no a need to do additional configuration like ini settings and prevents hardcoded values in tpl. Also allows to use eZ Publish override mechanism.

The second part[32] will describe eZ way to use AJAX.

  1. [Image]: #codesyntax_1
  2. [Image]: #codesyntax_1
  3. [Image]:
  4. [Image]: #codesyntax_2
  5. [Image]: #codesyntax_2
  6. [Image]: #codesyntax_3
  7. [Image]: #codesyntax_3
  8. [Image]: #codesyntax_4
  9. [Image]: #codesyntax_4
  10. [Image]: #codesyntax_5
  11. [Image]: #codesyntax_5
  12. [Image]: #codesyntax_6
  13. [Image]: #codesyntax_6
  14. [Image]: #codesyntax_7
  15. [Image]: #codesyntax_7
  16. [Image]: #codesyntax_8
  17. [Image]: #codesyntax_8
  18. [Image]: #codesyntax_9
  19. [Image]: #codesyntax_9
  20. [Image]: #codesyntax_10
  21. [Image]: #codesyntax_10
  22. [Image]: #codesyntax_11
  23. [Image]: #codesyntax_11
  24. [Image]: #codesyntax_12
  25. [Image]: #codesyntax_12
  26. [Image]: #codesyntax_13
  27. [Image]: #codesyntax_13
  28. [Image]: #codesyntax_14
  29. [Image]: #codesyntax_14
  30. [Image]: #codesyntax_15
  31. [Image]: #codesyntax_15
  32. The second part:

Source URL: