User Specific or Multi Site Specific CSS styles in Sitecore Rich Text Editor

Following a question on Stackoverflow about filtering the css classes shown in the Rich Text Editor control, I thought I would share some simple code which is useful in various scenarios.

The RTE control used in Sitecore is Telerik RadEditor. The implementation is very flexible, and a lot of the configuration can be changed by changing the profile in the core database under /sitecore/system/Settings/Html Editor Profiles. You can easily switch the profile used on a per field basis by setting the source on the field definition:

RTE-Field-Source

You can of course set the default profile use by all Rich Text fields by patching in the web.config:

<!--  HTML EDITOR DEFAULT PROFILE
      Path to the default html editor profile.
      Default value: /sitecore/system/Settings/Html Editor Profiles/Rich Text Default
-->
<setting name="HtmlEditor.DefaultProfile" value="/sitecore/system/Settings/Html Editor Profiles/Rich Text Default"/>

So back to the original question at hand. The need was to load a different stylesheet into the RTE for different users. A single stylesheet can be set in config again:

<!--  WEB SITE STYLESHEET
      CSS file for HTML content of Sitecore database.
      The file pointed to by W`bStylesheet setting is automatically included in Html and Rich Text fields.
      By using it, you can make the content of HTML fields look the same as the actual Web Site
-->
<setting name="WebStylesheet" value="/link/to/custom.css"/>

RTE-Styles-Droplist

Switching Stylesheets

In order to run logic during the load of the configuration, you can override the default configuration type. To do so, create a new class that inherits from Sitecore.Shell.Controls.RichTextEditor.EditorConfiguration and override the SetupStylesheets() method:

public class EditorConfiguration : Sitecore.Shell.Controls.RichTextEditor.EditorConfiguration
{
    public EditorConfiguration(Item profile) : base(profile)
    {
    }

    protected override void SetupStylesheets()
    {
        // if (user == X)
            this.Editor.CssFiles.Add("/path/to/custom.css");

        base.SetupStylesheets();
    }
}

Set RTE Configuration Type

There is two places the configuration type can be set, either in config by setting the following value to your class:

<!--  HTML EDITOR DEFAULT CONFIGURATION TYPE
      Specifies the type responsible for setting up the rich text editor. Can be overriden at profile level. Must inherit from Sitecore.Shell.Controls.RichTextEditor.EditorConfiguration,Sitecore.Client.
      Default value: Sitecore.Shell.Controls.RichTextEditor.EditorConfiguration,Sitecore.Client
-->
<setting name="HtmlEditor.DefaultConfigurationType" value="MyProject.Controls.EditorConfiguration, MyProject"/>

Or you can create an item of template type /sitecore/templates/System/Html Editor Profiles/Html Editor Configuration Type in your Rich Text Profile and setting the value of the Type field to your implementation:

RTE-Configuration-Type

Restricting Stylesheets by Role

In order to make the restriction more dynamic and more Sitecore friendly, define a set of “stylesheets” in settings somewhere in your content tree, and then restrict read access to them using the Security Editor and restrict permissions for different roles. Then you can simply read back a list of items, iterate and add them:

RTE-Content-Stylsheets

protected override void SetupStylesheets()
{
    IList<Item> stylesheets = Sitecore.Context.ContentDatabase.GetItem("/sitecore/content/RTE-Stylesheets").Children.ToList();
    foreach (Item item in stylesheets)
    {
        this.Editor.CssFiles.Add(item["Stylesheet"]);
    }

    base.SetupStylesheets();
}

Since the permissions have been restricted on each item only those the current user has read access to will be returned, thus the list of styles in the RTE.

Multi-site implementation

Where I have used something similar previously is in multi-site implementations, where each site may have a different set of styles defined or the styles for each site look different. Obviously you only want your Content Editors to be able to select styles specific to the site but it is also nice to be able to see the applied styles in the RTE field.

Set up your multi-site instance as normal and store the stylesheets as we previously did:

RTE-multisite-setup

Then simply update the code to look in the current site. Luckily the id of the current item is passed as a url parameter that we can read in, and then we can use a bit of Sitecore Query Notation to get to the site stylesheets:

protected override void SetupStylesheets()
{
    string id = WebUtil.GetQueryString("id");
    string query = "/*/content//*[@@id='" +id+ "']/ancestor::*[@@templateid='{root-guid}']//*[@@templateid='{style-folder-guid}']/*";

    IList<Item> stylesheets = Sitecore.Context.ContentDatabase.SelectItems(query);

    foreach (Item item in stylesheets)
    {
        this.Editor.CssFiles.Add(item["Stylesheet"]);
    }

    base.SetupStylesheets();
}

Be sure to read this follow up post from Kam Figy to get this working in Preview mode of the interface.
https://kamsar.net/index.php/2015/05/Extending-Sitecore-Rich-Text-Preview-CSS/

6 comments

  1. aceanindita · September 26, 2015

    Thank you for this! We were looking for a solutionf or our multisite instance. Very helpful!

  2. Jay Bonning · April 7, 2016

    This is great! Thank you.

  3. Lavie · November 23, 2017

    Hi,
    Is this work for Sitecore 8.0
    I cannot find the namespace Sitecore.Shell.Controls when try to inherit EditorConfiguration.
    Please help.
    Thanks

    • jammykam · November 23, 2017

      Yes this should work in 8.0, and also earlier versions since I don’t think it has changed since 6.x. The class is in `Sitecore.Client.dll`

      • Lavie · November 24, 2017

        It works.
        Thanks, jammykam.

Leave a comment