Creating a Gutenberg Block
A tutorial on how to build a Gutenberg block. The intended audience is a WordPress theme or plugin developers with some Javascript experience interested in learning what it takes to create a block in the new Gutenberg editor.
Updated: See my new post post Gutenberg blocks without the build step for a simpler example without the extra JavaScript workflow and ES6 build step.
Screenshot of Gutenberg editor
Background
Gutenberg is the project bringing a new editor to WordPress. The editor is based on content blocks of various types; types may be text, images, embeds, galleries, etc. A block really could be any combination of things, it is just a basic unit to add rich content to the editor in a structured way.
Why do we need blocks? The current WordPress editor experience can be confusing, especially for new users. A lot of functionality is hidden away in strange shortcodes, settings or requires lots of fiddling to get right. Gutenberg's core goal is to make an easy and consistent way for people to create rich content on WordPress.
Building a Block
The main way a developer can extend Gutenberg is to create their own block. Just like core WordPress, Gutenberg is extensible and pluggable; meaning a developer can create a plugin that adds their own block to Gutenberg.
Here's how.
A little PHP
Gutenberg blocks are mostly Javascript, but the way they are added to WordPress is the same way as any other plugin; a little bit of PHP. In this case, using the standard wp_enqueue_script which adds your Javascript file to the page.
function mkaz_editor_bloko() {
wp_enqueue_script(
'mkaz-bloko',
plugins_url( 'block.built.js', __FILE__ ),
array( 'wp-blocks', 'wp-element' )
);
}
add_action( 'enqueue_block_editor_assets', 'mkaz_editor_bloko' );
Javascript Workflow
To create the Javascript file that includes your Gutenberg block we use a modern workflow. Gutenberg is built using EcmaScript (ES6) which is a little newer/cleaner Javascript syntax than you might be used to if you primarily worked with JQuery.
If you are unfamiliar with ES6 and newer syntax, it will help you understand Gutenberg more by learning a little, see resources section below. Hopefully you can still follow the code just fine, but even I get confused when too much magic happens on one line.
Using ES6 is great for new browsers, but not compatible for all browsers and versions. So we use a build procedure using Babel & Webpack to convert to a compatible syntax.
Setting it up is straight-forward, especially when you copy your config. I grabbed the package.json, .babelrc, and webpack.config.js files from the gutenberg examples repo.
Copy the files to your repository, webpack.config.js might be the only file that needs any modifications, update to point to the file names you want.
Build tools use node.js and npm, install dependencies: npm install
Now as you're building your block, keep npm run dev
going in a terminal window. This will build a development version of your block on each save.
When you're ready to ship it, run npm run build
and it will build a production version of block.built.js
which you can commit with your plugin.
Simple Block
Here is the simplest possible block. It is a static block that simply inserts <h1>Bloko</h1>
.
const { registerBlockType } = wp.blocks;
registerBlockType( 'mkaz/bloko', {
title: 'Bloko',
icon: 'carrot',
category: 'common',
edit() {
return <h1>Bloko</h1>;
},
save() {
return <h1>Bloko</h1>;
},
} );
Each block is registered with a name-spaced name, in this case: mkaz/bloko
The title, icon, and category for the block control how it shows up in the inserter, see Dashicons for available icons.
The crux of a block is the edit()
and save()
functions, which are JSX components that describe your block. The edit()
function is the block content when in the editor, and save()
is the HTML to get saved. In this very simple case, they are the same.
See Gutenpride plugin for a full working example of a simple static block. You'll notice it is only a few minor differences from above, just to make it translatable.
Editable Block
You likely want to go beyond static content and create an editable block based on some sort of user input. Here is an example block which has a single editable field. <Editable/>
is a JSX component provided by Gutenberg Core. JSX is a syntax extension, like a template language, that gets compiled to Javascript.
Gutenberg provides a set of various JSX components you can use to build your block interface, from controls to media uploaders to color pickers, see Gutenberg documentation link in resources below.
const { registerBlockType, Editable, source: { children } } = wp.blocks;
registerBlockType( 'mkaz/bloko', {
title: 'Bloko',
icon: 'carrot',
category: 'common',
attributes: {
title: {
type: 'string',
source: children( 'h1' ),
},
},
edit: props => {
const attr = props.attributes;
const onChangeTitle = newTitle => {
props.setAttributes( { title: newTitle } );
};
return (
<Editable
tagName="h1"
placeholder="Your Title…"
value={ attr.title }
onChange={ onChangeTitle }
focus={ attr.focus }
onFocus={ attr.setFocus }
/>
);
},
save: props => {
const { attributes: { title } }: props;
return <h1> { title } </h1>;
},
} );
Attributes store the data for the block. These should be included, when possible, in the HTML itself, either as the content or as HTML attributes. Gutenberg will also use HTML comments around blocks to store information that can not be encoded within the HTML.
When a block loads it pulls the data out of the HTML. How it pulls the data is defined by attributes
which specifies variables and their form. In the block example above, attributes defines a title
variable that uses children()
method to get the content of the H1 tag in this block. See attributes reference, for other ways to parse.
If you are familiar with React, you can see that attributes are passed as props to the edit and save methods. The components there use and set the attributes as needed. If you are unfamiliar with React, check out the React tutorial.
You can add multiple components to the same block. Using multiple editable fields makes it really easy to create template blocks. My simple Haiku block is one example, or a more elaborate example see the Recipe Card block.
Summary
Hopefully I showed you how you can get started creating your own Gutenberg blocks. I'm pretty excited for the opportunities block level editing is bringing to WordPress and all the ways the editing experience can be enhanced.
Links
- We Called it Gutenberg for a Reason a post from Matt Mullenweg, co-founder of WordPress, on reasoning behind Gutenberg project.
- Gutenberg, or the Ship of Theseus a post from Matias Ventura, technical project lead of Gutenberg.
Gutenberg Resources
- Core Gutenberg Documentation
- Gutenberg Core Components
- One thousand and one way to extend Gutenberg today by Riad Benguella, a co-worker and other core contributor to Gutenberg. His article goes into more details discussing the various way to extend Gutenberg.
Javascript, ES6, and JSX Resources
- Understanding ECMAScript 6 by Nicholas C. Zakas,
- ES6 features by Luke Hoban,
- Destructuring assignment - MDN Documentation, and
- ES6 & Beyond - online book by Kyle Simpson
- JSX Tutorial
- Intro to React Tutorial