Scenariet er næsten altid det samme, som er en datatabel inde i en rulbar container. Hver række har en handlingsmenu, en lille rullemenu med nogle muligheder, såsom Rediger, Dupliker og Slet. Du bygger det, det ser ud til at fungere perfekt isoleret, og så lægger nogen det inde i den rullebare div, og tingene falder fra hinanden. Jeg har set denne nøjagtige fejl i tre forskellige kodebaser: containeren, stakken og rammen, alle forskellige. Fejlen er dog fuldstændig identisk. Dropdown-listen bliver klippet ved containerens kant. Eller det dukker op bag indhold, der logisk set burde være under det. Eller det fungerer fint indtil brugeren scroller, og så driver det. Du rækker ud efter z-indeks: 9999. Nogle gange hjælper det, men andre gange gør det absolut ingenting. Den inkonsekvens er det første fingerpeg om, at der sker noget dybere. Grunden til, at det bliver ved med at vende tilbage, er, at tre separate browsersystemer er involveret, og de fleste udviklere forstår hver enkelt for sig, men tænker aldrig på, hvad der sker, når alle tre kolliderer: overløb, stabling af sammenhænge og at indeholde blokke.

Når du først forstår, hvordan alle tre interagerer, holder fejltilstandene op med at føles tilfældige. Faktisk bliver de forudsigelige. De tre ting, der faktisk forårsager dette Lad os se på hver af disse elementer i detaljer. Overløbsproblemet Når du indstiller overløb: skjult, overløb: rul eller overløb: auto på et element, vil browseren klippe alt, der strækker sig ud over dets grænser, inklusive absolut placerede efterkommere. .scroll-container { overløb: auto; højde: 300px; /* Dette vil klippe rullemenuen, punktum */ }

.dropdown { position: absolut; /* Betyder ikke noget -- stadig klippet af .scroll-container */ }

Det overraskede mig første gang, jeg løb ind i det. Jeg havde indtaget position: absolut ville lade et element undslippe en containers klipning. Det gør den ikke. I praksis betyder det, at en absolut positioneret menu kan afskæres af enhver forfader, der har en ikke-synlig overløbsværdi, selvom denne forfader ikke er menuens indeholdende blok. Klipning og positionering er separate systemer. De kommer bare til at støde sammen på måder, der ser helt tilfældige ud, indtil du forstår begge dele.

Her er et React-eksempel ved hjælp af createPortal:

importer { createPortal } fra 'react-dom'; importer { useState, useEffect, useRef } fra 'react';

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

useEffect(() => { if (erOpen && anchorRef.current) { const rect = anchorRef.current.getBoundingClientRect(); setPosition({ top: rect.bottom + window.scrollY, venstre: rect.left + window.scrollX, }); } }, [isOpen, anchorRef]);

if (!isOpen) returner null;

returner createPortal(

, document.body ); }

Og selvfølgelig kan vi ikke ignorere tilgængelighed. Faste elementer, der vises over indhold, skal stadig være tilgængelige med tastaturet. Hvis fokusrækkefølgen ikke naturligt flytter ind i den faste dropdown, skal du administrere den ved hjælp af kode. Det er også værd at tjekke, at det ikke ligger over andet interaktivt indhold uden mulighed for at afvise det. Den der bider dig i tastaturtest. CSS-ankerpositionering: Hvor jeg tror, det er på vej CSS Anchor Positioning er den retning, jeg er mest interesseret i lige nu. Jeg var ikke sikker på, hvor meget af specifikationerne faktisk var brugbare, da jeg først så på den. Det lader dig erklære forholdet mellem en dropdown og dens trigger direkte i CSS, og browseren håndterer koordinaterne. .trigger { ankernavn: --min-udløser; }

.dropdown-menu { position: absolut; position-anker: --min-udløser; top: anker(bund); venstre: anker(venstre); position-try-fallbacks: flip-blok, flip-inline; }

Egenskaben position-try-fallbacks er det, der gør dette værd at bruge over en manuel beregning. Browseren prøver alternative placeringer, før den giver op, så en dropdown nederst i visningsporten vipper automatisk opad i stedet for at blive afskåret. Browserunderstøttelse er solid i Chromium-baserede browsere og vokser i Safari. Firefox har brug for en polyfill. @oddbird/css-anchor-positioning-pakken dækker kernespecifikationen. Jeg har ramt layout edge cases med det, der krævede fallbacks, jeg ikke havde forudset, så behandl det som en progressiv forbedring eller par det med enJavaScript fallback til Firefox. Kort sagt, lovende, men ikke universel endnu. Test i dine målbrowsere. Og hvad angår tilgængelighed, fortæller det ikke tilgængelighedstræet noget at erklære et visuelt forhold i CSS. aria-kontroller, aria-udvidet, aria-haspopup - den del er stadig på dig. Nogle gange er rettelsen bare at flytte elementet Inden jeg rækker ud efter en portal eller laver koordinatberegninger, stiller jeg altid først et spørgsmål: Skal denne dropdown faktisk være inde i rullecontaineren? Hvis det ikke gør det, vil flytning af markeringen til en indpakning på højere niveau eliminere problemet fuldstændigt uden JavaScript og ingen koordinatberegninger. Dette er ikke altid muligt. Hvis knappen og dropdown-menuen er indkapslet i den samme komponent, betyder det at flytte den ene uden den anden, at man genovervejer hele API'et. Men når du kan gøre det, er der intet at fejle. Problemet eksisterer bare ikke. Hvad moderne CSS stadig ikke løser CSS er nået langt her, men der er stadig steder, det svigter dig. Stillingen: problemer med løst og transformeret er der stadig. Det er med vilje i specifikationerne, hvilket betyder, at der ikke findes nogen CSS-løsning. Hvis du bruger et animationsbibliotek, der omslutter dit layout i et transformeret element, er du tilbage til brug for portaler eller ankerpositionering. CSS Anchor Positioning er lovende, men ny. Som tidligere nævnt har Firefox stadig brug for en polyfill på det tidspunkt, jeg skriver dette. Jeg har ramt layout-kantsager med det, der krævede fallbacks, jeg ikke havde forudset. Hvis du har brug for ensartet adfærd på tværs af alle browsere i dag, rækker du stadig efter JavaScript til de vanskelige dele. Den tilføjelse, jeg faktisk har ændret min arbejdsgang til, er HTML Popover API, som nu er tilgængelig i alle moderne browsere. Elementer med popover-attributten gengives i browserens øverste lag, over alt, uden behov for JavaScript-positionering.

Undslip-håndtering, afvis-ved-klik-udenfor og solid tilgængelighedssemantik er gratis for ting som værktøjstip, afsløringswidgets og simple overlejringer. Det er det første værktøj, jeg når til nu. Når det er sagt, så løser det ikke positionering. Det løser lagdeling. Du har stadig brug for ankerpositionering eller JavaScript for at tilpasse en popover til dens udløser. Popover API'en håndterer lagdelingen. Ankerpositionering håndterer placeringen. Brugt sammen dækker de det meste af det, du tidligere ville nå til et bibliotek at gøre. En beslutningsvejledning til din situation Efter at have gennemgået alt dette på den hårde måde, er her hvordan jeg faktisk tænker om valget nu.

Brug en portal. Jeg ville bruge denne, når udløseren bor dybt i indlejrede rullebeholdere. Jeg brugte dette mønster til tabelhandlingsmenuer og parrede det med fokusgendannelse og tilgængelighedstjek. Det er den mest pålidelige mulighed, men budgetter med tid til de ekstra ledninger. Brug fast positionering. Dette er til, når du er i vanilla JavaScript eller en letvægtsramme og kan bekræfte, at ingen forfader anvender transformationer eller filtre. Det er nemt at konfigurere og nemt at fejlfinde, så længe den ene begrænsning gælder. Brug CSS Anchor Positioning. Reach for dette, når din browsersupport tillader det. Hvis Firefox-understøttelse er påkrævet, skal du parre den med @oddbird polyfill. Det er her, platformen i sidste ende er på vej hen og vil i sidste ende blive din go-to-tilgang. Omstrukturer DOM. Brug dette, når arkitekturen tillader det, og du ønsker nul runtime-kompleksitet. Jeg tror, ​​at det sandsynligvis er den mest undervurderede mulighed. Kombiner mønstre. Gør dette, når du ønsker ankerpositionering som din primære tilgang, parret med en JavaScript-tilbagegang for ikke-understøttede browsere. Eller en portal til DOM-placering parret med getBoundingClientRect() for koordinatnøjagtighed.

Konklusion Jeg plejede at behandle denne fejl som et engangsproblem - noget at lappe og gå videre fra. Men da jeg først sad med det længe nok til at forstå alle tre involverede systemer - overløbsklipning, stabling af sammenhænge og indeholdende blokke - holdt det op med at føles tilfældigt. Jeg kunne se på en brudt dropdown og straks spore, hvilken forfader der var ansvarlig. Det skift i, hvordan jeg læste DOM, var den rigtige takeaway. Der er ikke et enkelt rigtigt svar. Hvad jeg rakte ud efter afhang af, hvad jeg kunne kontrollere i kodebasen: portaler, når forfadertræet var uforudsigeligt; fast positionering, når det var rent og enkelt; flytte elementet, når intet stoppede mig; og ankerpositionering nu,hvor jeg kan. Uanset hvad du ender med at vælge, skal du ikke behandle tilgængelighed som det sidste trin. Efter min erfaring er det præcis, når det bliver sprunget over. ARIA-relationerne, fokusstyringen, tastaturadfærden - de er ikke polske. De er en del af det, der får tingene til at fungere. Tjek den fulde kildekode i min GitHub-repo. Yderligere læsning Dette er de referencer, jeg blev ved med at vende tilbage til, mens jeg arbejdede igennem dette:

The Stacking Context (MDN) "CSS Anchor Positioning Guide", Juan Diego Rodriguez "Kom godt i gang med Popover API", Godstime Aburu Flydende brugergrænseflade (floating-ui.com) CSS-overløb (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