Skip to main content
Documentation/Developers/Element Studio/HTML

HTML

The HTML tab holds your element's markup. It's a Twig
template, saved as html.twig next to element.php, and it renders on every page the
element appears on — in the builder canvas and on the front end alike.

What you write here is the inside of the element. Breakdance supplies the wrapper tag itself,
along with its class and any attributes, from the Settings and
HTML Attributes tabs. A template that starts with a <div> gets you
two nested divs.

Reading control values

Element Studio HTML tab with the escaped notice template and its live canvas output visible
Element Studio HTML tab with the escaped notice template and its live canvas output visible

Control values arrive as a Twig object shaped exactly like your control tree — tab, then
section, then control slug:

Twig
{{ content.content.text }}

That's Breakdance's Text Link element reading a control called text, in a section called
content, on the Content tab. Design-tab controls sit under design by the same rule:
design.spacing.margin_top.

Standard Twig applies, so escaping, defaults, filters and conditionals all work:

Twig
{{ content.content.text|default('Click Here') }}

{% if content.card.heading %}
  <h3 class="card__heading">{{ content.card.heading|escape }}</h3>
{% endif %}

{% for item in content.card.items %}
  <li>{{ item.label|escape }}</li>
{% endfor %}

Breakdance's Twig renderer disables automatic escaping. Use |escape for plain text and |escape('html_attr') for attribute values. Only output HTML directly when it is intended markup and has been sanitized for that context.

Placeholders

Alongside Twig, Breakdance substitutes a handful of %%NAME%% placeholders after the template
renders. They exist for the things Twig can't know:

124 — the current element's node ID.

256146 — the current post ID.

— where nested elements render. An element without this placeholder
has no place to output its children. Configure a container nesting rule as well; the placeholder alone does not change the nesting rules. A container template can consist of:

Twig

%%SSR%% — where the output of ssr.php goes. See below.

.bde-themeless-template-content-area-256146-124 — the CSS selector for this specific element instance. It's mainly a
CSS and Dependencies placeholder, used when a script needs to
target the one instance it belongs to.

%%BREAKPOINT%% — stands in for the active breakpoint inside a property path, so a
single path expression covers all of them. It appears in property paths rather than in
markup.

Server-side rendering with ssr.php

Twig alone can't call WordPress. When your element needs to run a query, call a plugin's
API, or process a shortcode, put that PHP in a file named ssr.php in the element's folder
and drop %%SSR%% into the template where its output belongs.

Breakdance's Shortcode element is the whole pattern in two files. html.twig:

Twig
%%SSR%%

ssr.php:

PHP
<?php
/**
 * @var array $propertiesData
 */

echo do_shortcode($propertiesData['content']['shortcode']['full_shortcode'] ?? '');

The file is included with output buffering on, so echo, don't return. $propertiesData
holds the same control values the Twig template sees, as a plain PHP array with the same
content / design → section → slug nesting. Guard every lookup with ?? — a control the
user hasn't touched isn't there.

Two things worth knowing about ssr.php:

  • It is not loaded with the rest of the element. Breakdance's element scan deliberately
    skips files named ssr.php and includes yours only at render time.
  • It runs in the builder too. Every keystroke in a control that the element re-renders
    on runs this code again, so keep it cheap — and tell Breakdance exactly which controls should
    trigger a re-render, on the Property Paths tab. An ssr.php doing
    real work with no re-render paths configured makes the builder feel broken.

Read Parent Properties in Server-Rendered Children

When the parent enables Share props with SSR children, a child's ssr.php can read its values through $parentPropertiesData:

PHP
$productId = $parentPropertiesData['content']['content']['product'] ?? null;

The built-in Product Cart Button reads parent data supplied by Product Builder this way. Use the parent's actual control paths, and guard values that may not be set.

Macros

When several elements need the same chunk of markup, move it into a
macro and call it from each template rather than copying it. Macros
are Twig macros, created from the studio's New macro entry, and they live in their own
saving location.

Keeping the markup simple

Two habits pay off:

Let Breakdance own the outer element. Your wrapper tag is configurable by the user through
the Settings tab's HTML Tag options — someone can make your card a <section> or an
<article> without touching code. Hard-coding a wrapper in the template takes that away.

Put classes in the template only for internal structure. The wrapper's class is
generated (.bde-shortcode, .autogenerated-ee-yourelement) and is what your
CSS tab targets through .bde-themeless-template-content-area-256146-124. Classes you write in the template are for
the parts inside — card__heading, card__meta — and they need matching rules in
Default CSS.