Creating theme editor styles for Gutenberg

WordPress 5 will come with a new editor called »Gutenberg«, which is completely different from the current TinyMCE. That does not only mean change for the users, but also for theme developers, who want to modify editor styles, so it looks like in the frontend. This post shows you how that works for the new editor.

The previous procedure with TinyMCE: quite pleasant

The post content in the TinyMCE editor lives inside an iFrame, that means theme specific styles can be written similar to the frontend CSS. There is a normal website’s markup in the DOM just for the content, the visible content is inside a body element, and inside the body, there are the content elements directly, like paragraphs, headings, et cetera. That is how the DOM looks like:

DOM of this post’s content in the TinyMCE. (Screenshot: Firefox dev tools)

With that, it is not that difficult to implement the basic styles of the theme into TinyMCE.

The procedure with Gutenberg: not so pleasant

With Gutenberg, it is slightly different. First, the editor does not sit in an iFrame, which in itself is good. Among that, all content elements are so-called blocks, which are wrapped in divs that have spacing around them, et cetera. The DOM of this post looks like that in Gutenberg:

DOM of this post’s content in the Gutenberg editor. (Screenshot: Firefox dev tools)

Very complex compared with the content’s markup in TinyMCE…

So much for the starting point. But before we can start writing the CSS rules, let us begin loading the stylesheet. Helpful for me was the article »How to add WordPress Theme Styles to Gutenberg« by Rich Tabor.

Including a stylesheet for Gutenberg modifications

Including the stylesheet is not that hard:

// Add backend styles for Gutenberg.
add_action( 'enqueue_block_editor_assets', 'photographus_add_gutenberg_assets' );

/**
 * Load Gutenberg stylesheet.
 */
function photographus_add_gutenberg_assets() {
	// Load the theme styles within Gutenberg.
	wp_enqueue_style( 'photographus-gutenberg', get_theme_file_uri( '/assets/css/gutenberg-editor-style.css' ), false );
}

We hook a function to the enqueue_block_editor_assets hook and add the stylesheet via wp_enqueue_style. Now to the CSS rules.

Writing styles for Gutenberg

Gutenberg comes with styles we need to overwrite. We can use .edit-post-visual-editor as the wrapper for the content, the blocks itself have the .editor-block-list__block class.

We need to be careful to not modify styles of the inline toolbar or other inline tools from Gutenberg. Useful classes are:

  • .mce-content-body – used for many text block elements, like headings, paragraphs (but not the ones inside of blockquote elements), lists, and so on.
  • .wp-block-quote – a class for block quotes.
  • .editor-block-list__block-edit – wrapper inside of .editor-block-list__block for the content element.

My current state of editor styles for Gutenberg in my Photographus theme looks like the following in SASS (I removed media queries to make it shorter):

@import "abstracts/variables";
@import "abstracts/functions";
@import "abstracts/mixins";

.edit-post-visual-editor .editor-block-list__block {
	color: $color-tundora;
	margin: 0 auto;
	max-width: $content-max-width;
}

.edit-post-visual-editor p,
.edit-post-visual-editor,
.blocks-rich-text__tinymce.mce-content-body {
	line-height: inherit;
	font-size: inherit;
}

.edit-post-visual-editor .editor-block-list__block-edit,
.edit-post-visual-editor {
	font-family: "PT Serif", Georgia, serif;
	font-size: 1em;
	line-height: $line-height;
}

.edit-post-visual-editor .editor-block-list__block {
	h1,
	h2,
	h3,
	h4,
	h5,
	h6 {
		&.mce-content-body {
			font-weight: 400;
		}

	}

	h1.mce-content-body {
		font-size: 1.802em;
		line-height: line-height(1.802, 1.5);
	}

	h2.mce-content-body {
		font-size: 1.602em;
		line-height: line-height(1.602, 1.5);
	}

	h3.mce-content-body {
		font-size: 1.424em;
		line-height: line-height(1.424, 1.25);
	}

	h4.mce-content-body {
		font-size: 1.266em;
		line-height: line-height(1.266, 1.25);
	}

	h5.mce-content-body {
		font-size: 1.125em;
		line-height: line-height(1.125, 1);
	}

	h6.mce-content-body {
		font-size: 1em;
		line-height: line-height(1, 1);
	}

	figure {
		line-height: 0;
		margin: add-unit($space-half, 'em') 0 0;

		figcaption,
		img {
			line-height: $line-height;
		}
	}

	figcaption {
		clear: both;
		color: inherit;
		font-size: $font-size-small;
		padding-top: add-unit($space-quarter, 'em');
		text-align: left;
	}

	blockquote.wp-block-quote {
		border-left: 2px solid;
		padding-left: add-unit($space-half, 'em');
	}

	blockquote.wp-block-quote cite {
		display: block;
		font-style: italic;
		margin: add-unit($space-quarter, 'em') 0 0;
	}

	table {
		border-spacing: 0;
	}

	td,
	th {
		border: none;
		border-bottom: 1px solid;
		padding: add-unit($space-quarter, 'em');
	}

	th {
		border-bottom: 2px solid;
		text-align: left;
	}

	table tr:last-of-type td {
		border-bottom: none;
	}

	dt {
		margin: add-unit($space-quarter, 'em') 0 0;
	}

	dd {
		margin: 0 0 0 add-unit($space, 'em');
	}

	ul,
	ol {
		padding-left: 1rem;
		margin-left: 0;
	}

	ul > li {
		list-style-type: none;
		position: relative;
	}

	ul > li::before {
		content: "·";
		left: -#{add-unit($space-half, 'em')};
		top: 0;
		position: absolute;
	}

	li + li {
		margin: add-unit($space-quarter, 'em') 0 0;
	}

	ul ol,
	ol ul,
	ul ul,
	ol ol {
		margin: add-unit($space-quarter, 'em') 0 0;
	}
}

.edit-post-visual-editor .mce-content-body {
	a {
		box-shadow: inset 0 -1px 0 currentColor;
		box-shadow: inset 0 -1px 0 currentColor, 4px 0 0 transparent, -4px 0 0 transparent;
		box-decoration-break: clone;
		color: inherit;
		padding-bottom: .05em;
		padding-top: .05em;
		text-decoration: none;
		-webkit-text-decoration-skip: objects;
		transition: box-shadow .2s ease 0s, background .2s ease 0s;
	}

	a:active,
	a:hover {
		box-shadow: inset 0 -1px 0 transparent;
		outline-width: 0;
	}

	a:focus {
		background: $color-tundora;
		box-shadow: inset 0 -1px 0 $color-tundora, 4px 0 0 $color-tundora, -4px 0 0 $color-tundora;
		color: $color-white;
		outline-width: 0;
	}
}

First, I reset some styles of Gutenberg and define my base styles, like font and line height. After that, I define styles for the block elements and in the end for the inline elements, that live inside .mce-content-body (currently, that are just links in my stylesheet).

An unresolved problem for me is to define the spacing between elements in Gutenberg. If we want, for example, give the headings space to the top, the inline toolbar would float far away from the actual text.

That is a screenshot from Gutenberg with the current result:

The editor styles for Gutenberg in action. (Screenshot: own installation)

I am quite happy with that for now.

Like you can see, writing editor styles for Gutenberg is a little bit of trying and not made quickly. What you should avoid is: just take the styles for TinyMCE, copy them and think it will work. That could break the styles of the editor.

Related posts

Leave a Comment

Your email address will not be published. Required fields are marked *