Configuring skins, themes, static CSS and JS assets

November 14, 2023

Skins

Skins are predefined layouts that can be applied to any content object of jahia pages by authors, whatever the content particular structure.

Benefits

The same skin can be applied to a news, an article, or any other object. The interest for integrators is to build a collection of skins and make them accessible for authors so those authors benefit from a wider, but still correctly controlled, set of graphical options. As skins are very simple (authors just choose the skin they want to apply) and don't involve knowledge about CSS and such options, they remain simple to use and explain.

How skins work

Skins are XHTML files that can be activated to surround existing content object, most of the time to change the final layout. By adding a specific XHTML, authors can choose a different layout thanks to new CSS classes called in the page around the targeted object. For instance, with skins, it's easy to add the necessary DIVs to apply round corners around a content object, while by default the basic XHTML doesn't allow that.

Known capabilities and problems

If you call a skinned content in Ajax, the skin will be returned too.

Skins can be designed to display some content properties from the nested object. Example: use the jcr:title in the skin to display it in a special layout.

This is useful but can cause a problem: the property (title in our example) will be displayed twice: once by the skin itself, and one by the content object template.

To avoid to display it both in module and skin, you must add in your skin CSS an entry to hide the title in the module. For that, we suggest to use the same class to display all your module titles :

<h3 class="title">
    <jcr:nodeProperty node="${currentNode}" name="jcr:title"/>
</h3>

and in your CSS' skin :

.box2 .box2-text .title{
    display:none;
}

You can find an example on jnt:mainContent node display in default module.

Themes

You can set themes in a template set that will be used in pages and templates.

A theme is a set of CSS files that are loaded for a page. If a theme is set on a page, all its subpages will inherit it.

Create a theme

from the Studio, in a template set, go to the content side panel, then create a new folder named themes under /templates/files

To create a new theme named myTheme, add a folder myTheme under  /templates/files/themes

Upload all the related CSS to the theme in this folder.

The theme is ready to be used.

Use a theme

From the edit engine of a template or a page, enable the theme checkbox. This will let you choose any available theme within the current templates set (or the site templates set if the page is part of a site) 

Using jQuery

jQuery is provided by the core module Jahia jQuery (starting with DX 7.2.3.1, it is possible to choose between jQuery 1.12.4 and jQuery 3.3.1).

To use it in any view add the following code in the jsp : 

<template:addResources type="javascript" resources="jquery.min.js"/>

This module is a dependency of the default module and is needed by Jahia as it it is used for many pages or components (like page settings or CKeditor) 

If you want to use your own version of jQuery you can :

  • create your own jquery module, with an alternate name for the javascript file (jquery.1.x.x.min.js) and load it in your view
<template:addResources type="javascript" resources="jquery.1.x.x.min,js"/>

but you have to take care to override all views of Jahia components that use jQuery in order to load your own module and validate that it still works with this jQuery version.

  • create your own version of the existing jQuery module, but we cannot guarantee that our module will still continue to work as expected. 

Static assets

The assets module contains common CSS and JavaScript resources and also allows enabling support for Content Delivery Network or fine-grained mapping of resources.

This module is used by the Default Jahia Templates module (the default Jahia module), thus the bundled resources are available to all modules which depend on the Default Jahia Templates module.

The dependency to this module can be also specified explicitly in the module's deployment descriptor (e.g. my-custom-module/META-INF/MANIFEST.MF, by including it into depends attribute:

  ...
  package-name: My Custom Module
  depends: Jahia Static Assets
  ...

Following sections describe module features for more details:

Usage - how to include assets into templates
Advanced configuration, achieved by using asset mapping, including support for Content Delivery Network (CDN), development mode and aggregation of multiple resources.

Usage of assets module

Declaring asset dependency

In order to declare static asset dependency in a template the <template:addResources/> tag is used.

It supports four types of assets (the type name is case-insensitive):

  • CSS - an external CSS stylesheet
  • javascript - an external JavaScript resource, that will be included in
  • content in the body of the tag
  • inline body content of the tag

An external resource is declared as: 

<%-- Declaring dependency to timepicker JS and CSS --%>
<template:addResources type="javascript" resources="timepicker.js"/>
<template:addResources type="css" resources="timepicker.css"/>

<%-- Declaring multiple dependencies --%>
<template:addResources type="javascript"
    resources="jquery.min.js,jquery-ui.core.min.js,jquery-ui.datepicker.min.js,jquery-ui.slider.min.js"/>

For "inline resources" the body of the <template:addResources/> tag is utilized:

<template:addResources>
    <script type="text/javascript">
        $(document).ready(function() { alert('document loaded'); });
    </script>
</template:addResources>

or

<template:addResources>
    <style type="text/css">
        div#fancy_div {
            background: #FFF;
            color: #000;
            overflow: auto;
    </style>
    }
</template:addResources>

Asset lookup

When an asset is declared it is looked up in the specific location, based on the asset type and the current template module. The asset ui/xyz.js (of type javascript), declared as follows:

  <template:addResources type="javascript" resources="ui/xyz.js"/>

is searched in the following locations in that order:

/modules/my-custom-module/javascript/ui/xyz.js
/modules/direct-dependent-module-1/javascript/ui/xyz.js
/modules/direct-dependent-module-2/javascript/ui/xyz.js
/modules/indirect-dependent-module-1/javascript/ui/xyz.js
/modules/indirect-dependent-module-2/javascript/ui/xyz.js

It is also possible to specify a path, starting with "/" or event an absolute path (starting with "http://"). In this case, the search in modules won't be performed and the specified path will be used as-is.

A real resource path can be overridden by providing asset mappings, e.g. for enabling the CDN option or the asset aggregation.

Duplicate dependencies

Duplicate declarations of the same asset are handled automatically and have an effect on including the asset only once.

Sharing common assets

If the project uses multiple modules, which make use of same static assets (e.g. same jQuery library) it makes sense to share them in a common module that all other module depends on. The same way, it is done in this module (Jahia Static assets), which is the dependency of the Default Jahia Templates module and thus many others.

Including declared dependencies

Declared dependencies are included automatically by the Static Assets Filter

Assets mapping and CDN

Providing mappings

The higher control upon the static assets is achieved by using mappings.

A static asset can be mapped to a another internal asset or even an external asset. As well as multiple assets can be mapped to one "aggregate" asset to optimize page loading time.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- Google CDN for jQuery and jQuery UI -->
    <bean class="org.jahia.services.render.StaticAssetMapping">
        <property name="mapping">
            <map>
                <entry key="/modules/assets/javascript/jquery.min.js"
                       value="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"/>
            </map>
        </property>
    </bean>
</beans>

The key of the map entry is the original resolved asset. Under resolved, we mean the full context related path of the resource (context path is not included).

Next sections show several common use cases for using mappings.

Content Delivery Network

Enabling the Content Delivery Network (CDN) for assets brings a lot of benefits, from reducing the number of requests to your own server to the optimized page loading (browser optimizes concurrent loading of resources from different domains).

Following Spring configuration file snapshot shows the mapping from local resources to their CDN-hosted versions: 

...
<bean class="org.jahia.services.render.StaticAssetMapping">
    <property name="mapping">
        <map>
            <!-- Microsoft CDN for jQuery -->
            <entry key="/modules/assets/javascript/jquery.min.js"
                   value="http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.min.js"/>

            <!-- Google CDN for Prototype -->
            <entry key="/modules/assets/javascript/prototype.js"
                   value="http://ajax.googleapis.com/ajax/libs/prototype/1.6.1.0/prototype.js"/>
        </map>
    </property>
</bean>
...

Development mode

It can be useful during the development phase to use the non-minified (non-compressed) versions of the JavaScript libraries, mainly for debugging purpose.

It can be achieved by mapping the minified version of the resource to the non-minified one:

...
<bean class="org.jahia.services.render.StaticAssetMapping">
    <property name="mapping">
        <map>
            <!-- Map minified jQuery to the full one for debugging -->
            <entry key="/modules/assets/javascript/jquery.min.js"
                   value="/modules/assets/javascript/jquery.js"/>
        </map>
    </property>
</bean>
...

The benefit of using mappings, in this case, is that no changes need to be done in the template themselves. After the development phase is finished, removing the corresponding mapping will bring back the minified versions of assets.

Assets aggregation

It is possible to optimize asset loading by combining them together. During the development phase, it could be quite useful to use e.g. several small CSS or JavaScript files and later aggregate them into larger ones.

For versions until DX 7.3.1.0 assets are aggregated and compressed by default, this can be changed by setting the property aggregateAndCompressAssets to false in jahia.properties file.
Starting with DX 7.3.1.0 the default has changed to only aggregate and not compress.

Therefore the property aggregateAndCompressAssets has been replaced by two properties:

  • aggregateAssets
  • compressAssetsDuringAggregation
But it is important to note that the new property compressAssetsDuringAggregation will be ignored if you are using a version of JDK other than 1.8 and the compression of assets by Jahia is now deprecated as we will drop it in the future.

Following mapping "tells" asset mapping service to use single jQuery UI file instead of several components (Core, Datepicker, and Slider):

...
<bean class="org.jahia.services.render.StaticAssetMapping">
    <property name="mapping">
        <map>
            <entry key="/modules/assets/javascript/jquery-ui.core.min.js"
                   value="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"/>
            <entry key="/modules/assets/javascript/jquery-ui.datepicker.min.js"
                   value="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"/>
            <entry key="/modules/assets/javascript/jquery-ui.slider.min.js"
                   value="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js"/>
        </map>
    </property>
</bean>
...

A similar configuration can be done for CSS files:

...
<bean class="org.jahia.services.render.StaticAssetMapping">
    <property name="mapping">
        <map>
            <entry key="/modules/templates-intranet/css/01web.css"
                   value="/modules/templates-intranet/css/intranet-all.css"/>
            <entry key="/modules/templates-intranet/css/02intra.css"
                   value="/modules/templates-intranet/css/intranet-all.css"/>
            <entry key="/modules/templates-intranet/css/03navigation.css"
                   value="/modules/templates-intranet/css/intranet-all.css"/>
        </map>
    </property>
</bean>
...