Custom Gutenberg Blocks: React or PHP?

Choose React when the block’s editing interface is the product, core PHP-only blocks when a few settings and server-rendered HTML are enough, and a PHP tool when you need richer fields or containers without a build step.

The WordPress block editor is written in React, and for years custom blocks had to be written in React too. Since WordPress 7.0, core can also register simple blocks from PHP alone. And most blocks on real websites don’t need a custom React interface: they need a few fields and some HTML. Here’s what each approach actually gives you.

What a block needs, technically

Every block has an editor side (how it appears and which settings it shows while editing) and a front end (the HTML visitors get). The front end can be saved as static HTML, or rendered by PHP on each request. So “React or PHP” really means: who writes the editor side, and who renders the front end?

A dynamic block is not a block without an editor. It is a block whose front-end HTML is generated by PHP at request time instead of being saved into the post.

The React approach

npx @wordpress/create-block gives you a plugin where edit.js defines the editor UI in React/JSX, and either save.js (static HTML) or render.php (dynamic) defines the output. You build it with webpack through @wordpress/scripts.

What you get:

  • Full control over the editor: custom toolbars, drag handles, live-editable text (RichText), media pickers wired exactly how you want.
  • Static blocks: output saved in the post, so it renders even without the plugin active.
  • The same stack as core, with the most examples and documentation.

What it costs:

  • Node.js and a build step for every change.
  • Two templates to keep in sync: the React preview and the front-end output.
  • A skill set many WordPress developers and agencies don’t use day to day.
  • Markup changes don’t reach existing content. A static block’s HTML is saved in every post. Change the block and those posts keep the old HTML until each one is opened and re-saved, so visitors don’t see the change. The editor marks the old blocks as invalid unless you write a deprecation for each earlier version.

PHP-only blocks in WordPress core

Since WordPress 7.0, core registers a block from PHP alone: register_block_type() with autoRegister under supports and a render_callback. The editor generates the sidebar controls for string, number, integer and boolean attributes.

What you get:

  • No JavaScript and no build step, with nothing to install.
  • One PHP function renders the block in the editor and on the front end.

What it costs:

  • Basic fields only. No image, color, link or date controls.
  • No nested blocks, and no text typed directly in the canvas.
  • The dev note says it “isn’t meant to replace the existing client-side paradigm”.

The code is in how to create a custom Gutenberg block without React.

The PHP approach with a tool

Here the front end is always a dynamic block rendered by PHP, and the editor shows a preview of that same PHP. Settings appear in the sidebar as native WordPress controls. A tool such as FanCoolo WP writes the registration for you and adds the parts core leaves out: more field types, nested blocks and SCSS.

What you get:

  • One template. The editor preview and the front end come from the same PHP, so they can’t drift apart.
  • No build step. Edit, save, refresh.
  • Changes apply everywhere at once. Nothing is saved into the posts, so a template change shows on every page on its next load.
  • Easy dynamic data. Query posts, read post meta or ACF fields, check the current user: it’s just PHP.

What it costs:

  • Less inline editing. Content is edited in sidebar fields rather than typed directly into the block (unless you use nested blocks for the editable parts).
  • Rendered per request. Dynamic blocks run PHP on every page view, like any PHP template. Page caching handles this well.

A middle path: nested blocks

The “no inline editing” limit is smaller than it sounds. A PHP block can be a container: you render the wrapper and layout in PHP, and let editors type headings, paragraphs and buttons with normal core blocks inside it (InnerBlocks). You get a fixed design with a comfortable editing experience, still without React. Core’s PHP-only blocks can’t do this; ACF Blocks and FanCoolo WP can.

How fast do the blocks render?

We measured the server time to render one small testimonial block (two text fields, the same HTML) built four ways:

Block typeTime to render one blockCompared with a React static block
FanCoolo WP with Static output (coming in 1.4.1)10.0 µsabout 3× faster
React static block (HTML saved in the post)29.3 µsbaseline
Core PHP block with a render_callback50.7 µs1.7× slower
FanCoolo WP, normal dynamic rendering427.3 µsabout 15× slower

Static output is coming in FanCoolo WP 1.4.1; it is not in the current release. It stores a block’s rendered HTML and serves it without running the template, and re-renders the stored HTML when you change the template, so you get the speed of saved HTML without the stale-content problem.

Method: WordPress 7.1.2, PHP 8.3 with OPcache, a development build of FanCoolo WP 1.4.1, 2 October 2026. Each variant was rendered 3,000 times per run, and the table shows the median of 15 runs. No variant made a database query. These are microseconds per block on one server: with page caching, visitors won’t notice the difference between any of them.

How to decide

Choose React when…Choose core PHP-only blocks when…Choose a PHP tool when…
The editing UI itself is the product (drag-and-drop builders, complex interactions)The block needs a few text, number or on/off settingsThe block needs image, color, link or post-picker fields
You want static HTML saved in the postThe output is server-rendered and has no nested blocksThe block is a container for other blocks
Your team already works in ReactYou want no dependency beyond WordPress 7.0+Your team works in PHP, or hands sites to clients
You’re building for the WordPress.org block directoryYou’re fine writing the registration by handYou want fields, SCSS and reusable parts managed in one place

For the tool path, FanCoolo WP, which we build at DPlugins, does the wiring for you: you write the PHP render, add fields in a visual Attributes Manager (they appear as native sidebar controls), enable nested blocks in the block’s settings, and FanCoolo generates block.json and the editor registration.

FAQ

Can Gutenberg blocks be written entirely in PHP?

Yes, since WordPress 7.0, for simple server-rendered blocks. Richer editing still needs JavaScript or a tool.

What can’t a PHP-only block do?

No text typed directly in the canvas, no nested blocks, and sidebar controls only for string, number, integer and boolean attributes.

Do dynamic blocks hurt performance?

A dynamic block runs PHP on each page view, like any template. With page caching, visitors get the cached HTML either way. Our measurement above puts the difference in microseconds per block.

Sources

Skip the React toolchain

Skip the React toolchain

Build native Gutenberg blocks in PHP with FanCoolo WP: visual fields, nested blocks, SCSS and hot reload.

More comparisons

See all WordPress comparisons.