A dynamic WordPress block generates its front-end HTML when WordPress renders a page instead of storing a complete HTML snapshot in post content. That makes it the right choice for content driven by current server data—such as latest posts—or for markup and styling that may need to change across already-published pages.
Antihost offers managed WordPress hosting with free migration, one-click staging and a 14-day free trial.
The official workflow is to scaffold a dynamic block, define its contract in block.json, build an editor interface, render on the server with render.php or a render_callback, return the correct value from save(), and compile production assets with npm run build.
As an Amazon Associate I earn from qualifying purchases.
Recommended Free Tools
What a dynamic block does
A block is dynamic when WordPress creates its front-end markup at request time. The post stores the block delimiter and its attributes, then the registered PHP renderer receives those values and returns HTML for the current request.
That separation matters when the output depends on data that can change without anyone editing the post. A “latest posts” list, an inventory count, a logged-in user’s status, or a query whose results change daily should not require editors to open and resave every page. It also lets a developer improve the generated markup or styling for existing block instances without causing saved-markup validation failures.
#1 Best Overall
- [Ultra-Lightweight Ear Buds Designed for Small Ears] Each earbud weighs only 3.7g and features a compact, ergonomic in-ear design made especially for small ears. Secure, low-profile, and comfortable for workouts, all-day wear or overnight sleeping.The ultra-slim profile sits flush in your ear with no hard edges poking or rubbing, so you can even sleep on your side without discomfort.
- [Immersive Stereo Sound with TOZO OrigX Technology] TOZO OrigX tuning delivers clear vocals, balanced mids, and natural stereo sound for music, podcasts, and videos.
- [Long Battery Life for Daily Use] Get up to 7 hours of playtime on a single charge, with up to 32 hours total using the charging case—ideal for workdays, commuting, and extended listening sessions.
- [Bluetooth 5.3 & Stable Connection] Bluetooth 5.3 provides fast pairing, stable wireless performance, and reduced dropouts as you move around home or office.
- [Deep Bass with Clear Vocals] High-performance drivers produce punchy bass while keeping vocals clean and detailed for everyday listening.
| Concern | Dynamic block | Static block |
|---|---|---|
| Where front-end HTML is produced | On the server when the page is rendered | When the post is saved in the editor |
| Data freshness | Reflects current server data at request time | Shows the saved output until the post is updated |
| Validation behavior | save() === null avoids comparing a generated snapshot with current output |
Changed generated markup can trigger a block-validation warning |
| Request cost | Adds server work for each uncached render | Stores ready-to-display markup in post content |
| Failure behavior | Can provide fallback HTML, but a missing renderer may remove output | Saved markup can remain visible if the block code is unavailable |
Use a static block when the saved markup is the source of truth and does not depend on changing server state. Use a dynamic block when freshness, centralized markup changes, or server-side decisions outweigh the extra rendering work.
Prepare the plugin and block identity
Scaffold the official project
Run the WordPress block scaffolding tool from a development environment with Node.js and npm available:
Do these 3 things before closing this tab:
1Scan for outdated or missing drivers - takes under a minute2Repair Windows errors before they cause bigger problems3Fix the driver behind crashes, sound loss and screen glitchesnpx @wordpress/create-block@latest my-dynamic-block --variant=dynamic
The command creates a plugin directory containing PHP registration code, JavaScript source, styles, metadata, and the build configuration. Keeping the block in a plugin is usually safer than coupling it to a theme: changing themes then does not remove the block’s registration and rendering code.
Choose a namespace and slug once
Every block name follows the namespace/slug form. In the example, the slug determines the project folder and contributes to the internal block name. Pick a stable, project-specific namespace before publishing. Renaming it later creates a different block identity, so existing content will not automatically become instances of the renamed block.
Define the block contract in block.json
block.json is the shared metadata contract used by the editor, the block registry, and the server renderer. Its attributes declaration describes the values passed to the editor’s Edit component, to save(), and to PHP rendering. The render property can point to a PHP template; that property was introduced in WordPress 6.1.
{
"apiVersion": 3,
"name": "acme/latest-posts",
"title": "Latest Posts",
"category": "widgets",
"attributes": {
"count": { "type": "number", "default": 5 }
},
"editorScript": "file:./index.js",
"render": "file:./render.php"
}
How the attribute definition is used
type: tells WordPress how to parse and serialize the value.default: supplies a predictable value when an editor has not changed the control.- Editor data: the same attribute is available to
Editfor controls and previews. - Saved data: the value is serialized into the block comment when the block is saved.
- PHP data: the renderer receives the value in the
$attributesarray.
Add every value that changes the output to this contract. Do not rely on an editor-only variable that PHP cannot receive, and do not accept an attribute without validating it before using it in a query or in output.
Rank #2
- 【IP68 Waterproof Multifunctinal Smart Watch】Torjalph fitness activity tracker smart watch is IP68 waterproof technology ,you can wear it when swimming,handwashing,it's rain-proof which means that you perform multiple exercise modes outside without worrying about sweat or rain corroding your fitness smart watch,and this watch equipped with a 230 mAh large capacity battery magnetic charging ,and this sports activity tracker watch can be used 5-7 days If fully charged.
- 【Larger 1.83'' Full Screen Watch & Multi-dial Selection】1.83 inch full HD color touch screen smart watch for men / women provides excellent 240*284 resolution image quality ,This Bluetooth smart watch offers a better touch experience and remarkable immersion and ,more than 200 watch faces for you to choose from App"Da Fit ", you can change the dial style according to your mood to wear keeping the world on your wrist
- 【Accurate Activity Tracker Smart Watch 】sports watch activity tracker uses sweat and dust resistant breathable silicone strap, our Fitness Tracker Smart Watch for Android iOS Phones supports 12 sports modes,walking,running,bicycle,swimming,badminton,basketball,football,rope skipping. This bluetooth calls smart watch for men women is lightweight and stylish, bringing more convenient and relaxing sports experience while also providing more protection.
- 【Your 24 Hour Personal Daily Health Monitor】Fitness watch for women men full touch screen IP67 waterproof bluetooth smartwatch for Android iOS Phones with heart rate blood pressure monitor multifunction Andriod smart watch with steps counter sleep monitor sports fitness watch, monitoring blood oxygen saturation allows you to understand your physical condition in real time to track fitness progress ,to know your health status in time.
- 【More Functions Bluetooth Call Smart Watch】This fitness activity smart watch full screen for iPhone and Android phones includes a bunch of new features including:The bluetooth smart watch can hang up the phone, receive and display WhatsAPP /Text /Facebook /Twitter /Messenger reminder.Support sedentary reminder, alarm clock, stopwatch, timer,weather information,music control, remote camera control compatible with Android 5.0 and above or iOS 9.0 and above smartphones.
Build the editor interface
The editor component should give authors controls for the attributes and a clear representation of the block’s state. Use WordPress block-editor components and useBlockProps() for the editor wrapper. The wrapper keeps the block’s class names and supports-related attributes aligned with the front end.
import { __ } from '@wordpress/i18n';
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import { PanelBody, RangeControl } from '@wordpress/components';
export default function Edit( { attributes, setAttributes } ) {
const { count = 5 } = attributes;
return (
<>
setAttributes( { count: value } ) }
/>
{ __( 'Latest posts will be loaded on the front end.' ) }
>
);
}
The editor does not need to duplicate every detail of the final PHP markup. For simple blocks, a labelled placeholder is often clearer than a misleading preview. If authors need to see live server output, add a server-side preview as described below.
Render the front end with render.php
When block.json names a render file, WordPress loads that file for each instance. The template receives three exposed variables:
Windows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallOutdated Drivers Are Slowing You Down
One free scan finds every outdated or missing driver and matches the right update for your exact hardware.Free scan · exact hardware match$attributescontains the values declared inblock.json.$contentcontains saved inner content, including serialized inner blocks when applicable.$blockcontains the current block instance and its context.
This complete example reads a bounded count, queries published posts, applies the standard block wrapper, and escapes each value for its context:
<?php
$count = isset( $attributes['count'] ) ? absint( $attributes['count'] ) : 5;
$posts = get_posts(
array(
'numberposts' => $count,
'post_status' => 'publish',
)
);
?>
<ul <?php echo get_block_wrapper_attributes(); ?>>
<?php foreach ( $posts as $post ) : ?>
<li>
<a href="<?php echo esc_url( get_permalink( $post ) ); ?>">
<?php echo esc_html( get_the_title( $post ) ); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
Use the wrapper helper on the front end
get_block_wrapper_attributes() adds the classes and attributes generated by block supports, such as alignment or spacing settings. Pair it with useBlockProps() in the editor so the editor and front-end wrappers remain structurally compatible.
Rank #3
- [Low Noise High Fidelity] New bee guitar cord with 22AWG oxygen-free-copper center conductors provides enhanced signal transfer, the PVC insulation material and the high-density stranded copper double shield provide noise rejection for quiet operation
- [Ideal for Choice] New bee 1/4 straight and right angle metal connectors, ensures a secure connection in any instrument, pedal, or amp jack. L shape great fro on stage guitar stands
- [Wide Compatible] Suitable for mixer, power amplifier, microphone, effector, decoder, equalizer, electoronic organ, electric guitar, electric bass and other electronic equipments. Widely used in the installation of smart home, karaoke speaker, professional stage audio, etc
- [Easy Disassemble] Making incidental repairs quick and easy! Very nice, flexible cable
- [Dont Hesite to Order] 24 hours customer services and professional technology team are standing by
Escape at the point of output
Escape according to the output context, not as a blanket final step. Use esc_html() for text, esc_url() for URLs, and the appropriate attribute or HTML sanitization helper for other contexts. When returning generated block markup from a callback, the official tutorial demonstrates sanitizing the resulting fragment with wp_kses_post().
Use a render_callback when registration needs PHP logic
A PHP callback is an alternative to a template file. Register the block with register_block_type() and provide a callable under render_callback:
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
function acme_latest_posts_render( $attributes, $content, $block ) {
$count = isset( $attributes['count'] ) ? absint( $attributes['count'] ) : 5;
$posts = get_posts(
array(
'numberposts' => $count,
'post_status' => 'publish',
)
);
$output = '<ul ' . get_block_wrapper_attributes() . '>';
foreach ( $posts as $post ) {
$output .= '<li><a href="' . esc_url( get_permalink( $post ) ) . '">';
$output .= esc_html( get_the_title( $post ) );
$output .= '</a></li>';
}
$output .= '</ul>';
return wp_kses_post( $output );
}
register_block_type(
__DIR__ . '/build',
array(
'render_callback' => 'acme_latest_posts_render',
)
);
Both approaches receive $attributes, $content, and $block. Choose the template when markup should be easy to read alongside HTML. Choose a callback when rendering requires reusable PHP functions, branching, or registration that is already centralized in a plugin.
| Choice | Best fit | Watch for |
|---|---|---|
render.php |
Mostly markup with a modest amount of PHP | Keep data preparation and escaping clear inside the template |
render_callback |
Complex logic, shared functions, or conditional registration | Return a string and escape or sanitize every interpolated value |
Decide what save() should return
Return null for a fully server-rendered block
If PHP produces the entire front-end output, the JavaScript save() function can return null:
export default function save() {
return null;
}
WordPress then stores the block delimiter and its attributes rather than a complete HTML snapshot. On the front end, the renderer generates the current markup. This is the usual choice for a block whose output is entirely dynamic.
Preserve nested blocks with InnerBlocks.Content
A dynamic parent does not automatically preserve nested block content just because it renders on the server. If the block contains InnerBlocks, save the nested content explicitly:
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Rank #4
- Digital Family Calendar: BSIMB digital calendar wall touch screen puts an end to your chaotic life. Designed for busy families, the digital calendar keeps you organised and in step with your family. Assign different colours and tasks to each family member to make family scheduling easier and more intuitive.
- Easy Setup and Auto-Sync: Plug in, connect to WLAN and auto-syn your electric calendar in minutes. Digital wall calendar compatible with Google calendar, iCloud calendar, Outlook calendar, Cozi calendar and Yahoo calendar. Add events directly on the device or through the ecalendar app. Electronic calendar stays current whether you're at work or traveling—no manual updates needed.
- All-In-One Home Assistant: Smart calendar builds habits and encourage independence with personalised chores. Display daily meal plan to reduce the daily ‘What's for dinner?’ stress. To-do lists keep track of everything you want. Turning chores into valuable achievements with stars and rewards, making life easier and more enjoyable.
- Manage Anytime Anywhere: BSIMB electronic calendar for family stay connected with the powerful ecalendar app. Access and manage your digital wall calendar anytime, anywhere with free features like stars & rewards, photo screensaver, chore charts, meals plans, to-do lists etc. Electronic planner paid features like Magic Import tailor advanced tools for users with special needs.
- Stay in Touch with Loved Ones: Share photos or videos from your phone to electronic wall calendar with app, instantly update your life moment, and keep in touch with your family, especially those who are far away; you can also surprise your smart calendar digital wall by sending him a wish card; it's also great for keeping tech-illiterate elders in touch with the youngsters.
import { InnerBlocks } from '@wordpress/block-editor';
export default function save() {
return <InnerBlocks.Content />;
}
The PHP renderer can then use the supplied $content when assembling the parent output. Failing to save it causes nested editor content to disappear from the serialized post.
Use fallback HTML deliberately
A dynamic block may save fallback HTML that remains visible if its plugin is deactivated or its renderer is removed. This improves failure behavior, but it also means the saved markup must be maintained as a meaningful fallback. Do not include a stale snapshot merely to avoid deciding what the block should do when unavailable.
Preview PHP output in the editor
The editor cannot execute PHP directly. The @wordpress/server-side-render package requests the block-renderer REST endpoint, whose route is /wp/v2/block-renderer/:block, and displays the registered callback or template output.
import ServerSideRender from '@wordpress/server-side-render';
import { useBlockProps } from '@wordpress/block-editor';
export default function Edit( { attributes } ) {
return (
<ServerSideRender
block="acme/latest-posts"
attributes={ attributes }
/>
);
}
Server-side rendering is useful for PHP-heavy blocks whose editor preview must match server output. The package documentation describes it as a fallback or legacy mechanism; for new experiences, prefer a REST endpoint designed for the block and client-side rendering where practical. That approach gives the editor an explicit data contract and avoids making every keystroke depend on a block-renderer request.
Build and package the block
- During development, use the scaffolded development script defined in the generated project so JavaScript and CSS changes are rebuilt while you work.
- Test the block in the editor, save a post, reload it, and view the published page. Check both an empty result and a populated result.
- Run
npm run buildbefore release. This creates optimized production assets from the source files. - Activate the plugin in a clean WordPress environment and verify that the registered block name, editor script, render file, and built paths all resolve.
Common failures and fixes
The block does not appear in the inserter
- Confirm the plugin is activated.
- Check that the name in
block.jsonuses thenamespace/slugformat and matches the name used by any server-side preview. - Make sure the built editor script exists at the path declared by
editorScript. - Re-run the production build after changing source files.
The editor reports a validation error
A validation warning usually means the saved HTML produced by save() differs from the HTML the editor now expects. For a block that is completely server rendered, return null instead of trying to maintain a generated snapshot. If the block intentionally saves fallback or static markup, update the save implementation and migrate existing content carefully.
The front end is blank
- Inspect the PHP error log for syntax errors or an undefined variable.
- Confirm the renderer is registered and the block name matches exactly.
- Check that the template is located where the
renderfield expects it. - Verify that a query is not returning an empty result and that the template handles that case.
- Ensure the plugin remains active on the site displaying the block.
Nested blocks disappear
Return <InnerBlocks.Content /> from save() and use the supplied $content in the PHP renderer. A parent that returns null without serializing inner blocks has no saved nested content to render.
Best Value
The editor preview differs from the published page
Check that both paths use the same attributes and wrapper logic. A ServerSideRender preview calls the renderer through the REST endpoint, while the published page calls it during normal front-end rendering. Authentication, current user context, query timing, and missing attributes can therefore produce different results. Give every attribute a default and keep the renderer deterministic for the same inputs.
Block-support classes are missing
Use useBlockProps() around the editor output and get_block_wrapper_attributes() around the server output. Hard-coding a wrapper class in only one location can make alignment, spacing, or other supports appear to work in the editor but not on the front end.
Performance, security, and maintenance decisions
Control server work
Dynamic rendering performs its query and markup generation during page rendering. Keep queries bounded, sanitize numeric limits with functions such as absint(), and avoid doing expensive work repeatedly when the same result can be cached at an application or page-cache layer. A dynamic block is not automatically slow, but its request-time work must be proportional to the value of fresh output.
Treat attributes as untrusted input
Editors can control attributes, and imported or manipulated post content can contain unexpected values. Validate ranges and types before using attributes in queries. Escape titles and other text with esc_html(), URLs with esc_url(), and generated HTML with an HTML-aware sanitizer such as wp_kses_post() when assembling a string.
Keep the contract backward-compatible
Existing posts retain the attributes that were saved when they were created. If an attribute is renamed or its type changes, provide a default and a migration strategy rather than assuming every old instance has the new value. A stable namespace and slug also protect existing content from accidental block identity changes.
A practical implementation checklist
- Scaffold with
npx @wordpress/create-block@latest ... --variant=dynamic. - Choose a permanent namespace and slug.
- Declare
apiVersion, scripts, attributes, and eitherrenderor PHP registration. - Give every attribute a type and safe default.
- Build the editor UI with
useBlockProps(). - Render current data in
render.phpor arender_callback. - Use
get_block_wrapper_attributes()for the front-end wrapper. - Escape each value for its output context.
- Return
nullfromsave()when no HTML snapshot is needed. - Save
InnerBlocks.Contentwhen nested content must survive. - Use server-side preview only when PHP output must be shown in the editor; consider a REST-backed client preview for new features.
- Run
npm run buildand test activation, editing, saving, publishing, empty results, and renderer failure behavior.
When this architecture is the right fit
Choose a dynamic block when the reader of the published page should see the latest server state, when a single markup change should update many existing instances, or when generating a reliable saved snapshot would create constant validation problems. Choose a static block when the content is editorially fixed, the output is inexpensive to store, and serving it without a PHP query is more important than request-time freshness.
The essential design is simple: let block.json define the data contract, let the editor collect that data, let PHP render the current result, and let save() preserve only what must be stored. That division keeps dynamic blocks fresh without sacrificing editor compatibility or safe output.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




