If you’re building with Elementor, sometimes the default widgets don’t have quite enough flexibility. For example, the Heading widget only provides a single text field.
But what if you want a subheading directly beneath it — without creating a new custom widget from scratch?
The good news: Elementor is extremely extensible, and you can inject new fields into existing widgets using action hooks. This means:
- No editing of Elementor core files.
- Changes survive plugin updates.
- Works on any site where Elementor is active.
In this tutorial, you’ll learn how to add a Subheading field to the Elementor Heading widget and render it on the frontend — all with a few lines of PHP.
Add the Subheading Control via Hook
Elementor provides the elementor/element/{widget_name}/{section_id}/before_section_end
action hook, which runs before a control section closes.
For the Heading widget:
widget_name
=heading
section_id
=section_title
Add this snippet to your theme’s functions.php
or a custom plugin:
add_action( 'elementor/element/heading/section_title/before_section_end', function( $element, $args ) {
$element->add_control(
'subheading',
[
'label' => __( 'Subheading', 'plugin-name' ),
'type' => \Elementor\Controls_Manager::TEXT,
'placeholder' => __( 'Enter your subheading', 'plugin-name' ),
'default' => '',
]
);
$element->add_control(
'subheading_color',
[
'label' => __( 'Subheading Color', 'plugin-name' ),
'type' => \Elementor\Controls_Manager::COLOR,
'selectors' => [
'{{WRAPPER}} .elementor-subheading' => 'color: {{VALUE}};',
],
]
);
}, 10, 2 );
What this does:
- Injects a Subheading text field into the Heading widget’s “Title” section.
- Adds a color picker so the subheading can be styled independently.
Render the Subheading in the Frontend
Adding the field to the panel is only half the job.
We also need to tell Elementor how to output it on the page.
We can use the elementor/widget/render_content
filter for this:
add_filter( 'elementor/widget/render_content', function( $content, $widget ) {
// Only target the Heading widget
if ( 'heading' === $widget->get_name() ) {
$settings = $widget->get_settings_for_display();
if ( ! empty( $settings['subheading'] ) ) {
$subheading_html = '<h4 class="elementor-subheading">' . esc_html( $settings['subheading'] ) . '</h4>';
$content .= $subheading_html;
}
}
return $content;
}, 10, 2 );
How it works:
- Checks if the current widget being rendered is the Heading widget.
- If a subheading value is set, appends it below the original heading HTML.
- Adds a
.elementor-subheading
class for easy styling.
Style the Subheading (Optional)
Since we’ve already added a color picker, users can choose colors directly in Elementor.
But you can also add your own CSS:
.elementor-subheading {
font-size: 1.2rem;
font-weight: 400;
margin-top: 5px;
}
Test It in Elementor
- Edit any page with Elementor.
- Add or edit a Heading widget.
- Scroll to the “Title” section — you’ll see a Subheading field.
- Enter text and optionally pick a color.
- Save and preview — your subheading should appear right below the heading.
Why This Method Is Better Than Editing Core Widgets
- Update-safe — no changes to Elementor’s core files.
- Reusable — you can inject controls into any widget.
- Lightweight — no need to create a duplicate widget.