Scénář je téměř vždy stejný, což je datová tabulka uvnitř rolovatelného kontejneru. Každý řádek má nabídku akcí, malou rozevírací nabídku s některými možnostmi, jako je Upravit, Duplikovat a Smazat. Když to postavíte, zdá se, že to funguje perfektně izolovaně, a pak to někdo vloží do toho rolovatelného divu a věci se rozpadnou. Viděl jsem přesně tuto chybu ve třech různých kódových základnách: kontejner, zásobník a rámec, všechny různé. Chyba je však zcela identická. Rozbalovací seznam se ořízne na okraji kontejneru. Nebo se objeví za obsahem, který by měl být logicky pod ním. Nebo to funguje dobře, dokud uživatel neposouvá, a pak se to posune. Sáhnete po z-indexu: 9999. Někdy to pomůže, ale jindy nedělá absolutně nic. Tato nekonzistence je prvním vodítkem, že se děje něco hlubšího. Důvodem, proč se neustále vrací, je to, že se jedná o tři samostatné systémy prohlížečů a většina vývojářů rozumí každému z nich samostatně, ale nikdy nepřemýšlí o tom, co se stane, když se všechny tři střetnou: přetečení, skládání kontextů a obsahující bloky.

Jakmile pochopíte, jak se všechny tři vzájemně ovlivňují, režimy selhání přestanou být náhodné. Ve skutečnosti se stávají předvídatelnými. Tři věci, které to ve skutečnosti způsobují Podívejme se na každou z těchto položek podrobně. Problém přetečení Když u prvku nastavíte overflow: hidden, overflow: scroll nebo overflow: auto, prohlížeč ořízne vše, co přesahuje jeho hranice, včetně absolutně umístěných potomků. .scroll-container { přetečení: auto; výška: 300px; /* Tím se ořízne rozevírací seznam, tečka */ }

.rozbalovací seznam { pozice: absolutní; /* Nezáleží na tom - stále oříznuto .scroll-container */ }

To mě překvapilo, když jsem na to poprvé narazil. Zaujal jsem pozici: Absolutno by umožnilo prvku uniknout výstřižku kontejneru. není. V praxi to znamená, že absolutně umístěná nabídka může být odříznuta jakýmkoli předkem, který má neviditelnou hodnotu přetečení, i když tento předek není blok obsahující nabídku. Clipování a polohování jsou samostatné systémy. Náhodou se srazí způsoby, které vypadají zcela náhodně, dokud obojí nepochopíte.

Zde je příklad React pomocí createPortal:

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

function Dropdown({ anchorRef, isOpen, children }) { const [position, setPosition] = useState({ nahoře: 0, vlevo: 0 });

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

if (!isOpen) return null;

vrátit createPortal(

, dokument.tělo ); }

A samozřejmě nemůžeme ignorovat dostupnost. Opravené prvky, které se objevují nad obsahem, musí být stále dostupné z klávesnice. Pokud se pořadí fokusu přirozeně nepřesune do pevného rozevíracího seznamu, budete ho muset spravovat pomocí kódu. Také stojí za to zkontrolovat, že nesedí nad jiným interaktivním obsahem a není možné jej odmítnout. Ten vás kousne při testování klávesnice. Umístění kotvy CSS: Kam si myslím, že to směřuje CSS Anchor Positioning je směr, který mě teď nejvíc zajímá. Když jsem se na to poprvé podíval, nebyl jsem si jistý, kolik ze specifikace bylo skutečně použitelné. Umožňuje vám deklarovat vztah mezi rozevíracím seznamem a jeho spouštěčem přímo v CSS a prohlížeč zpracovává souřadnice. .trigger { kotevní-jméno: --my-trigger; }

.rozbalovací nabídka { pozice: absolutní; poloha-kotva: --my-trigger; nahoře: kotva(dole); vlevo: kotva(vlevo); pozice-try-fallbacks: flip-block, flip-inline; }

Vlastnost position-try-fallbacks je to, kvůli čemu se vyplatí používat tuto vlastnost při ručním výpočtu. Prohlížeč zkouší alternativní umístění, než to vzdá, takže rozevírací seznam v dolní části výřezu se místo oříznutí automaticky otočí nahoru. Podpora prohlížeče je pevná v prohlížečích založených na Chromiu a roste v Safari. Firefox potřebuje polyfill. Balíček @oddbird/css-anchor-positioning pokrývá základní specifikaci. Podařilo se mi s ním narazit na okrajové případy rozložení, které vyžadovaly nouzová řešení, s nimiž jsem nepočítala, takže to považujte za progresivní vylepšení nebo je spárujte sZáložní JavaScript pro Firefox. Zkrátka slibné, ale zatím ne univerzální. Otestujte ve svých cílových prohlížečích. A pokud jde o přístupnost, deklarování vizuálního vztahu v CSS stromu přístupnosti nic neřekne. aria-controls, aria-expanded, aria-haspopup – tato část je stále na vás. Někdy je oprava jen přesunutí prvku Než sáhnem po portálu nebo udělám souřadnicové výpočty, vždy se nejprve zeptám na jednu otázku: Musí tato rozevírací nabídka skutečně žít uvnitř rolovacího kontejneru? Pokud tomu tak není, přesunutí označení do obálky vyšší úrovně problém zcela eliminuje, bez JavaScriptu a bez souřadnicových výpočtů. To není vždy možné. Pokud jsou tlačítko a rozevírací seznam zapouzdřeny ve stejné komponentě, přesun jednoho bez druhého znamená přehodnocení celého API. Ale když to dokážete, není co ladit. Problém prostě neexistuje. Co moderní CSS stále neřeší CSS zde ušlo dlouhou cestu, ale stále existují místa, kde vás zklame. Pozice: Opraveno a problémy s transformací stále existují. Je to ve specifikaci záměrně, což znamená, že neexistuje žádné řešení CSS. Pokud používáte knihovnu animací, která zabalí vaše rozvržení do transformovaného prvku, budete opět potřebovat portály nebo umístění kotvy. CSS Anchor Positioning je slibný, ale nový. Jak již bylo zmíněno dříve, Firefox v době, kdy toto píšu, stále potřebuje polyfill. Narazil jsem na okrajové případy rozvržení, které vyžadovaly nouzová řešení, se kterými jsem nepočítal. Pokud dnes potřebujete konzistentní chování ve všech prohlížečích, stále sáhnete po JavaScriptu pro složitější části. Doplněk, kvůli kterému jsem změnil svůj pracovní postup, je HTML Popover API, které je nyní dostupné ve všech moderních prohlížečích. Prvky s atributem popover se vykreslují v horní vrstvě prohlížeče, nad vším, bez nutnosti umístění JavaScriptu.

Únikové ovládání, zavření při kliknutí-venku a solidní sémantika přístupnosti jsou zdarma pro věci, jako jsou popisky, widgety pro zpřístupnění a jednoduché překryvy. Je to první nástroj, po kterém teď sáhnu. To znamená, že to neřeší umístění. Řeší vrstvení. K zarovnání vyskakovacího okna s jeho spouštěčem stále potřebujete umístění kotvy nebo JavaScript. Rozhraní Popover API zpracovává vrstvení. Umístění kotvy řeší umístění. Když se použijí společně, pokrývají většinu toho, co byste dříve sáhli po knihovně. Průvodce rozhodováním pro vaši situaci Poté, co jsem si tím vším těžce prošel, tady je návod, jak teď vlastně o výběru přemýšlím.

Použijte portál. Použil bych to, když spouštěč žije hluboko ve vnořených rolovacích kontejnerech. Tento vzor jsem použil pro nabídky akcí tabulky a spároval jsem ho s obnovením fokusu a kontrolami přístupnosti. Je to nejspolehlivější možnost, ale rozpočet na další kabeláž. Použijte pevné umístění. Je to pro případ, že používáte vanilkový JavaScript nebo odlehčenou strukturu a můžete ověřit, že žádný předek nepoužívá transformace nebo filtry. Je snadné jej nastavit a snadno ladit, pokud platí toto jedno omezení. Použijte CSS Anchor Positioning. Reach k tomu, pokud to podpora vašeho prohlížeče umožňuje. Pokud je vyžadována podpora Firefoxu, spárujte ji s @oddbird polyfill. To je místo, kam platforma nakonec směřuje a nakonec se stane vaším přístupem. Restrukturalizovat DOM. Použijte to, když to architektura umožňuje a chcete nulovou složitost běhu. Věřím, že je to pravděpodobně nejvíce podceňovaná možnost. Kombinujte vzory. Udělejte to, když chcete jako primární přístup umístění kotvy, spárované s nouzovým kódem JavaScriptu pro nepodporované prohlížeče. Nebo portál pro umístění DOM spárovaný s getBoundingClientRect() pro přesnost souřadnic.

Závěr Kdysi jsem tuto chybu považoval za jednorázový problém - něco, co je třeba opravit a od čeho se posunout. Ale jakmile jsem u toho seděl dostatečně dlouho, abych pochopil všechny tři zúčastněné systémy – ořezávání přetečení, skládání kontextů a obsahující bloky – přestalo mi to připadat náhodné. Mohl jsem se podívat na nefunkční rozevírací seznam a okamžitě vysledovat, který předek byl zodpovědný. Tento posun v tom, jak jsem četl DOM, byl skutečným zážitkem. Neexistuje jediná správná odpověď. To, po čem jsem sáhl, záviselo na tom, co jsem mohl ovládat v kódové základně: portály, když byl strom předků nepředvídatelný; pevné umístění, když to bylo čisté a jednoduché; pohyb prvku, když mě nic nezastavovalo; a umístění kotvy nyní,kde můžu. Ať už si vyberete cokoli, nepovažujte dostupnost za poslední krok. Podle mých zkušeností je to přesně ten okamžik, kdy se to přeskakuje. Vztahy ARIA, řízení fokusu, chování klávesnice – to není nic extra. Jsou součástí toho, díky čemu ta věc skutečně funguje. Podívejte se na úplný zdrojový kód v mém repozitáři GitHub. Další čtení Toto jsou reference, ke kterým jsem se neustále vracel při práci na tomto:

Kontext stohování (MDN) „Průvodce umístěním kotvy CSS“, Juan Diego Rodriguez „Začínáme s Popover API“, Godstime Aburu Plovoucí uživatelské rozhraní (floating-ui.com) Přetečení CSS (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