Drupal 8 How To - CKEditor Custom Styles

CKEditor Custom Styles in Drupal 8

Much like everything in Drupal 8, setting up custom CKEditor styles is actually ridiculously easy, once you know how. Its just not widely documented or particularly obvious from the admin UI. Coming from Drupal 7, you're probably used to having to jump through all sorts of WYSIWYG hoops and can easily spend an hour searching for missing custom config files and the like. The good news is, everything you need is a few clicks and couple of lines of yml away!

In Drupal 7 CKEditor was either installed as standalone module or as a plug in for the WYSIWYG module. In either case you would also have to separately install and configure the actual CKEditor library itself. If you were lucky things would work smoothly from there-on in, but for many this also meant a little trial and error, finding and downloading the specific version number of CKEditor that would work without problems in your specific Drupal installation (conflicts with other modules and versions of JQuery were common.) Setting up custom styles for CKEditor in Drupal 7 could also be a nightmare of linking JS config files and extra style sheets.

In Drupal 8, CKEditor has been chosen as the Drupal editor of choice and is installed as the default editor as part of core. No more convoluted setup. On a new installation of Drupal 8, just visit /admin/config/content/formats and you will see that the Full and Basic HTML text formats are already using CKEditor out-of-the-box. And custom styles? A breeze to set up - once you know where to look.

So. About Custom Styles?

Once you have a working CKEditor installation on your Drupal site, one of the most powerful things you can do as a developer for users of a CMS platform, is create a set of custom typographic styles, sympathetic to the site's design and brand guidelines, which can be selected and applied inside the Editor window.

When configuring CKEditor for a client, I usually break things down into three main tasks.

  1. Clean up the editor window's toolbar to only display formatting buttons that content editors actually need and for every button that is displayed, make sure CSS rules exist to style their output inline with the site's design.
  2. Add custom styles to the editor window toolbar: Enable the 'Styles' dropdown menu for the editor and populate with a set of custom typographic styles and/or formatting options, not available as default buttons. Also create the CSS needed for each new custom style. 
  3. Lastly we need to make sure that the actual editor itself is set up to use the correct CSS, so that as CMS users interact with it, the content in the editor window is presented using the site's theme styles and when custom editor styles are applied, they appear in 'real-time' within the editor window.

Step 1  - Customising The Editor Toolbar

Before adding new tools to CKEditor it's a good idea tofirst clean things up by removing all unnecessary text formatting options from the editor toolbar. For instance, I almost always remove the ability to Create H1 headings in content areas, text alignment options, text colours, sizes and fonts etc.

Limiting access to confusing options and potentially 'dangerous' temptations...

This may seem restrictive, but by limiting access to these sometimes confusing options and potentially 'dangerous' temptations, jarringly bad and incohesive text formatting can be avoided and a much more consistent site style is easier to dictate. Instead of just letting editors go wild, with random colours, font sizes and the like, its much more sensible to listen to their needs and provide them with a tailored, design-lead selection of custom text rules to enable them to richly format articles safely, without destroying layout and design naratives.

This first step has always been pretty straight forward. Either through a drag and drop interface or using checkboxes, admins can choose which formatting buttons appear in the editor toolbar, on a text format by text format basis. In Drupal 8, this is a simple drag and drop process.

Disable Unwanted Buttons

Visit /admin/config/content/formats/manage/text format name.

Under 'Toolbar Configuration', to disable a toolbar button, drag it from its place on the 'Active toolbar' up to 'Available buttons'. Repeat this process for each button you want to remove. To re-enable abutton just do the reverse and drag it back to the 'Active toolbar'. *Buttons must be assigned to a 'group' (the areas denoted by the faint, dotted borders). 

In the image below, I've dragged the 'justified center' text button from the Active toolbar to the  'Available buttons'

Toolbar Disable Button

Step 2 - Creating The Custom Styles

Step 2 Involves creating the actual CSS for the custom style rules, but also, first configuring the editor, so that these styles will appear in the 'styles' drop down menu.

2a Enable 'Styles' Dropdown

IMPORTANT! This step must be carried out BEFORE step 2b.

To Enable a button in the toolbar, do the opposite of what we did in Step 01.  So to enable the custom styles dropdown, drag 'styles' down on to the desired position of the 'Active toolbar'. *Note that when adding buttons to the active toolbar, they must be either added to an existing button group (illustrated by the dot bordered boxed areas) or a new empty button group must first be created. If you try and drag a button to anywhere in the toolbar which is not a button group, nothing will happen.

Toolbar Styles Enabled

2b Populate The Dropdown

Now that we have added the styles dropdown to the active toolbar, we can start populating the dropdown with our custom styles.

Below the section of the admin page where we configured the buttons, there is a heading of 'CKEditor Plugin Settings'. 

You should now see settings for the 'Image' plugin (the plugin that handles inline image uploads) and also the settings for the 'Styles dropdown' plugin we enabled by dragging the styles button into the active toolbar.

The reason it's important to perform step 2a before 2b is that without first enabling the button itself, the plugin settings will not appear. This caught me out at first, as under Drupal 7 WYSIWYG configuration, these settings were displayed, regardless of whether the styles dropdown was active. In Drupal 8 plugin settings only appear if that plugin is first made active.

Now that the settings are exposed you will find a text area and a brief description on how to create custom styles in the form of element|label pairs, one per line.

An element|label pair consists of:

1. Element

An element refers to a HTML element tag, like 'p', 'a' or 'span' for instance, given one (or more) CSS classes. When applying a custom style in the Editor window, these classes are injected into the source code of the selected text. We can then reference this class or classes in our site's CSS to create the desired effect (see step 2c).

2. Label

The human readable name by which this style is displayed in the actual dropdown menu.

Example in use

On my site I have created a custom style which (visually at least) turns normal anchor link tags into buttons like so:

this is a link button

To populate the dropdown with this style and inject the class into the code that I will need in step 2c, i created this element|label pair under the Styles dropdown plugin settings:

a.btn|Buttonlink Def

I'm creating a style which when applied to a link (an 'a' tag), will inject a class of 'btn' into that tag. This style will appear in the Editor's styles drop down as 'Buttonlink Def'.

Applying Button

Multiple classes applied in one custom style

I also have style for an alternative gray button:

a gray button

This style uses most of the same CSS rules as the default 'Def' button style. Only the text and background colour changes. So rather that replicate code for padding, font etc, I still use the class of 'btn', but also add a class of 'btn-gray'. This 'btn-gray' class contains rules purely there to override the text and background colour only.

So for this style to work, I need two classes to be injected into the code of the selected link, when its applied in the editor.

So for my element|label pair I create:

a.btn.btn-gray|Buttonlink Gray

When applied, both the classes of 'btn' and 'btn-gray' will be simultaneously injected into the same 'a' tag. This style will appear in the dropdown as 'Buttonlink Gray'

2c Creating the CSS Rules

I'll continue to use my button link style as an example.

Now that I've added the custom style to the editor dropdown, applying this style will inject the necessary classes into the code for me to create my button style, but I still need to create the actual CSS rules needed to style all links containing these classes. This can be added to the existing site theme's CSS files.

I'm actually using SASS to write my CSS and as such this button is the result of a few included mixins and variables, but for ease of understanding i'm just going to show the compiled CSS here instead (minus browser prefixes).

/*Styles applied to all link buttons*/
.btn {
    display: inline-block;
    text-align: center;
    white-space: nowrap;
    vertical-align: middle;
    cursor: pointer;
    user-select: none;
    border: 0 solid transparent;
    transition: all 0.2s ease-out;
    padding: 0.5rem 1rem;
    font-size: 1rem;
    font-weight: 400;
    letter-spacing: 0.05rem;
    color: #fff;
    background-color: #231f20;

/*Styles applied to override colors*/
.btn-gray {
    color: #231f20;
    background-color: #ccc;


Step 03 - Styling Live Input

By this stage we should have all unnecessary buttons removed from CKEditor's toolbar, we've enabled the 'styles' dropdown, added our own custom styles to the dropdown and have created the CSS needed to make those styles come to life.

That's great. We can now 'technically' use our new custom styles in the editor, but something's not quite right.

When we select text and apply a style to the body of the editor window nothing happens!?!

Actually that's not 100% true. Our class or classes are being added to the source code, but out-of-the-box the editor window doesn't know to use our site theme's CSS, so although our classes are being added, the CSS needed to style them in real-time, is not being loaded into the editor window. *If we save the page and view it, the styles will take effect. but so far there's no way of seeing them inside the editor as we apply them.

Not Quite There Yet

Not ideal right? I mean it 'works', but how can we possibly keep track of where we've applied custom styles in the body of a long page without the visual feedback of seeing those styles actually changing the text in the editor as we work? We could look a look at the source code and maybe get confirmation that the classes are being applied, but that's not really an acceptable solution when you want get immediate feed back on how your formatting choices are shaping the output of the page.

And while we're on the subject, even without our custom styles, the text in the editor is all horrible Times Roman and none of our site's default heading sizes or link colour are being respected.. eeeggghhh!!!!

Thankfully we can fix all this with just a couple of line of yml!

What's yml? A discussion for another time, but suffice to say that yml (pronounced by most as 'Yamal') is a coding language used in many of Drupal 8's user configurable files.

Have CKEditor Use Your Theme's CSS To Style Text In The Editor Window

In the root of the your Drupal site's theme you should have or have created a mytheme.info.yml file (where 'mytheme' is the name of your specific theme).

This is the Drupal 8 equivalent of the Drupal 7 mytheme.info file, where we declare our theme to Drupal and make various default theme wide settings, like the theme's name and description, specifying which CSS and JS files the theme uses, creating custom block regions etc.

In the Drupal 8 mytheme.info.yml file, we specify the css sheet or sheets our theme uses for it's default output, but if we want the CKEditor editor window to use our theme's CSS (or indeed a separate dedicated file), we must specifically declare it here.

So under my declared libraries (the css and js I want my theme to use for its main output), I add a rule that says if CKEditor is being used, style the content in it's editor window with the following CSS file. *In yml 'spaces' are a crucial part of the mark up, so be especially carefully NOT to use tabs (unless your IDE has been specifically set up for 2 space tabs) and to indent each nested level with precisely 2 'spaces'.

name: My Theme Name
desciption: A description of my drupal theme
type: theme
core: 8.x
screenshot: screenshot.png

  - mytheme/global-css
  - mytheme/global-js

  - css/style.css

It may not be obvious, but here I've set CKEditor to use the same 'css/styles.css/ stylesheet as the rest of my theme. (under libraries, 'global-css' is actually referencing the same file path. You can track this path in a separate theme file called 'mytheme.libraries.yml')

You can use a separate CSS file, specifically for CKEditor if you wish, but to keep our CSS DRY and free from repetition, it makes sense to use the same file as the rest of the site. This also makes sure that if our global site font style is Open Sans at 16px, that's the font style editors will see in the CKEditor window. And if they apply one of our new custom styles, they will see it update live in the editor window.

Wrap Up

You should hopefully now have all the information needed to confirgure CKEditor in Drupal 8, to provide a content publishing tool set, tailored specifically to your's or your client's needs.

Further Reading