There are three ways to display a Core Forms form on the frontend: the shortcode, the Gutenberg block, and PHP functions.
Shortcode
Use the [cf_form] shortcode to embed a form anywhere shortcodes are supported (posts, pages, widgets, etc.).
By slug:
[cf_form slug="contact-form"]
By ID:
[cf_form id="123"]
The slug attribute looks up the form by its post slug. The id attribute looks up by post ID. If both are provided, slug takes priority.
If the form is not found, the shortcode outputs nothing (empty string). No error is shown on the frontend.
Filtering the Form Identifier
You can modify which form is loaded using the cf_shortcode_form_identifier filter. This is useful for A/B testing or serving different forms based on conditions:
add_filter( 'cf_shortcode_form_identifier', function( $identifier, $attributes ) {
if ( $identifier === 'contact' && wp_is_mobile() ) {
return 'contact-mobile';
}
return $identifier;
}, 10, 2 );
Gutenberg Block
In the block editor, search for “Core Forms” or find it in the block inserter. The block provides a dropdown to select from your existing forms.
The block stores either the form slug or ID as a block attribute and renders using the same callback as the shortcode.
Block markup:
<!-- wp:core-forms/form {"slug":"contact-form"} /-->
PHP Function
In theme templates or plugin code, use the cf_get_form() function to retrieve and render a form:
<?php
$form = cf_get_form( 'contact-form' ); // by slug
echo $form->get_html();
?>
Or by ID:
<?php
$form = cf_get_form( 123 ); // by post ID
echo $form; // Form objects can be cast to string
?>
The cf_get_form() function throws an Exception if the form is not found, so wrap it in a try/catch if needed:
<?php
try {
$form = cf_get_form( 'contact-form' );
echo $form;
} catch ( Exception $e ) {
// Form not found
}
?>
What Gets Rendered
When a form is displayed, Form::get_html() generates the full form markup:
- An opening
<form>tag with CSS classes (cf-form cf-form-{ID}), data attributes (messages, slug, title),novalidate, and anaria-labelset to the form title. - A nonce field (if nonce verification is enabled globally).
- A hidden field with the AJAX action name (
cf_form_submit). - A hidden field with the form ID (
_cf_form_id). - A hidden honeypot field for spam protection.
- A
.cf-messagescontainer for displaying success/error messages. - A
.cf-fields-wrapdiv containing your form markup. - A
<noscript>fallback telling users to enable JavaScript. - Optional
<style>and<script>blocks for custom CSS/JS.
The core-forms and core-forms-a11y JavaScript files are enqueued automatically when a form is rendered.
Stylesheet Loading
By default, the Core Forms stylesheet is only loaded when a form is present on the page. You can force the stylesheet to load on every page by enabling Load Stylesheet in Core Forms > Settings.
The stylesheet provides minimal styling for labels, inputs, and message containers. Most forms will use your theme’s styles.