Skip to content

Custom style formats

indigoxela edited this page Oct 7, 2024 · 26 revisions

Custom styles are CSS classes applied to HTML tags, not to get confused with snippets, which are supposed to be more complex – there's a plugin for snippets.

In Backdrop's TinyMCE integration, there are three ways to add custom styles to the styles dropdown.

  1. CSS file tinymce-styles-dropdown.css
  2. JSON code adaption of a custom editor profile
  3. hook_tinymce_options_alter()

All have their pro and cons. Which one works best for you may depend on what you're trying to achieve. But the first one is the most convenient one, if you have a custom theme, anyway.

The convenient (low code) approach: a CSS file with file name tinymce-styles-dropdown.css

Available as of version 1.x-1.4.0

Assuming, you have a custom theme, that ships with your styles, these are the steps:

  1. Add a CSS file to your theme, that only contains styles relevant for the styles dropdown (see below code example)
  2. Its filename has to be tinymce-styles-dropdown.css, the path to it doesn't matter
  3. Apply styles to display by adding stylesheets[all][] = css/tinymce-styles-dropdown.css to your theme's info file - as you'd normally do
  4. Additionally add tinymce_content_css[] = css/tinymce-styles-dropdown.css to your theme's info file

The fourth step will do two things: it'll apply the styles to the editor content AND it will cause TinyMCE to parse the file and automatically add these styles to the dropdown.

An example styles content looks like this:

Click to expand CSS code sample
p.grey-background {
  padding: 1em;
  background: #f7f7f7;
}
.small-text {
  font-size: .7rem;
}
.x-large-text {
  font-size: 2rem;
}
span.blue-text {
  color: blue;
}
span.red-text {
  color: red;
}
.text-spaced {
  letter-spacing: 1rem;
}
.text-shadow {
  text-shadow: 1px 1px 0px #ff0000;
}

Which results in a dropdown like this:

tinymce-styles-dropdown-custom-items

Additional benefit of this approach: any changes in the CSS file will automatically update the dropdown. There's only one place to consider, when you need to add more custom styles.

The quick and dirty approach: adapt the JSON config of your custom profile

Quick example:

Click to expand JSON code sample
{
    "_config_name": "tinymce.profiles.testing",
    "name": "testing",
    "label": "Testing",
    "filter_allowed_html": "a,em,strong,cite,blockquote,ul,ol,li,h3,h4,h5,p,span",
    "tiny_options": {
        "toolbar": "bold italic blockquote | styles | bullist numlist | backdroplink backdropunlink | backdropimage code",
        "plugins": "backdroplink lists autoresize backdropimage",
        "contextmenu": "backdropimage backdroplink",
        "formats": {
            "mycustom": {
                "selector": "p",
                "classes": "my-class"
            },
            "small": {
                "inline": "span",
                "classes": "small"
            },
            "x-large": {
                "inline": "span",
                "classes": "x-large"
            }
        },
        "style_formats": [
            {
                "title": "Paragraph",
                "format": "p"
            },
            {
                "title": "Heading 3",
                "format": "h3"
            },
            {
                "title": "Heading 4",
                "format": "h4"
            },
            {
                "title": "My custom",
                "format": "mycustom"
            },
            {
                "title": "Small text",
                "format": "small"
            },
            {
                "title": "Large text",
                "format": "x-large"
            }
        ]
    }
}

In formats you define your custom block or inline formats and which classes TinyMCE should apply. Classes should be separated by spaces. Also see formats in TinyMCE docs.

In style_formats you define the elements to display in the styles dropdown (see toolbar settings). There you can set the order of elements and define the title to display your custom formats. Also see style_formats in TinyMCE docs.

The actual styles should go to a CSS file (in your theme), and that could get added to the "Content CSS files" admin setting on /admin/config/content/formats/FORMAT.

Example CSS in your theme:

p.my-class {
  font-size: 2rem;
  color: blue;
}
span.small {
  font-size: .7rem;
}
span.x-large {
  font-size: 2rem;
}

While this approach may appear a bit hacky, it's safe to do so. The profile builder won't touch the formats or style_formats options. However, having a backup of your JSON profile is recommended.

The sophisticated approach: hook_tinymce_options_alter()

You need a custom module for that, in our example the module name is "tinycustom". It consists of 3 files: tinycustom.info, tinycustom.module and in a subdirectory css/tinymce-custom.css

Content of tinycustom.info:

type = module
name = TinyMCE Custom
description = Customizes TinyMCE options.
dependencies[] = tinymce
backdrop = 1.x
stylesheets[all][] = css/tinymce-custom.css

Note that the CSS file is attached to all pages via info file.

Content of tinycustom.module:

<?php
/**
 * @file
 * Customizing TinyMCE.
 */

/**
 * Implements hook_tinymce_options_alter().
 */
function tinycustom_tinymce_options_alter(array &$options, $format) {
  // For this format we set custom styles dropdown content.
  if ($format->format == 'filtered_tinymce') {
    // Add CSS file to editor content. The editor loads in its own iframe.
    // Option `content_css` defines the styles to apply to its content.
    $module_url = base_path() . backdrop_get_path('module', 'tinycustom');
    $options['tiny_options']['content_css'][] = $module_url . '/css/tinymce-custom.css';

    // Custom content for the styles dropdown. CSS styles for that ship with the
    // css/tinymce-custom.css file from above.
    $options['tiny_options']['style_formats'] = array(
      // Re-use some of the default formats.
      array(
        'title' => 'Paragraph',
        'format' => 'p',
      ),
      array(
        'title' => 'Heading 2',
        'format' => 'h2',
      ),
      array(
        'title' => 'Heading 3',
        'format' => 'h3',
      ),
      // Now our custom items.
      array(
        'title' => 'Large text',
        'inline' => 'span',
        'classes' => 'large-text',
      ),
      array(
        'title' => 'Small text',
        'inline' => 'span',
        'classes' => 'small-text',
      ),
      array(
        'title' => 'Button link',
        'selector' => 'a',
        'classes' => 'specials custom-huge-button',
      ),
    );
  }
}

And finally css/tinymce-custom.css:

.large-text {
  font-size: x-large;
}
.small-text {
  font-size: small;
}
a.specials.custom-huge-button {
  font-weight: bold;
  text-decoration: none;
  color: #fff;
  background: #2a74b5;
  display: inline-block;
  padding: .5em 1em;
  border-radius: 7px;
}

The result looks like this:

screenshot of the expanded dropdown list

Note that the styles are applied to the item label in the dropdown - as a nice preview.

Also note that hook_tinymce_options_alter() can do a lot more than just adding styles. 😉