In der nicht allzu fernen Vergangenheit erforderten selbst einfache, Akkordeon-ähnliche Interaktionen JavaScript-Event-Listener oder einige CSS-Tricks. Und je nach verwendeter Lösung konnte die Bearbeitung des zugrunde liegenden HTML kompliziert werden.
Nun, die Elemente <details> und <summary> (die zusammen als ein „Disclosure Widget“ bezeichnet werden) haben die Erstellung und Wartung dieser Komponenten relativ trivial gemacht.
Bei meiner Arbeit verwenden wir sie für Dinge wie häufig gestellte Fragen.

Es gibt ein paar zu berücksichtigende Probleme
Da die Ein- und Ausklapp-Interaktivität bereits in den HTML-Tags <details> und <summary> integriert ist, können Sie jetzt Disclosure Widgets ohne *jegliches* JavaScript oder CSS erstellen. Aber Sie möchten vielleicht trotzdem etwas. Ungestaltet lassen <details> Disclosure Widgets uns mit zwei Problemen zurück.
Problem 1: Der <summary>-Cursor
Obwohl der Abschnitt <summary> zur Interaktion einlädt, ist der Standardcursor des Elements ein Textauswahl-Icon und nicht der Zeigefinger, den man vielleicht erwartet

Problem 2: Verschachtelte Blockelemente in <summary>
Das Verschachteln eines Block-Level-Elements (z. B. einer Überschrift) innerhalb eines <summary>-Elements verschiebt diesen Inhalt unterhalb des Pfeilmarkers, anstatt ihn inline zu halten

Die CSS-Reset-Korrektur
Um diese Probleme zu beheben, können wir die folgenden beiden Stile zum Reset-Abschnitt unserer Stylesheets hinzufügen
details summary {
cursor: pointer;
}
details summary > * {
display: inline;
}
Lesen Sie weiter für mehr über jedes Problem und seine jeweilige Lösung.
Ändern des <summary>-Cursorwerts
Wenn Benutzer mit der Maus über ein Element auf einer Seite fahren, möchten wir, dass sie immer einen Cursor sehen, „der die erwartete Benutzerinteraktion mit diesem Element widerspiegelt.“
Wir haben kurz darauf hingewiesen, dass, obwohl <summary>-Elemente interaktiv sind (wie ein Link oder ein Formular-Button), ihr Standard-Cursor nicht der Zeigefinger ist, den wir normalerweise für solche Elemente sehen. Stattdessen erhalten wir den text-Cursor, den wir normalerweise erwarten, wenn wir Text auf einer Seite eingeben oder auswählen.
Um dies zu beheben, ändern Sie den Cursorwert auf pointer
details summary {
cursor: pointer;
}
Einige bemerkenswerte Websites beinhalten diese Eigenschaft bereits, wenn sie <details>-Elemente gestalten. Die MDN Web Docs-Seite über das Element selbst tut genau das. GitHub verwendet ebenfalls Disclosure Widgets für bestimmte Elemente, wie z. B. die Aktionen zum Beobachten, Sternen und Forken eines Repos.

cursor: pointer für das <summary>-Element seiner Disclosure-Widget-Menüs.Ich vermute, der Standardwert cursor: text wurde gewählt, um anzuzeigen, dass der Summary-Text (zusammen mit dem Rest des Inhalts eines Disclosure Widgets) vom Benutzer ausgewählt werden kann. Aber in den meisten Fällen halte ich es für wichtiger anzuzeigen, dass das <summary>-Element interaktiv ist.
Summary-Text *ist* weiterhin auswählbar, auch nachdem wir den Cursorwert von text auf pointer geändert haben. Beachten Sie, dass die Änderung des Cursors nur das Erscheinungsbild und nicht die Funktionalität beeinflusst.
Verschachtelte <summary>-Inhalte inline anzeigen
Innerhalb jedes <summary>-Abschnitts der zuvor gezeigten FAQ-Einträge umschließe ich die Frage normalerweise in einem geeigneten Überschriften-Tag (abhängig von der Seitenstruktur)
<details>
<summary>
<h3>Will my child's 504 Plan be implemented?</h3>
</summary>
<p>Yes. Similar to the Spring, case managers will reach out to students.</p>
</details>
Das Verschachteln einer Überschrift in <summary> kann aus mehreren Gründen hilfreich sein
- Konsistente visuelle Gestaltung. Ich mag es, wenn meine FAQ-Fragen wie andere Überschriften auf meinen Seiten aussehen.
- Die Verwendung von Überschriften hält die Seitenstruktur für Benutzer von Internet Explorer und älteren Chromium-Versionen von Edge gültig, die
<details>-Elemente nicht unterstützen. (In diesen Browsern ist ein solcher Inhalt immer sichtbar und nicht interaktiv.) - Korrekte Überschriften können Benutzern von assistiven Technologien helfen, sich innerhalb von Seiten zu navigieren. (Das gesagt, Überschriften innerhalb von
<summary>-Elementen stellen einen besonderen Fall dar, wie unten detailliert erklärt wird. Einige Screenreader interpretieren diese Überschriften als das, was sie sind, andere nicht.)
Überschriften vs. Buttons
Beachten Sie, dass das <summary>-Element ein wenig ungewöhnlich ist. Es verhält sich in vielerlei Hinsicht wie ein Button. Tatsächlich hat es sogar eine implizite ARIA-Zuordnung von role=button. Aber ganz anders als bei Buttons dürfen Überschriften direkt in <summary>-Elemente verschachtelt werden.
Das stellt uns – und Browser- und Assistive-Technology-Entwicklern – vor einen Widerspruch
- Überschriften sind in
<summary>-Elementen erlaubt, um Navigationshilfen auf der Seite bereitzustellen. - Buttons entfernen die Semantik aus allem (wie Überschriften), was in ihnen verschachtelt ist.
Leider sind assistive Technologien inkonsistent darin, wie sie diese Situation gehandhabt haben. Einige Screenreader-Technologien, wie NVDA und Apples VoiceOver, erkennen Überschriften in <summary>-Elementen an. JAWS hingegen nicht.
Das bedeutet für uns, dass wir beim Platzieren einer Überschrift in <summary> das Aussehen der Überschrift gestalten *können*. **Aber wir können nicht garantieren, dass unsere Überschrift tatsächlich als Überschrift interpretiert wird!**
Mit anderen Worten, es schadet wahrscheinlich nicht, dort eine Überschrift zu platzieren. Sie mag nur nicht immer helfen.
Alles inline machen
Wenn wir einen Überschriften-Tag (oder ein anderes Block-Element) direkt in unser <summary> einfügen, wollen wir wahrscheinlich dessen display-Stil auf inline ändern. Andernfalls erhalten wir unerwünschte Umbrüche, wie z. B. das Ein-/Ausklapp-Pfeilsymbol, das über der Überschrift anstatt daneben angezeigt wird.
Wir können die folgende CSS verwenden, um einen display-Wert von inline auf jede Überschrift und jedes andere Element anzuwenden, das direkt in <summary> verschachtelt ist.
details summary > * {
display: inline;
}
Ein paar Hinweise zu dieser Technik. Erstens empfehle ich die Verwendung von inline und nicht inline-block, da das Problem mit dem Zeilenumbruch auch bei inline-block auftritt, wenn der Überschriftentext über eine Zeile hinausgeht.
Zweitens, anstatt den display-Wert der verschachtelten Elemente zu ändern, sind Sie vielleicht versucht, den Standardwert display: list-item des <summary>-Elements durch display: flex zu ersetzen. Zumindest ich war es! Wenn wir dies jedoch tun, verschwindet der Pfeilmarker. Hoppla!
Bonus-Tipp: Internet Explorer von Ihren Stilen ausschließen
Ich habe bereits erwähnt, dass Internet Explorer und ältere Chromium-Versionen (auch EdgeHTML genannt) von Edge <details>-Elemente nicht unterstützen. Wenn wir also keine Polyfills für diese Browser verwenden, möchten wir vielleicht sicherstellen, dass unsere benutzerdefinierten Disclosure-Widget-Stile für sie nicht angewendet werden. Andernfalls landen wir in einer Situation, in der unser gesamtes Inline-Styling das Element durcheinanderbringt.

<summary>-Überschriften könnten in Internet Explorer und EdgeHTML ungewöhnliche oder unerwünschte Effekte haben.Außerdem ist das <summary>-Element in diesem Fall nicht mehr interaktiv, was bedeutet, dass der Standardstil text des Cursors besser geeignet ist als pointer.
Wenn wir entscheiden, dass unsere Reset-Stile nur für die entsprechenden Browser gelten sollen, können wir eine Feature-Abfrage hinzufügen, die verhindert, dass IE und EdgeHTML jemals unsere Stile angewendet bekommen. Hier ist, wie wir das mit @supports machen, um eine Funktion zu erkennen, die nur diese Browser unterstützen.
@supports not (-ms-ime-align: auto) {
details summary {
cursor: pointer;
}
details summary > * {
display: inline;
}
/* Plus any other <details>/<summary> styles you want IE to ignore.
}
IE unterstützt Feature-Abfragen tatsächlich überhaupt nicht, daher wird alles im obigen Block ignoriert, was in Ordnung ist! EdgeHTML unterstützt Feature-Abfragen, aber es wird auch nichts innerhalb des Blocks angewendet, da es die einzige Browser-Engine ist, die -ms-ime-align unterstützt.
Die Hauptnebenwirkung hier ist, dass es auch einige ältere Versionen von Chrome (nämlich 12-27) und Safari (macOS- und iOS-Versionen 6-8) gibt, die <details> unterstützen, aber keine Feature-Abfragen unterstützen. Die Verwendung einer Feature-Abfrage bedeutet, dass diese Browser, die etwa 0,06 % der weltweiten Nutzung (Stand Januar 2021) ausmachen, unsere benutzerdefinierten Disclosure-Widget-Stile ebenfalls nicht anwenden.
Die Verwendung eines @supports selector(details)-Blocks anstelle von @supports not (-ms-ime-align: auto) wäre eine ideale Lösung. Aber Selector-Abfragen haben sogar noch weniger Browser-Unterstützung als Property-basierte Feature-Abfragen.
Abschließende Gedanken
Sobald wir unsere HTML-Struktur eingerichtet und unsere beiden CSS-Reset-Stile hinzugefügt haben, können wir all unsere Disclosure Widgets beliebig verschönern. Schon einfache Rand- und Hintergrundfarbstile können für Ästhetik und Benutzerfreundlichkeit viel bewirken. Wissen Sie nur, dass die Anpassung der <summary>-Marker ein wenig kompliziert werden kann!
Hey, diese CSS-Feature-Abfrage war ziemlich großartig! Aber ich frage mich, wie man diese Dinge richtig animiert, da das Setzen eines Übergangs nicht funktioniert. Können Sie einige gute Animationen vorschlagen, damit diese nicht so aufdringlich sind?
Man könnte versuchen, dies zu modifizieren, ich habe
transform: scaleY(0);in den @keyframes verwendethttps://dev.to/pixmy/animate-details-tag-with-pure-css-52j7#:~:text=The%20tag%20can%20be,the%20open%20attribute%20is%20set.%22
Ich bevorzuge subtile Animationen, daher habe ich verwendet
JA! Vielen Dank, Greg – ich weiß es sehr zu schätzen. Bitte mach weiterhin tolle Sachen.
:)
Ich bin mir nicht sicher, ob es richtig ist zu sagen „es schadet wahrscheinlich nicht, dort eine Überschrift zu platzieren. Sie mag nur nicht immer helfen.“ Ich denke, das Problem ist ernster als das. JAWS kündigt nicht nur die Überschriften im Disclosure an, es nimmt sie auch nicht in die Überschriftenliste auf, die Screenreader-Benutzer oft zum Navigieren von Seiten verwenden. Für mich ist das ein Showstopper, wenn Überschriften in Disclosure Widgets benötigt werden. In diesen Situationen verwende ich JavaScript anstelle von Details-Summary.
Kann mir jemand helfen zu verstehen, warum ich die Kinder von (nicht die ) in ein Blockelement verpacken muss, um Flexbox für das Layout zu verwenden?
Minimalbeispiel mit Codepen: https://codepen.io/jbrains/pen/OJbmzoB
Vielen Dank.
Toller Artikel, aber ich habe eine Frage zu Ihrer Selektorverwendung. Ist es nicht unnötig spezifisch und redundant, einen Selektor wie
details summaryzu schreiben? Das einzig erlaubte Elternteil von<summary>ist<details>, daher sehe ich nicht wirklich, warum Sie es einschließen müssten. Best Practice ist, Ihre Selektoren mit einem möglichst geringen Spezifitätswert und so kurz wie möglich zu halten, also sollten Sie nicht einfachsummaryals Selektor verwenden?Gibt es einen Grund für die Verwendung eines Descendant-Combinator-Selektors anstelle eines einfachen Typselektors, den ich übersehe?
Ich möchte den Standard-Pfeilmarker verwenden und der Summary-Text soll eine andere Farbe haben als der Pfeilmarker.
Ist das möglich?
Ja, das ist möglich. Sie können den Pfeil eines Summary über das
::markerPseudo-Element gestalten.Ein paar kleine Anmerkungen.
Setzen Sie keine Überschriften in das summary-Tag, das ist schlecht für einige Screenreader, da sie diese ignorieren, wodurch Titel nicht im richtigen Fluss für eine Seite sind.
Verwenden Sie auch nicht cursor pointer dafür, das ist kein Link. „Interaktive Elemente“ brauchen keinen cursor pointer. Niemand wird ihn vermissen. Sie können jedoch einen normalen Mauszeiger als Cursor hinzufügen, wenn der Textcursor Sie stören würde.
Ich widerspreche der Cursor-Änderung entschieden. Pointer ist für Links; die Verwendung auf viel mehr als das ist irreführend. In einem Formular würden Sie Benutzer nicht irreführen, indem Sie den Eindruck erwecken, dass Labels Links sind, oder sie verwirren, indem Sie die vertikale Leiste bei den Texteingabefeldern nicht haben.
Für das Summary-Element sollte der Cursor die Textauswählbarkeit anzeigen – genau wie bei den meisten anderen Textinhalten. Wie bei einem Button, verwenden Sie nicht den Pointer, sondern stattdessen eine Hintergrundfarbe.
Und wie Dave Rupert schrieb, vermeiden Sie die Verwendung von h*-Tags in Summary.
https://daverupert.com/2019/12/why-details-is-not-an-accordion/