Ein <strong> in der Akkordeon-Überschrift, ein kleines Icon vor dem Titel – und Contao macht daraus sichtbaren Quelltext statt Formatierung. Kein Fehler, sondern Absicht: Contao 5.3 escaped den Header-Inhalt aus Sicherheitsgründen und bereinigt HTML schon beim Speichern.

Trotzdem gibt es gute Gründe für Inline-Markup im Titel – visuelle Akzente, semantische Hervorhebungen, barrierearme Icon-Darstellung. Der folgende Ansatz zeigt, wie sich das Accordion-Template gezielt überschreiben und das DCA-Feld so konfigurieren lässt, dass HTML gespeichert und unverändert ausgegeben wird – ohne die Struktur des Elements anzutasten.

Den Anfang macht ein Twig-Template-Override. Der Speicherort folgt der Contao-Konvention: templates/content_element/accordion.html.twig im Projektverzeichnis. Als Basis dient das Originaltemplate aus Contao 5.3.11 – verändert wird genau eine Stelle, aber die entscheidet: Der Header-Inhalt wird nicht mehr escaped, sondern mit dem Twig-Filter raw ausgegeben. Alles Übrige – die handorgel-Klassen, die Attribute, die Button-Ebene – bleibt unangetastet, damit das vorhandene JavaScript-Verhalten weiter funktioniert.

Code für templates/content_element/accordion.html.twig:

{% extends "@Contao/content_element/accordion.html.twig" %}

{% block element_header %}
    {% set accordion_header_attributes = attrs()
        .addClass('handorgel__header')
        .mergeWith(accordion_header_attributes|default)
    %}
    <{{ element.header_tag }}{{ accordion_header_attributes }}>
        {% set accordion_header_button_attributes = attrs()
            .addClass('handorgel__header__button')
            .set('type', 'button')
            .mergeWith(accordion_header_button_attributes|default)
        %}
        <button{{ accordion_header_button_attributes }}>
            {{- element.header|raw -}}
        </button>
    </{{ element.header_tag }}>
{% endblock %}

Die einzige inhaltliche Änderung liegt in der Zeile mit {{- element.header|raw -}}. Während Contao im Standard den Header-Text escaped ausgibt, sorgt raw dafür, dass HTML-Inhalte direkt gerendert werden. Um zu vermeiden, dass Redakteursinhalte beim Speichern in der Datenbank bereinigt oder herausgefiltert werden, ist zusätzlich eine DCA-Anpassung notwendig. Dazu wird im Projekt eine Datei unter contao/dca/tl_content.php angelegt oder entsprechend erweitert. Es genügt, die Evaluation des Feldes sectionHeadline so zu konfigurieren, dass HTML erlaubt ist. Das Feld steuert die Überschrift des Accordion-Elements; mit allowHtml = true bleibt das eingegebene Inline-Markup erhalten.

Code für contao/dca/tl_content.php:

<?php
// contao/dca/tl_content.php
$GLOBALS['TL_DCA']['tl_content']['fields']['sectionHeadline']['eval']['allowHtml'] = true;

Nach dem Anlegen der beiden Dateien empfiehlt sich das Leeren des Symfony Cache, damit sowohl das Template-Override als auch die DCA-Anpassung aktiv werden. Anschließend lässt sich in einem Accordion-Content-Element in der Überschrift beispielsweise ein Icon-Span oder eine Hervorhebung unterbringen, ohne die Button-Struktur zu verletzen.

Wichtig ist, in den Überschriften nur Inline-Elemente zu nutzen und Block-Elemente wie div zu vermeiden, da der Inhalt innerhalb eines Button-Elements liegt. Inline-Markup wie span, em, strong oder sup/sub ist unkritisch; auf semantisch sinnvolle Verwendung und das Vermeiden unnötiger Verschachtelungen sollte geachtet werden.

Sollte das HTML trotz der Änderungen weiterhin escaped erscheinen, ist zu prüfen, ob das eigene Template tatsächlich greift. Der Dateipfad muss exakt stimmen (templates/content_element/accordion.html.twig), Caches müssen geleert werden und ggf. ist im Backend zu kontrollieren, ob ein anderes Template erzwungen wird.

Mit dieser minimalinvasiven Kombination aus Template-Override und DCA-Konfiguration wird HTML in Accordion-Überschriften unter Contao 5.3 zuverlässig ermöglicht – updatefreundlich, kompatibel zur bestehenden handorgel-Integration und flexibel genug, um gängige Inline-Auszeichnungen und Icon-Markup ohne zusätzliche Erweiterungen zu unterstützen.

Update 2026: HTML erlauben – aber kontrolliert

Update 2026: HTML in Überschriften zuzulassen, löst ein gestalterisches Problem – und öffnet gleichzeitig ein Sicherheitsfenster. Wer die Freigabe erteilt, sollte wissen, was er erlaubt.

Kurz gesagt: Contao filtert Eingaben bewusst. Erlaubt man beliebiges HTML in Überschriften, kann ein Redakteur mit Backend-Zugang – oder jemand, der einen Zugang übernommen hat – Skripte einschleusen. Die Lösung besteht deshalb nicht darin, den Filter abzuschalten, sondern ihn gezielt zu erweitern.

Gezielt erlauben statt pauschal freigeben

// config/config.yaml – nur harmlose Auszeichnungen zulassen
contao:
  sanitizer:
    allowed_url_protocols: [http, https, mailto, tel]

// contao/dca/tl_content.php – Feld gezielt öffnen
$GLOBALS['TL_DCA']['tl_content']['fields']['sectionHeadline']['eval']['allowHtml'] = true;
$GLOBALS['TL_DCA']['tl_content']['fields']['sectionHeadline']['eval']['decodeEntities'] = true;

// Und danach beim Speichern konsequent bereinigen:
$GLOBALS['TL_DCA']['tl_content']['fields']['sectionHeadline']['save_callback'][] =
    static function ($value) {
        return strip_tags((string) $value, '<strong><em><br><span><sup><sub>');
    };

Der save_callback ist der eigentliche Schutz: Er entscheidet, welche Tags überleben – <strong>, <em>, ein Zeilenumbruch, vielleicht ein <span> für eine Hervorhebung. Alles andere, insbesondere <script>, <iframe> und Event-Attribute wie onclick, fliegt raus, bevor der Wert in der Datenbank landet.

Die elegantere Alternative: gar kein HTML

In vielen Fällen geht es gar nicht um HTML, sondern um ein hervorgehobenes Wort. Das lässt sich ohne jedes Sicherheitsrisiko lösen – mit einem Trennzeichen, das im Template ausgewertet wird:

{# Redaktion schreibt: „Unsere |Stärke| im Detail“ #}
{% set teile = element.sectionHeadline|split('|') %}
<h3>
  {% for teil in teile %}
    {% if loop.index is odd %}{{ teil }}{% else %}<em>{{ teil }}</em>{% endif %}
  {% endfor %}
</h3>

Die Redaktion tippt Text, das Template erzeugt das Markup – kein Weg für Skripte, keine kaputten Tags, kein Sanitizer nötig. Und die Barrierefreiheit dankt es ohnehin: Eine Überschrift, die halb aus Auszeichnung besteht, liest sich für Screenreader selten so, wie es gemeint war.

Zurück zur Blog-Übersicht