How to Create A Custom Block Manually

Creating a custom block isn't an easy feat especially if you are not comfortable with pure JavaScript. We will you guide you slowly through the proces

Gutenberg (also knows as Block Editor) is the official drag-n-drop builder in WordPress version 5.0+.

Creating a custom block isn’t an easy feat especially if you are not comfortable with pure JavaScript. So before creating one, think whether we can achieve what we want with custom style in existing block.

Follow the steps below on how to create Gutenberg block with code:

1. Enqueue the Assets

Create a CSS and JS file then enqueue them. Don’t forget to adapt the file name to fit your project.

add_action( 'enqueue_block_editor_assets', 'my_editor_assets', 100 );

function my_editor_assets() {
  if ( !is_admin() ) { return; }
  
  $css_dir = get_stylesheet_directory_uri() . '/css';
  $js_dir = get_stylesheet_directory_uri() . '/js';

  wp_enqueue_script( 'my-editor', $js_dir . '/my-editor.js', [ 'wp-blocks', 'wp-dom' ] , null, true );
  wp_enqueue_style( 'my-editor', $css_dir . '/my-editor.css', [ 'wp-edit-blocks' ] );
}

2. The Basic Script

The codes below is a good starting point for creating a custom block:

( function( blocks, editor, element ) {
  var el = element.createElement;
  var RichText = editor.RichText;

  blocks.registerBlockType( 'my/simple-text', {
    title: 'Simple Text (Custom)',
    icon: 'universal-access-alt',
    category: 'layout',
    edit: function( props ) {
      // what's rendered in admin
    },
    save: function() {
      // what's saved and rendered in frontend
    },
  } );

}( window.wp.blocks, window.wp.editor, window.wp.element ) );
  • (Line 5) Block’s name – The format is namespace/id. It will be translated into class name. The example above will have .wp-block-my-simple-text as class name.
  • (Line 7) IconClick here List of available icons here.
  • (Line 9) Edit Function – Return the element to render in editor.
  • (Line 12) Save Function – Return the element that is saved in database and shown in front-end.

3. Implementing Edit & Save

( function( blocks, editor, element ) {
  var el = element.createElement;
  var RichText = editor.RichText;
  var props;

  blocks.registerBlockType( 'my/simple-text', {
    title: 'Simple Text (Custom)',
    icon: 'universal-access-alt',
    category: 'layout',
    example: {},
    edit: _simpleTextEdit,
    save: _simpleTextSave,
  } );

  //
  function _simpleTextEdit( _props ) {
    props = _props;

    return el( RichText, {
      tagName: 'p',
      onChange: _onChange,
      value: props.attributes.text,
      className: props.className,
    } );
  }

  function _simpleTextSave() {
    return el( RichText.Content, {
      tagName: 'p',
      value: props.attributes.text,
    } );
  }

  function _onChange( newContent ) {
    props.setAttributes( { text: newContent } );
  }
  
}( window.wp.blocks, window.wp.editor, window.wp.element ) );
  • (Line 4) New props variable to hold the content.
  • (Line 11 & 12) Moved the functions below so it looks tidier.
  • (Line 19 – 24) Edit Function – Create a RichText field wrapped with <p>, add listener when changed, and populate the existing value and class name (from Advanced tab).
  • (Line 28 – 31) Save Function – Data that is saved is <p> element with the content from RichText.
  • (Line 34) onChange Listener – Update the props so it can get saved properly.

4. Check the Result

Selecting the custom block
Our “Simple Text” custom block in action

That’s Too Complex, Any Plugin?

Yes, just like the old-saying in WordPress: “There’s a plugin for that”.

So far I have tried LazyBlock and ACF Pro. LazyBlock is easier to use but ACF Pro is much more customizable because you can use any ACF fields.

One thing I don’t like about both of them is how out-of-place they look compared to the native block.


Conclusion

Creating a custom block is difficult and can get ugly. So always try to repurpose an existing block if possible. Need a block for Namecard? Media-Text block might be a good replacement.

If you are interested to learn multi fields block, check out the official example in Github. We are basing this tutorial on that example too.

Feel free to leave a question below regarding custom block 🙂

Default image
Henner Setyono
A web developer who mainly build custom theme for WordPress since 2013. Young enough to never had to deal with using Table as layout.
Leave a Reply