Using Rich Text custom classes and attributes in eZ Platform

eZ Platform 2.x has evolved a lot - tons of great changes/improvements. But one vital feature is still missing: custom CSS classes and custom attributes. This could prevent a large number of eZ Publish 5.4 sites migrating to the latest eZ Platform version.

That's why we decided to help by submitting a few pull requests. Among them, are:

So right now is possible to store custom attributes, and it will be possible to migrate them from eZ Publish 5.4 very soon. But there is no way to manage them in eZ Platform. eZ Systems plans to release this feature in upcoming 3.x.

In the meantime, ezplatform-custom-attributes solves this problem. It provides a way to set up custom classes and attributes. And it also brings the new UI to them in the Online Editor:


There is nothing special; you know the drill:

  • Require contextualcode/ezplatform-custom-attributes via composer:
composer require contextualcode/ezplatform-custom-attributes
composer require
  • Activate the bundle in app/AppKernel.php:
$bundles = [
    new ContextualCode\EzPlatformCustomAttributesBundle\EzPlatformCustomAttributesBundle(),
  • Clear the caches:
php bin/console cache:clear
clear cache
php bin/console bazinga:js-translation:dump web/assets --merge-domains
yarn encore dev
lump translations

After the steps above, the installation is complete. You should now see the new "Elements Path" block in the Online Editor. You are able to click on any element in that block; if the clicked element has been defined to be able to have at least one custom class or attribute a new UI will be shown to edit them.

The next step is to configure custom classes and custom attributes.


Custom classes and attributes are set up per each HTML element in the yml configuration file. An example configuration looks like the following:

        p: [p-class-1, p-class-2, p-class-3]
        table: [table-class-1, table-class-2]
                type: checkbox
                type: text
                default: 80
                type: select
                options: [javascript, php, java]

For custom_classes you just specify an HTML element and the array of its custom CSS classes.

Similarly, for custom_attributes, it is required to define custom attribute settings per each HTML element. There are following options:

  • type possible values are: text, textarea, select, checkbox
  • default applicable only for text and textarea attributes
  • options is used only for select attributes, and it contains an array of possible options

If you are migrating from eZ Publish 5.4 and your content has a lot of custom classes and attributes, it might be very time-consuming to configure all of them. To simplify this task its better to use the ezplatform:generate-custom-attributes-configuration command. This script will generate a configuration based on the content stored in the database. Example usage:

php bin/console ezplatform:generate-custom-attributes-configuration --config-file=src/AppBundle/Resources/config/custom_attributes.yml

Extracting Custom Classes from Rich Text fields

 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

Extracting Custom Attributes from Rich Text fields

 1/1 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 [NOTE] Found 2 elements with custom classes: table, p      
 [NOTE] Found 3 elements with custom attributes: tr, pre, p

 [OK] Configurations are saved into "src/AppBundle/Resources/config/custom_attributes.yml"

After the custom classes and attributes configuration is done you should see and be able to edit them in the Online Editor. At this point, you might want to make their labels more editor friendly. And it is done via translations.


We are using JavaScript translations (custom_attributes translations domain). So all the custom class and attribute labels are translated on the client side.

To set up custom labels start with creating a custom_attributes.<LANGUAGE-CODE>.yaml translation file in your bundle. A good example would be src/AppBundle/Resources/translations/custom_attributes.en.yaml.

Then you need to add the actual labels there. Supported types are:

  • Custom class label, its translation message key should follow options.<css-class-name>.label pattern. Examples:
options.p-class-1.label: 'Paragraph Class 1'
options.p-class-2.label: 'Paragraph Class 2'
options.p-class-3.label: 'Paragraph Class 3'
options.table-class-1.label: 'Table Class 1'
options.table-class-2.label: 'Table Class 2'
custom class labels
  • Options labels (only for select type attributes), its key pattern is options.<option>.label. Examples:

custom attribute option plans

  • Custom attribute title, the pattern is attributes.<name>.label. Examples:
attributes.hide.label: 'Hide'
attributes.max-length.label: 'Maximal Length'
attributes.language.label: 'Language'
custom attribute titles

Please note, every time after custom attributes translations are changed you need to dump them and run encore:

php bin/console bazinga:js-translation:dump web/assets --merge-domains
yarn encore dev
dump translations

So now the remaining part would be to handle the custom classes and attributes on the front-end.


There is nothing special about the rendering of custom classes on the front-end. They are set as a class attribute on the corresponding HTML elements.

Custom attributes are rendered as data attributes with an ezattribute- prefix by default. So if for some element max-length is set to 10, on the front-end it will be rendered as data-ezattribute-max-length="10" attribute. It works in most cases, but there are few ways to customize it.

XSL Stylesheets

One of the possible ways to implement advanced rendering for custom attributes is to use custom XSL stylesheets. This option is the best for performance, but it requires some extensive knowledge of XSL. Also, you need to be familiar with eZ Platform Rich Text schema. In this case, Rich Text content is modified at the stage when it is transformed from the format it is stored into the database to HTML5. Example implementation:

Example implementation:

<?xml version="1.0" encoding="UTF-8"?>
  <xsl:output indent="yes" encoding="UTF-8"/>
  <xsl:template match="docbook:tr[docbook:ezattribute[docbook:ezvalue[@key='hide' and text()='true']]]"/>

Rich Text Converter

Alternatively, you can use Rich Text Converters to implement advanced rendering for custom attributes. In this case, Rich Text content is manipulated in PHP, which makes easier to develop and debug it. Basically you define a new service with a ezpublish.ezrichtext.converter.output.xhtml5 tag, which implements EzSystems\EzPlatformRichText\eZ\RichText\Converter interface. And that's all!

Example implementation:


You can grab a working example of eZ Platform with ezplatform-custom-attributes from . Please check out AppBundle there. It has examples of all possible configurations and customizations in the scope of custom classes and attributes.


There are no reasons why you can't start using ezplatform-custom-attributes right now, and then use the official Custom Attributes feature due to be released in eZ Platform 3.


  • First of all, we want to highlight that ezplatform-custom-attributes does not modify the Rich Text schema. This means you don't need to make any changes to your data during your eZ Platform 3 upgrade. And you don't need to run any migration scripts.
  • Custom classes and attributes rendering is done by using built-in eZ Platform functionality. So if you implement it now, it should stay the same in eZ Platform 3.
  • The only thing that's going to be changed in eZ Platform 3 is the admin UI. An that point you can just disable this bundle and the new UI will be picked up.
  • The only part might need to be changed during eZ Platform 3 migrations is custom classes and attributes configurations. That's going to depend on the configuration format for custom classes and Attributes in eZ Platform 3.

So please have a try ezplatform-custom-attributes. We would love to hear your feedback. PRs and comments are very welcome!

Leave us a comment
blog comments powered by Disqus