---
url: 'https://sithis.xyz/blog/der-formate-button-der-einfach-nicht-wollte'
title: 'Der Formate-Button, der einfach nicht wollte: Ein unsichtbarer CKEditor-5-Bug und wie du ihn jagst'
author:
  name: 'Joachim Namyslo'
  url: 'https://sithis.xyz/team/joachim'
  sameAs:
    - 'https://www.youtube.com/@jo_de'
    - 'https://github.com/nodedropweb'
    - 'https://www.drupal.org/u/Joachim-Namyslo'
date: '2026-09-06T18:52:35+00:00'
updated: '2026-09-23T20:23:50+00:00'
type: article
summary: 'CKEditor-5-Formate-Button bleibt grau? So findest du den unsichtbaren Style-Plugin-Bug mit blockquote – und fixt ihn mit einer Zeile.'
tags:
  - ckeditor
  - debugging
published: true
og:
  site_name: 'Drupal TV'
  updated_time: '2026-09-23T22:23:50+02:00'
---
# Der Formate-Button, der einfach nicht wollte: Ein unsichtbarer CKEditor-5-Bug und wie du ihn jagst

## Key Facts

- Das Problem: Ein CKEditor-5-"Formate"-Dropdown mit drei Callout-Styles (Update/Powertipp/Info) blieb dauerhaft grau und deaktiviert – egal, wo der Cursor stand.
- Die Falle: Jede Config-Prüfung sah perfekt aus. JSON-Settings korrekt, Dropdown-Einträge mit den richtigen Labels und Farben generiert. Trotzdem: nichts ging.
- Der eigentliche Bug: Die Styles zielten auf &lt;blockquote&gt; – aber CKEditor 5 kann Blockquote keine freie Klasse verpassen, weil das Element schon von einem eigenen Feature verwaltet wird.
- Der Fix: Ziel auf &lt;p&gt; umgestellt. Button war sofort klickbar, Dropdown zeigte die drei Farbkacheln mit Emoji-Label – fertig.
- Die Lehre: "Sieht in der Config richtig aus" ist keine Bestätigung. Öffne den echten Editor im Browser, bevor du eine Style-Konfiguration für fertig erklärst.

Kennst du das Gefühl? Du baust ein Feature, jede Zeile Config stimmt, du liest deinen eigenen JSON-Output dreimal gegen – und trotzdem tut die UI einfach nicht das, was sie soll. Kein Fehler in der Konsole. Keine rote Meldung. Nur ein Button, der stur grau bleibt.

Genau das ist mir heute beim Bau der Callout-Boxen für diese Seite passiert. Und weil der Bug am Ende so unauffällig war, dass ich ihn fast übersehen hätte, will ich dir zeigen, wie ich ihn gefunden habe – damit du nicht dieselbe Stunde verlierst, wenn du mal selbst CKEditor-5-Styles konfigurierst.

Kein Custom-Modul nötig, kein Theme-Umbau – wir bleiben die ganze Zeit auf Core-Bordmitteln. Wo genau du klickst, zeige ich dir unterwegs.

## Die Mission: Drei Callout-Boxen für den Editor

Die Idee war simpel: Redakteur:innen sollen einen Absatz markieren, im Editor auf "Formate" klicken und daraus eine farbige Hinweisbox machen – 🔔 Update, 💡 Powertipp oder ℹ️ Info. Ähnlich wie ein Toast in Bootstrap 5, nur direkt im CKEditor nutzbar.

Drupal bringt dafür das passende Werkzeug schon mit: das CKEditor-5-"Style"-Plugin. Das ist Core-Funktionalität, kein zusätzliches Modul – du musst nichts installieren, nur konfigurieren. Du definierst ein paar Styles in der Editor-Konfiguration, jeder bekommt ein Ziel-Element plus eine oder mehrere CSS-Klassen, und Drupal baut dir daraus automatisch das "Formate"-Dropdown.

> 📍 **Wo trägst du das ein?** Gehe zu *Konfiguration → Inhaltsbearbeitung → Text-Formate und -Editoren* (/admin/config/content/formats) und bearbeite das Textformat, das du erweitern willst (z. B. "Volles HTML" oder dein eigenes Redakteurs-Format). Ziehe im CKEditor-5-Toolbar-Baukasten den Button "Formate" in die aktive Toolbar. Darunter erscheint ein neuer Bereich "Formate" mit einer Liste, in der du pro Zeile ein Label und ein HTML-Element einträgst. Genau diese Liste – nicht eine separate YAML-Datei irgendwo im Dateisystem – ist die ckeditor5\_style-Config aus dem Beispiel unten. Wenn du lieber mit drush config:export / config:import arbeitest, landet sie in der editor.editor.&lt;formatname&gt;.yml deiner Config-Sync-Verzeichnisses; für den Einstieg reicht aber das Formular völlig.

Also los: Drei Styles definiert, jeweils gemappt auf ein **blockquote** mit eigener Klasse. So sieht das im Hintergrund als YAML aus (du tippst nichts davon direkt – das UI-Formular erzeugt es für dich):

```yml
ckeditor5_style:
  styles:
    - label: Update
      element: '<blockquote class="callout callout--update">'
    - label: Powertipp
      element: '<blockquote class="callout callout--tip">'
    - label: Info
      element: '<blockquote class="callout callout--info">'
```

ckeditor5\_style: styles: - label: Update element: '&lt;blockquote class="callout callout--update"&gt;' - label: Powertipp element: '&lt;blockquote class="callout callout--tip"&gt;' - label: Info element: '&lt;blockquote class="callout callout--info"&gt;'

Dazu noch **filter\_html** erweitert, damit die drei Klassen auf blockquote überhaupt erlaubt sind. Auch das ist kein separater Schritt an anderer Stelle: Im selben Bearbeitungsformular für das Textformat findest du weiter unten das Feld "Zulässige HTML-Tags". Dort ergänzt du blockquote um die erlaubten Klassen, etwa so: &lt;blockquote class="callout callout--update callout--tip callout--info"&gt;.

Und noch ein Stück fehlte: das CSS für Farbe und Emoji-Label. Das gehört nicht ins Textformat, sondern in dein Theme (oder ein kleines Custom-Modul, falls du es nicht ans Theme koppeln willst). Konkret: eine .css-Datei mit den Regeln für .callout, .callout--update usw., eingebunden über die \*.libraries.yml deines Themes und dort per libraries: in der \*.info.yml angehängt – der ganz normale Weg, wie du überhaupt CSS in Drupal lädst. Sah in jeder Config-Ansicht wasserdicht aus.

## Der Endgegner: Ein Button, der nichts tut

Cache geleert, Editor neu geladen – und dann: nichts. Der "Formate"-Button in der Toolbar stand einfach nur grau da. Kein Klick, kein Dropdown, keine Reaktion. Egal, ob der Cursor im Text stand oder nicht.

Das Tückische daran: Es gab absolut keinen Hinweis darauf, *warum*. Kein Fehler in der Browser-Konsole. Die generierten JavaScript-Settings für den Editor zeigten exakt das, was ich erwartet hatte – die drei Styles, korrekt benannt, mit den richtigen Farben. Wenn du nur auf die Konfiguration schaust, würdest du schwören: Das muss funktionieren.

Hier ist der Punkt, an dem viele aufgeben und anfangen, wahllos an der Config herumzuschrauben. Stattdessen bin ich einen Schritt zurückgegangen und habe mir den Button selbst angeschaut – nicht die Config, sondern das tatsächliche DOM-Element im Browser. Dafür öffnest du die Entwicklertools deines Browsers (Rechtsklick → "Untersuchen" oder F12) und tippst im Tab "Konsole" folgenden Befehl ein – klingt nach Hexerei, ist aber nur eine Frage an die Seite, die sie dir direkt beantwortet:

```javascript
document.querySelectorAll('button')
  .find(b => b.textContent.trim() === 'Stile')
  .getAttribute('aria-disabled');
// → "true"
```

document.querySelectorAll('button') .find(b =&gt; b.textContent.trim() === 'Stile') .getAttribute('aria-disabled'); // → "true"

Da war er, der eigentliche Zustand: **aria-disabled="true"**. Fest verdrahtet, unabhängig von Cursorposition oder Auswahl. Der Button war nicht kaputt – er war *absichtlich* deaktiviert. Nur eben von CKEditor 5 selbst, aus einem Grund, den keine Config-Datei verraten hätte.

## Die Auflösung: Blockquote ist schon vergeben

CKEditor 5 aktiviert den "Formate"-Button nur, wenn mindestens einer der konfigurierten Styles auf das aktuelle Element angewendet werden *kann*. Und genau hier lag der Haken: blockquote wird bereits von einem eigenen, fest eingebauten Feature verwaltet – dem BlockQuote-Feature, das für den normalen "Zitat"-Button in der Toolbar zuständig ist.

Dieses Feature kennt zwar blockquote, aber es ist nicht darauf ausgelegt, dass ihm ein anderes Plugin einfach beliebige CSS-Klassen unterschiebt. Das Style-Plugin und das BlockQuote-Feature reden schlicht nicht dieselbe Sprache – und weil keins von beiden das als Fehler behandelt, bleibt der Button einfach für immer deaktiviert. Kein Absturz, keine Warnung. Er tut einfach: nichts.

Der Fix war am Ende eine einzige Änderung: statt blockquote als Ziel-Element &lt;p&gt; verwenden. Zurück im selben Formular unter *Konfiguration → Text-Formate und -Editoren* → dein Format → Bereich "Formate" – dort trägst du die drei Zeilen einfach um:

```yml
ckeditor5_style:
  styles:
    - label: Update
      element: '<p class="callout callout--update">'
    - label: Powertipp
      element: '<p class="callout callout--tip">'
    - label: Info
      element: '<p class="callout callout--info">'
```

ckeditor5\_style: styles: - label: Update element: '&lt;p class="callout callout--update"&gt;' - label: Powertipp element: '&lt;p class="callout callout--tip"&gt;' - label: Info element: '&lt;p class="callout callout--info"&gt;'

Warum &lt;p&gt;? Weil das Textformat hier schon lange bewiesen hat, dass Klassen-basiertes Styling auf &lt;p&gt; zuverlässig funktioniert – die Textausrichtung (linksbündig, zentriert, …) läuft über exakt denselben Mechanismus. Nach der Umstellung: Button sofort klickbar, Dropdown zeigt alle drei Styles mit Farbvorschau und Emoji-Label, Klick verwandelt den Absatz tatsächlich in die farbige Box.

## Warum eigentlich kein &lt;div&gt;? Die vollständige Liste

Naheliegende Frage, die ich mir selbst gestellt habe: Wenn blockquote schon Ärger macht, warum dann nicht einfach ein neutrales &lt;div class="callout"&gt; nehmen, ganz ohne konkurrierendes Feature?

Um das sauber zu beantworten, bin ich eine Ebene tiefer gegangen, als die Config normalerweise verlangt: direkt in den JavaScript-Quellcode, den Drupal-Core für das Style-Plugin mitliefert (core/assets/vendor/ckeditor5/style/style.js – minifiziert, aber lesbar). Dort steckt die eigentliche Logik, und sie beantwortet die Frage eindeutig.

CKEditor 5 unterscheidet für jedes Style-Ziel-Element drei Situationen:

1. **Kein eigenes Feature, direkt von General HTML Support (GHS) verstanden.** &lt;p&gt; und die Überschriften h1–h6 fallen darunter – GHS behandelt sie als sein eingebautes "paragraphartiges" Standardelement. Kein Konflikt möglich, weil niemand sonst Anspruch auf den Tag erhebt.
2. **Eigenes Feature, aber mit eingebauter Brücke zum Style-Plugin.** Listen, Tabellen und Links werden zwar von eigenen, spezialisierten Features verwaltet (List, Table, Link) – aber CKEditor 5 liefert dafür extra Kompatibilitäts-Plugins mit: ListStyleSupport, TableStyleSupport, LinkStyleSupport. Die verbinden das jeweilige Feature explizit mit dem Style-Plugin. Ich habe das für &lt;li&gt; selbst nachgestellt (Style nur auf &lt;li class="test-li"&gt; konfiguriert, Absatz per Toolbar in eine Liste verwandelt): Button sofort aktiv, keine Spur des Problems von vorhin.
3. **Eigenes Feature, aber keine Brücke.** Genau das ist der Fall bei blockquote. Das BlockQuote-Feature verwaltet den Tag exklusiv, aber es existiert kein BlockQuoteStyleSupport – anders als bei Listen, Tabellen und Links hat hier schlicht niemand die Brücke gebaut. Ergebnis: für immer deaktiviert, ohne jede Fehlermeldung.

Und &lt;div&gt;? Der landet in einer vierten, eigentlich noch einfacheren Kategorie: Es ist gar kein Tag, das dieses Textformat überhaupt erlaubt. General HTML Support kennt für diesen Editor nur die Elemente, die filter\_html freigibt – &lt;div&gt; steht da nicht drin. Der Style-Eintrag findet dadurch weder ein Block- noch ein Inline-Ziel und bleibt komplett wirkungslos, noch bevor die Frage "eigenes Feature ja/nein" überhaupt eine Rolle spielt.

Die gute Nachricht: Genau deshalb ist &lt;div&gt; kein Sackgassen-Fall. Wenn du unbedingt einen neutralen Container brauchst, kannst du ihn explizit erlauben – auch das läuft wieder über dasselbe Textformat-Formular, diesmal über den CKEditor-5-Toolbar-Baustein "Source Editing" (im Toolbar-Baukasten als eigener Button verfügbar, klingt martialischer als er ist: er schaltet nur zusätzliche HTML-Tags für General HTML Support frei). Ist der Tag einmal darüber erlaubt, kennt GHS ihn, niemand sonst beansprucht ihn – und er verhält sich wie &lt;p&gt;: Kategorie 1, keine Brücke nötig.

> 📍 **Kurz zusammengefasst, wo was hingehört:**
> 
> - **Style-Definitionen** (welches Element, welche Klasse, welches Label) → Textformat bearbeiten → Toolbar-Baustein "Formate" aktivieren → Formular-Liste ausfüllen.
> - **Erlaubte HTML-Tags/-Klassen** → dasselbe Formular → Feld "Zulässige HTML-Tags".
> - **Zusätzliche Tags wie &lt;div&gt; erlauben** → Toolbar-Baustein "Source Editing" aktivieren, dann im selben Feld ergänzen.
> - **Das CSS für Farben/Emojis** → Theme-Library (\*.libraries.yml + CSS-Datei) oder ein Custom-Modul mit eigener Library – kein Bestandteil des Textformats.
> - Ein eigenes Modul brauchst du für nichts davon. Alles läuft über Core-Bordmittel.

Hier die Liste als Tabelle, mit allem, was ich direkt bestätigen konnte (live getestet oder im Core-Quellcode mit Namen gefunden) und allem, was sich logisch aus derselben Mechanik ergibt:

| Element | Funktioniert mit Style? | Warum |
|---|---|---|
| &lt;p&gt; | Ja (live bestätigt) | Kein eigenes Feature, GHS-Standardelement |
| &lt;h1&gt;–&lt;h6&gt; | Ja | Gleiche GHS-Mechanik wie &lt;p&gt; |
| &lt;li&gt; | Ja (live bestätigt) | Eigenes List-Feature, aber ListStyleSupport-Brücke |
| &lt;ul&gt;, &lt;ol&gt; | Ja | Gleiche ListStyleSupport-Brücke |
| &lt;td&gt;, &lt;th&gt; | Ja | Eigenes Table-Feature, aber TableStyleSupport-Brücke |
| &lt;thead&gt;, &lt;tbody&gt; | Ja | Gleiche TableStyleSupport-Brücke |
| &lt;a&gt; | Ja (als Inline-Style) | Eigenes Link-Feature, aber LinkStyleSupport-Brücke |
| &lt;blockquote&gt; | Nein (live bestätigt) | Eigenes BlockQuote-Feature, keine Brücke vorhanden |
| &lt;hr&gt;, &lt;br&gt;, &lt;img&gt;, drupal-media | Nein | Von Drupal-Core offiziell als "bekannt inkompatibel" dokumentiert, inkl. Verweis auf offene Upstream-Issues |
| &lt;div&gt;, &lt;span&gt;, &lt;article&gt;, &lt;section&gt;, &lt;figure&gt; | Nein – aber nachrüstbar | Vom Textformat gar nicht erlaubt; GHS kennt den Tag nicht. Über "Source Editing" freischalten, dann wie &lt;p&gt; nutzbar |

Zeilen ohne "live bestätigt" habe ich nicht selbst durchgeklickt, sondern aus derselben, im Quellcode klar benannten Mechanik abgeleitet (Plugin-Namen wie ListStyleSupport oder TableStyleSupport sind kein Rateergebnis, die stehen wortwörtlich so im Code). Bei &lt;hr&gt;, &lt;br&gt;, &lt;img&gt; und drupal-media ist es noch eindeutiger: Die stehen in einer festen Liste namens KNOWN\_UNSUPPORTED\_TAGS direkt im Drupal-Core-Code, mit Kommentaren, die auf die jeweiligen offenen Tickets verweisen.

## Die größere Lehre

Eine Konfiguration, die auf dem Papier – oder im JSON-Export – korrekt aussieht, ist noch keine funktionierende Konfiguration. Öffne den echten Editor, bevor du einen Haken dran machst. Manche Bugs verstecken sich nicht im Code, sondern genau in der Lücke zwischen "sieht richtig aus" und "tut auch, was es soll". Und wenn du wirklich wissen willst, warum etwas nicht geht: Config-Ebene ist oft nur die halbe Wahrheit – die andere Hälfte steckt manchmal im JavaScript, das der Browser tatsächlich ausführt.



Weiterführende Links

[CKEditor 5 Style-Feature (offizielle Doku)](https://ckeditor.com/docs/ckeditor5/latest/features/style.html)

[CKEditor 5 General HTML Support (offizielle Doku)](https://ckeditor.com/docs/ckeditor5/latest/features/html/general-html-support.html)

[Drupal.org: CKEditor 5-Modul](https://www.drupal.org/project/ckeditor5)

[MDN: aria-disabled](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-disabled)