Das Szenario ist fast immer dasselbe: eine Datentabelle in einem scrollbaren Container. Jede Zeile verfügt über ein Aktionsmenü, ein kleines Dropdown-Menü mit einigen Optionen wie Bearbeiten, Duplizieren und Löschen. Wenn man es baut, scheint es isoliert perfekt zu funktionieren, und dann fügt jemand es in dieses scrollbare Div ein und alles fällt auseinander. Ich habe genau diesen Fehler in drei verschiedenen Codebasen gesehen: dem Container, dem Stack und dem Framework, alle unterschiedlich. Der Fehler ist jedoch völlig identisch. Das Dropdown wird am Rand des Containers abgeschnitten. Oder es erscheint hinter Inhalten, die logischerweise darunter liegen sollten. Oder es funktioniert einwandfrei, bis der Benutzer einen Bildlauf durchführt, und dann driftet es ab. Sie greifen nach Z-Index: 9999. Manchmal hilft es, aber manchmal bewirkt es überhaupt nichts. Diese Inkonsistenz ist der erste Hinweis darauf, dass etwas Tieferes passiert. Der Grund dafür, dass es immer wieder auftritt, ist, dass drei separate Browsersysteme beteiligt sind und die meisten Entwickler jedes für sich verstehen, aber nie darüber nachdenken, was passiert, wenn alle drei kollidieren: Überlauf, Stapelkontexte und enthaltende Blöcke.

Sobald Sie verstehen, wie alle drei zusammenwirken, fühlen sich die Fehlermodi nicht mehr zufällig an. Tatsächlich werden sie vorhersehbar. Die drei Dinge, die dies tatsächlich verursachen Schauen wir uns jeden dieser Punkte im Detail an. Das Überlaufproblem Wenn Sie overflow:hidden, overflow:scroll oder overflow:auto für ein Element festlegen, schneidet der Browser alles ab, was über seine Grenzen hinausgeht, einschließlich absolut positionierter Nachkommen. .scroll-container { Überlauf: automatisch; Höhe: 300px; /* Dadurch wird das Dropdown-Menü abgeschnitten, Punkt */ }

.dropdown { Position: absolut; /* Spielt keine Rolle – immer noch abgeschnitten durch .scroll-container */ }

Das hat mich überrascht, als ich zum ersten Mal darauf gestoßen bin. Ich hatte angenommen, dass position: absolute einem Element erlauben würde, dem Ausschnitt eines Containers zu entkommen. Das ist nicht der Fall. In der Praxis bedeutet das, dass ein absolut positioniertes Menü von jedem Vorgänger abgeschnitten werden kann, der einen nicht sichtbaren Überlaufwert hat, selbst wenn dieser Vorgänger nicht der enthaltende Block des Menüs ist. Clipping und Positionierung sind separate Systeme. Sie kollidieren einfach auf völlig zufällige Weise, bis man beides versteht.

Hier ist ein React-Beispiel mit createPortal:

import { createPortal } aus 'react-dom'; import { useState, useEffect, useRef } from 'react';

function Dropdown({ AnchorRef, isOpen, Children }) { const [position, setPosition] = useState({ top: 0, left: 0 });

useEffect(() => { if (isOpen && AnchorRef.current) { const rect = AnchorRef.current.getBoundingClientRect(); setPosition({ oben: rect.bottom + window.scrollY, links: rect.left + window.scrollX, }); } }, [isOpen, AnchorRef]);

if (!isOpen) return null;

return createPortal(

, document.body ); }

Und natürlich dürfen wir die Barrierefreiheit nicht außer Acht lassen. Feste Elemente, die über dem Inhalt angezeigt werden, müssen weiterhin über die Tastatur erreichbar sein. Wenn die Fokusreihenfolge nicht automatisch in das feste Dropdown-Menü verschoben wird, müssen Sie sie mithilfe von Code verwalten. Es lohnt sich auch zu prüfen, dass es nicht über anderen interaktiven Inhalten liegt und es keine Möglichkeit gibt, es zu verwerfen. Das stört Sie beim Tastaturtest. CSS-Ankerpositionierung: Wohin das meiner Meinung nach führt CSS-Ankerpositionierung ist die Richtung, die mich derzeit am meisten interessiert. Als ich es mir zum ersten Mal ansah, war ich mir nicht sicher, wie viel von der Spezifikation tatsächlich nutzbar war. Damit können Sie die Beziehung zwischen einem Dropdown und seinem Auslöser direkt in CSS deklarieren, und der Browser verarbeitet die Koordinaten. .trigger { Ankername: --my-trigger; }

.dropdown-menu { Position: absolut; Positionsanker: --my-trigger; oben: Anker (unten); links: Anker(links); Position-Try-Fallbacks: Flip-Block, Flip-Inline; }

Aufgrund der Position-Try-Fallbacks-Eigenschaft lohnt sich die Verwendung gegenüber einer manuellen Berechnung. Der Browser versucht alternative Platzierungen, bevor er aufgibt, sodass ein Dropdown-Menü am unteren Rand des Ansichtsfensters automatisch nach oben klappt, anstatt abgeschnitten zu werden. Die Browserunterstützung ist in Chromium-basierten Browsern solide und nimmt in Safari zu. Firefox benötigt eine Polyfüllung. Das Paket @oddbird/css-anchor-positioning deckt die Kernspezifikation ab. Ich bin damit auf Layout-Edge-Fälle gestoßen, die Rückschläge erforderten, mit denen ich nicht gerechnet hatte. Behandeln Sie es also als progressive Verbesserung oder kombinieren Sie es mit einerJavaScript-Fallback für Firefox. Kurz gesagt: vielversprechend, aber noch nicht universell. Testen Sie in Ihren Zielbrowsern. Und was die Barrierefreiheit betrifft, sagt die Deklaration einer visuellen Beziehung in CSS dem Barrierefreiheitsbaum nichts aus. aria-controls, aria-expanded, aria-haspopup – dieser Teil liegt immer noch bei Ihnen. Manchmal besteht die Lösung einfach darin, das Element zu verschieben Bevor ich nach einem Portal greife oder Koordinatenberechnungen durchführe, stelle ich immer zuerst eine Frage: Muss sich dieses Dropdown-Menü tatsächlich im Scroll-Container befinden? Ist dies nicht der Fall, wird das Problem durch Verschieben des Markups auf einen Wrapper auf höherer Ebene vollständig beseitigt, ohne JavaScript und ohne Koordinatenberechnungen. Dies ist nicht immer möglich. Wenn die Schaltfläche und das Dropdown-Menü in derselben Komponente gekapselt sind, bedeutet das Verschieben einer ohne die andere, dass die gesamte API überdacht werden muss. Aber wenn Sie es schaffen, gibt es nichts zu debuggen. Das Problem existiert einfach nicht. Was modernes CSS immer noch nicht löst CSS hat hier einen langen Weg zurückgelegt, aber es gibt immer noch Stellen, an denen es Sie im Stich lässt. Die Position: Fix- und Transformationsprobleme sind immer noch da. Es ist absichtlich in der Spezifikation enthalten, was bedeutet, dass es keinen CSS-Workaround gibt. Wenn Sie eine Animationsbibliothek verwenden, die Ihr Layout in ein transformiertes Element einhüllt, sind Sie wieder auf Portale oder Ankerpositionierung angewiesen. CSS-Ankerpositionierung ist vielversprechend, aber neu. Wie bereits erwähnt, benötigt Firefox zum Zeitpunkt, an dem ich dies schreibe, noch eine Polyfill-Funktion. Ich bin damit auf Layout-Randfälle gestoßen, die Rückschläge erforderten, mit denen ich nicht gerechnet hatte. Wenn Sie heute ein konsistentes Verhalten in allen Browsern benötigen, greifen Sie für die kniffligen Teile immer noch auf JavaScript zurück. Die Ergänzung, für die ich meinen Workflow tatsächlich geändert habe, ist die HTML-Popover-API, die jetzt in allen modernen Browsern verfügbar ist. Elemente mit dem Popover-Attribut werden in der obersten Ebene des Browsers über allem gerendert, ohne dass eine JavaScript-Positionierung erforderlich ist.

Escape-Handling, Dismiss-on-Click-outside und eine solide Barrierefreiheitssemantik sind für Dinge wie Tooltips, Offenlegungs-Widgets und einfache Overlays kostenlos. Es ist das erste Werkzeug, zu dem ich im Moment greife. Das heißt, es löst nicht die Positionierung. Es löst die Schichtung. Sie benötigen weiterhin eine Ankerpositionierung oder JavaScript, um ein Popover an seinem Auslöser auszurichten. Die Popover-API übernimmt die Schichtung. Die Ankerpositionierung übernimmt die Platzierung. Zusammengenommen decken sie den größten Teil dessen ab, was Sie früher von einer Bibliothek erwarten würden. Ein Entscheidungsleitfaden für Ihre Situation Nachdem ich das alles auf die harte Tour durchgemacht habe, denke ich jetzt tatsächlich so über die Wahl nach.

Verwenden Sie ein Portal. Ich würde es verwenden, wenn der Auslöser tief in verschachtelten Scroll-Containern liegt. Ich habe dieses Muster für Tabellenaktionsmenüs verwendet und es mit Fokuswiederherstellung und Barrierefreiheitsprüfungen kombiniert. Dies ist die zuverlässigste Option, aber planen Sie Zeit für die zusätzliche Verkabelung ein. Verwenden Sie eine feste Positionierung. Dies ist für den Fall gedacht, dass Sie sich in Vanilla-JavaScript oder einem leichtgewichtigen Framework befinden und sicherstellen können, dass kein Vorgänger Transformationen oder Filter anwendet. Es ist einfach einzurichten und zu debuggen, solange diese eine Einschränkung gilt. Verwenden Sie hierfür CSS Anchor Positioning.Reach, sofern Ihr Browser dies zulässt. Wenn Firefox-Unterstützung erforderlich ist, koppeln Sie sie mit der @oddbird-Polyfüllung. In diese Richtung geht die Plattform letztendlich und wird schließlich zu Ihrem bevorzugten Ansatz. Strukturieren Sie das DOM neu. Verwenden Sie dies, wenn die Architektur dies zulässt und Sie keine Laufzeitkomplexität wünschen. Ich glaube, es ist wahrscheinlich die am meisten unterschätzte Option. Kombinieren Sie Muster. Tun Sie dies, wenn Sie die Ankerpositionierung als primären Ansatz verwenden möchten, gepaart mit einem JavaScript-Fallback für nicht unterstützte Browser. Oder ein Portal für die DOM-Platzierung gepaart mit getBoundingClientRect() für Koordinatengenauigkeit.

Fazit Früher habe ich diesen Fehler als ein einmaliges Problem betrachtet – etwas, das man beheben und dann weitermachen kann. Aber als ich lange genug damit saß, um alle drei beteiligten Systeme zu verstehen – Overflow-Clipping, Stacking-Kontexte und Containing-Blöcke – fühlte es sich nicht mehr zufällig an. Ich konnte mir eine kaputte Dropdown-Liste ansehen und sofort herausfinden, welcher Vorfahre dafür verantwortlich war. Diese Veränderung in der Art und Weise, wie ich das DOM las, war der eigentliche Erkenntnisgewinn. Es gibt keine einzige richtige Antwort. Wonach ich griff, hing davon ab, was ich in der Codebasis steuern konnte: Portale, wenn der Ahnenbaum unvorhersehbar war; feste Positionierung, wenn es sauber und einfach war; das Element bewegen, als mich nichts mehr aufhalten konnte; und Ankerpositionierung jetzt,wo ich kann. Was auch immer Sie letztendlich wählen, betrachten Sie die Barrierefreiheit nicht als den letzten Schritt. Meiner Erfahrung nach wird es genau dann übersprungen. Die ARIA-Beziehungen, die Fokusverwaltung, das Tastaturverhalten – das ist nicht auf Hochglanz. Sie sind Teil dessen, was die Sache tatsächlich zum Funktionieren bringt. Schauen Sie sich den vollständigen Quellcode in meinem GitHub-Repo an. Weiterführende Literatur Dies sind die Referenzen, auf die ich während der Arbeit immer wieder zurückkam:

Der Stacking-Kontext (MDN) „CSS Anchor Positioning Guide“, Juan Diego Rodriguez „Erste Schritte mit der Popover-API“, Godstime Aburu Floating-Benutzeroberfläche (floating-ui.com) CSS-Überlauf (MDN)

You May Also Like

Enjoyed This Article?

Get weekly tips on growing your audience and monetizing your content — straight to your inbox.

No spam. Join 138,000+ creators. Unsubscribe anytime.

Create Your Free Bio Page

Join 138,000+ creators on Seemless.

Get Started Free