Good to hear that you managed to solve the problem already. Here’s a few examples on how you could also return html from a shortcode.
As you already found out, you can use ob_start()
and ob_get_clean()
to buffer the html. Inside it you can echo the markup or drop out of PHP and write plain HTML.
function my_shortcode() {
ob_start();
echo '<div>some HTML here</div>';
?>
<p>Or outside of the PHP tags</p>
<?php
return ob_get_clean();
}
If the shortcode is within a theme, then you could also use get_template_part()
with the output buffering. This way you can make the shortcode callback a little cleaner looking as the HTML will find its home in a separate file. You can also pass data to the template part, if needed.
function my_shortcode() {
$template_part_args = array(
'key' => 'value',
);
ob_start();
get_template_part(
'path/to/template/part',
'optional-name', // use null, if not named
$template_part_args // access with $args in the template part file
);
return ob_get_clean();
}
As Rup noted in the comments, one option is to concatenate the html to a string variable and then return that.
function my_shortcode() {
$output="<div>";
$output .= 'Some HTML here';
$output .= '</div>';
return $output;
}
Personally, I like to use sprintf()
for returning in a similar situation. I think it makes the code clean looking and makes adding escaping a breeze.
function my_shortcode() {
return sprintf(
'<div>
<p>%s</p>
<div>%s</div>
</div>',
esc_html('Some HTML here'),
esc_html('Additional nested HTML')
);
}
Especially with lists, I tend to build an array of the list items, which are imploded into a string. But you can use the same idea to push various HTML strings into an array, which is turned into one string on output return.
function my_shortcode() {
$list_items = array();
foreach ($some_array as $value) {
$list_items[] = sprintf(
'<li>%s</li>',
esc_html($value)
);
}
return '<ul>' . implode('', $list_items) . '</ul>';
}