How To Create A Custom Block For Gutenberg

A rebirth of WordPress is underway. Like it or not, Gutenberg is coming, and it is going to change things. So, with all the buzz about Gutenberg, we decided to build our first custom block. In this post I’ll outline how the block was created, the resources used, and my feelings on the subject.

Let me preface this post by stating that I’m primarily a WordPress theme designer and developer. I’ve dabbled in a few plugins as well, but my JavaScript experience is limited to simple jQuery.

When I discovered that blocks were primarily developed in the ES5 and ESNext JavaScript languages, I was intimidated. Despite my ignorance of JavaScript and the lack of documentation on blocks, I managed to build a custom block. I learned a great deal in the process.

A Custom Block For Profiles

I found a handful of helpful resources for building custom blocks. However, the examples were extremely simple. I wanted to create something more practical. So, I settled on building a Profile Block for displaying a personal profile with social media links.

The Profile Block features an image, name, title, bio and social media links. It provided the opportunity to create a “RichText” block with custom controls and inspector options. Essentially, it utilizes every aspect of blocks.

The Profile Block plugin is available on Github and the WordPress plugin directory.

Note: The Profile Block requires the active Gutenberg plugin at this time.

Building The Block With ES5

I chose to build the Profile Block using ES5 JavaScript for a couple reasons. First, it was the easiest for me to understand. Second, ES5 is supported by modern browsers. So, I can develop locally without needing a compiler like Babel.

The Block Plugin Structure

Before we dig into the code, I think it’s important to look at the overall file structure of our plugin. It will give us a better understanding of the necessary components that make up a block.

  • organic-profile-block.php – Register our plugin and call our block files.
  • includes – Folder for any global block resources. In this case, our fonts.
  • block – Folder for custom blocks.
    • profile – Folder for the profile block.
      • block.js – The JavaScript file where we register our custom block.
      • editor.css – The styles for viewing the block within the Gutenberg editor.
      • font-awesome.css – The styles for our Font Awesome icons.
      • index.php – The file for enqueuing the block assets.
      • style.css – The styles for the front-end appearance of the block.

Enqueuing Scripts and Styles

We’ll start by registering and enqueuing the scripts and styles for our custom block in the index.php file. This process should be familiar to theme and plugin developers, and it’s the bulk of the PHP we will be working with.

First, we’ll register the scripts and styles for our custom block. Here, we will assign each registered file with a unique handle, and include any dependencies:

Next, we’ll use the register_block_type() function to enqueue the scripts and styles. Here, you will use the unique handles defined in your previously registered scripts and styles.

Enqueue the scripts and styles by assigning the appropriate handles to the following registration settings:

  • editor_script – Scripts loaded only within the editor. This is where you will enqueue the block.js file.
  • editor_style – Styles loaded only within the editor.
  • script – Scripts loaded both within the editor and the frontend of the site.
  • style – Styles loaded both within the editor and the frontend of the site.

Registering The Block

Within the block.js file, we’ll start by wrapping our block in a function with its dependencies. The dependencies should match what was previously defined in our index.php file:

Next, we’ll import the components needed for our block. There are many components available. Unfortunately, I haven’t found a library listing all the components with descriptions. So, finding and using the right components has been a process of trial and error.

Now, we register the custom block:

Edit And Save

Now that we have registered our custom block, we need to build the interface. The block interface is comprised of 2 parts. The edit function is the interface for the block within the editor. The save function saves the output of the block for the front-end.

If you’re like me, and JavaScript isn’t a strength, it may be easier to think of defining the elements in the same way you would structure tags for HTML.

For instance, let’s take this simple block element:

It’s essentially the same as this HTML:

The Edit Function

I’m going to break down the edit function into 4 parts — declaring variables, block controls, inspector controls, and the elements of our block.

First, we’ll setup our edit function and declare the variables:

Next, let’s setup our block controls. This section defines the controls available within the TinyMCE editor for the block. In this case, we are adding content alignment controls and a media upload button for adding and changing our profile image:

Next, we’ll add our inspector controls. These are the additional block options that can be set by clicking the “Block” tab within the editor. For the Profile Block, the social media links are added within the inspector controls:

Now, we will build the elements of block within the editor:

The Save Function

Now, we need to save the block. This function defines the output of the block on the front-end:

Finishing Up

There you have it! That’s the bulk of creating a custom block for the upcoming Gutenberg editor. Just add styles, and you will have a fully functioning custom block!

My Feelings

When I began working with WordPress in 2008, I was ignorant of PHP development and building custom themes. I struggled to find resources on the subject. As a result, I taught myself with the little bits of information I could find. Over time, I honed my skills. I became comfortable and confident with what I learned.

The announcement of Gutenberg was somewhat frightening because it disrupted my comfort zone. I knew it would force me to learn new ways of development, and it would force our business to evolve.

Any immediate dislike towards the new direction of WordPress was based in fear. However, that’s not a valid reason for disliking Gutenberg.

The fact of the matter is that developing for Gutenberg is much more difficult. It introduces new languages and dependencies to the platform. Some developers will evolve, some will flourish, some will resist change, and some will be left behind completely. New businesses will be born, and old businesses will die.

I believe the average WordPress user is still very unaware of the changes that are taking place. However, I think Gutenberg will be a very positive change. It’s a major step towards simplifying the platform. It will provide users with considerably more control over their content. Additionally, it will eliminate the need for many shortcodes, custom post types, page templates, and other WordPress relics. Eventually the old admin will fade away, as mentioned in my post about the Future of WordPress.

The more I work with blocks, the more potential I see. It feels like a rebirth of WordPress is on the verge of taking place. Frankly, it’s needed. I was feeling stagnant in my work as of late. Now, WordPress is new again.

WordPress was built by a community of people who just started poking around in the open source software. We bent the platform to meet our needs, and we learned along the way. Gutenberg is forcing us to do that all over again. If you can get over the shock of such a big change, it has the potential to be exciting.

The Future

Organic Themes is taking Gutenberg seriously. We believe blocks are the future of building pages and websites with WordPress. As a result, we intend to align our products with the upcoming editor. We are excited about the possibilities, and looking forward to a rebirth of our company with the integration of Gutenberg into core.

We anticipate our themes becoming a framework for blocks. They will focus on simplicity, with styles and layouts catered to the usage of blocks. Additionally, we have begun development on a suite of custom blocks for Gutenberg that will seamlessly integrate with any theme. Similar to widgets with our Customizer Widgets plugin, blocks will be used to display a variety of content sections on your site.

Block Resources

The links below are the resources I found most useful when building a custom block. Additionally, this post from WP Tavern lists several Gutenberg resources.

A huge thanks to the developers that have provided these resources!

Please feel free to contribute to the Git repo, and offer any constructive criticism in the comments below.

17 Comments on “How To Create A Custom Block For Gutenberg

  1. David,

    Back in October I was in an odd place. I’d been asked to build a website for a local community group and I’m also in the paperwork process of setting up a new charity (if all goes well it launches April 2018).

    I’d used WordPress for an local events group and I knew that the platform would be best suited to both new projects but Gutenberg arriving within the year really worried me. WordPress is long overdue this change and it’s a change that has too much backing to be stopped but it raised some key questions. Would I need to build these sites and in 6-12 months change everything to suit the new WP Way? Would I need to train, and train again the contributors to the site? Was it worth delaying everything to see where the land would lie in 6 months? All valid questions, even more so when it’s all volunteers times.

    Then, by accident, by searching for ‘Gutenberg WordPress Themes’ in Google I found a blog post on your site. What made the post different was that it was embracing the new. It was enough. for me, to decide then and there you were getting the sale. Thank you for writing it.

    The actual purchase came a little later (money is tight for the group and free is hard to combat!) but your teams service has been exceptional. I don’t see how I could have made a better choice.

    The single reason your company got the sale is because it’s being so open and so forward thinking with regards to Gutenberg. The fact your themes are delightful to work with (no clumsy dashboard extras, all changes are made in the customiser), posts remain easily transferable and your after sales support is second to none are incredible bonuses. Yes I might still have to make changes, including possibly replacing the theme but I am reassured by my experiences that if it is required it will be almost painless.

    Thank you for doing things the WordPress way. It makes life so much easier,

    • Hi David,

      Thanks for the awesome comment and kind words about our products and support! And thanks for your purchase! It’s definitely our goal to keep customers happy and create products that are easy to use. 🙂

      I think your questions and concerns regarding Gutenberg are definitely valid. One of the major strengths of WordPress has always been a focus on backwards compatibility. So, while the editor will change, the old ways of editing will still be available after Gutenberg has been implemented — most likely using the Classic Text block.

      Gutenberg can already convert content added within the classic editor into blocks. It works quite well, although you may experience some slight issues with spacing and styles that may need to be addressed, depending on your theme. However, there shouldn’t be any need to rebuild your sites after the update takes place.

      From a user perspective, I don’t foresee a big learning curve. If anything, I think Gutenberg is more intuitive than the existing editor. So, any training of volunteers or employees done before the change should not be lost. Granted, training might be easier after the change.

      Thanks again!

  2. Thank you for this tutorial. Do you find your way available to migrate some custom fields to Gutenberg blocks? I have some projects with plenty of CF, and I just wonder if it’s a good idea to relocate them to custom blocks to have involvement in the order of such a blocks…

    Thank you so much anyway!

    • Hi Mariusz,

      I’ve seen some issues on Github regarding potential ways to use legacy custom fields in the Gutenberg editor, https://github.com/elliotcondon/acf/issues/622

      Additionally, adding custom input fields and meta boxes to blocks is possible within the InspectorControls element. We have done this with the Profile Block for the social media link fields.

      Thanks!

  3. Hey David,
    thanks for this great tutorial!
    As I see from the code there is almost no PHP involved.
    Does that mean the block will be created by JavaScript alone, also in the front-end?
    What would that mean for SEO?
    Or am I missing something?
    Thanks,
    Andreas

    • Hi Andreas,

      Yes, blocks are created almost entirely using Javascript. However, the Javascript will output HTML on the front-end of the website. So, it will not have any negative effect on SEO.

      It does pose an issue for the large number of WordPress developers that are accustomed to coding in PHP.

  4. Hi David,

    Personally I’m excited about the direction that Gutenberg is taking WordPress in. My main concern though is how that will affect the many client sites we have already built in older versions of WordPress. I suppose in a way it’s an opportunity.

    Thanks for providing this resource!

    • True. The conversion of content to blocks seems to work well, but if you have made customizations to the classic WordPress editor for your clients, then Gutenberg could pose a problem.

      I imagine new services will arise around supporting the transition to Gutenberg for clients and users.

  5. Hi

    Thanks for sharing you code!

    I have a problem with my site:
    WP Version 4.9.6
    Organic Profile Block Version 1.1.1
    Gutenberg Version 3.0.1

    The Image-Upload button isn’t there. I had some warning in the console, so I tried to fix the warnings.
    I had to change the definitions of the vars from line 1 to line 9

    From:
    ( function( blocks, components, i18n, element ) {
    var el = element.createElement;
    var registerBlockType = wp.blocks.registerBlockType;
    var RichText = wp.blocks.RichText;
    var BlockControls = wp.blocks.BlockControls;
    var AlignmentToolbar = wp.blocks.AlignmentToolbar;
    var MediaUpload = wp.blocks.MediaUpload;
    var InspectorControls = wp.blocks.InspectorControls;
    var TextControl = wp.components.TextControl;

    To:
    ( function( editor, components, i18n, element ) {
    var el = element.createElement;
    var registerBlockType = wp.blocks.registerBlockType;
    var RichText = wp.editor.RichText;
    var BlockControls = wp.editor.BlockControls;
    var AlignmentToolbar = wp.editor.AlignmentToolbar;
    var MediaUpload = wp.editor.MediaUpload;
    var InspectorControls = wp.editor.InspectorControls;
    var TextControl = wp.components.TextControl;

    Also on line 329:
    From:
    window.wp.blocks,

    To:
    window.wp.editor,

    The warnings are fixed, but the Image-Upload button isn’t there yet. And there aren’t any other warnings or errors in the console. Do you have any idea or solution?

    Thanks & Regars

    • Thanks for the fix Dario! I’ll look into adding this and pushing an update to the plugin. 🙂

      Since Gutenberg is still in beta, it seems every new update to the plugin runs the risk of breaking custom blocks. This will be the 3rd time I’ve had to update the block code after a Gutenberg update. :p

    • I ran into this problem too and could not get the upload button to show up.
      In my case this was caused by Advanced custom fields. This issue have been resolved so it was fixed by updating the plugin. Hope it helps!

  6. Thanks so much for taking the time to put this together. I find practical examples like this much easier to learn from and understand than simply reading through the documentation and it saves a lot of trial-and-error.

  7. Hi David,

    Thanks for this amazing tutorial. I’ve created themes and plugins in the past, so I thought it was time to learn how to create a block.

    I installed your plugin, and then I created a new plugin based on your code. It resides in its own directory, and of course it has a unique name as the block type. When I enable my plugin, yours no longer appears in the Blocks panel. It seems that there is some conflict, so that one or the other is recognized by WordPress, but not both.

    Is there some sort of identified that I am missing in the code?

  8. It would be great to see a post on creating a container block with ES5, I have not seen a single post anywhere on how to do this 🙁

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.