Skenari është pothuajse gjithmonë i njëjtë, i cili është një tabelë e të dhënave brenda një kontejneri të lëvizshëm. Çdo rresht ka një meny veprimi, një listë të vogël me disa opsione, si Edit, Duplicate dhe Fshi. Ju e ndërtoni atë, duket se funksionon në mënyrë të përsosur në izolim, dhe më pas dikush e vendos brenda asaj div të lëvizshme dhe gjërat shpërbëhen. Unë e kam parë këtë gabim të saktë në tre baza të ndryshme kodesh: kontejneri, pirgu dhe korniza, të gjitha të ndryshme. Megjithatë, defekti është krejtësisht identik. Lista e lëshimit pritet në skajin e kontejnerit. Ose shfaqet pas përmbajtjes që logjikisht duhet të jetë poshtë saj. Ose funksionon mirë derisa përdoruesi të lëvizë dhe më pas të lëvizë. Ju arrini z-indeksin: 9999. Ndonjëherë ndihmon, por herë të tjera nuk bën absolutisht asgjë. Kjo mospërputhje është e dhëna e parë se diçka më e thellë po ndodh. Arsyeja pse ai vazhdon të rikthehet është se përfshihen tre sisteme të veçanta të shfletuesit dhe shumica e zhvilluesve e kuptojnë secilin më vete, por kurrë nuk mendojnë se çfarë ndodh kur të tre përplasen: tejmbushja, grumbullimi i konteksteve dhe mbajtja e blloqeve.
Pasi të kuptoni se si ndërveprojnë të treja, mënyrat e dështimit ndalojnë të ndjehen të rastësishme. Në fakt, ato bëhen të parashikueshme. Tre gjërat që e shkaktojnë në të vërtetë këtë Le të shohim në detaje secilin prej këtyre artikujve. Problemi i tejmbushjes Kur vendosni tejkalim: i fshehur, tejmbushje: lëviz ose tejmbushje: automatik në një element, shfletuesi do të këpusë çdo gjë që shtrihet përtej kufijve të tij, duke përfshirë pasardhësit e pozicionuar absolutisht. .scroll-container { tejmbushje: auto; lartësia: 300 px; /* Kjo do të shkurtojë listën rënëse, pikë e plotë */ }
.dropdown { pozicioni: absolut; /* Nuk ka rëndësi -- ende i prerë nga .scroll-container */ }
Kjo më befasoi herën e parë që u përplasa me të. Unë do të kisha marrë pozicionin: absolute do të lejonte një element të shpëtonte nga prerja e një kontejneri. nuk bën. Në praktikë, kjo do të thotë se një menu absolutisht e pozicionuar mund të ndërpritet nga çdo paraardhës që ka një vlerë të padukshme të tejmbushjes, edhe nëse ai paraardhës nuk është blloku që përmban menunë. Prerja dhe pozicionimi janë sisteme të veçanta. Ata thjesht ndodhin të përplasen në mënyra që duken krejtësisht të rastësishme derisa t'i kuptoni të dyja.
Këtu është një shembull React duke përdorur createPortal:
importoni {createPortal } nga 'react-dom'; importoni { useState, useEffect, useRef } nga 'react';
funksioni Dropdown ({ anchorRef, isOpen, fëmijë }) { const [pozicion, setPosition] = useState({ lart: 0, majtas: 0 });
useEffect(() => { nëse (isOpen && anchorRef.current) { const rect = anchorRef.current.getBoundingClientRect(); setPozicioni ({ lart: rect.bottom + window.scrollY, majtas: rect.left + window.scrollX, }); } }, [isOpen, anchorRef]);
nëse (!isOpen) kthen null;
ktheje CreativePortal(
Dhe, natyrisht, ne nuk mund të injorojmë aksesin. Elementet fikse që shfaqen mbi përmbajtje duhet të jenë ende të arritshme nga tastiera. Nëse rendi i fokusit nuk kalon natyrshëm në listën fikse me zbritje, do t'ju duhet ta menaxhoni atë duke përdorur kodin. Vlen gjithashtu të kontrollohet se nuk qëndron mbi përmbajtje të tjera interaktive pa asnjë mënyrë për ta hedhur poshtë. Ai ju kafshon në testimin e tastierës. Pozicionimi i ankorimit CSS: Ku mendoj se po shkon CSS Anchor Positioning është drejtimi për të cilin jam më i interesuar për momentin. Nuk isha i sigurt se sa nga specifikat ishin në të vërtetë të përdorshme kur e shikova për herë të parë. Kjo ju lejon të deklaroni lidhjen midis një dropdown dhe aktivizimit të tij direkt në CSS, dhe shfletuesi trajton koordinatat. .trigger { spirancë-emër: --my-trigger; }
.dropdown-menu { pozicioni: absolut; pozicion-spirancë: --my-trigger; sipër: spirancë (poshtë); majtas: spirancë (majtas); pozicion-provim-fallbacks: Flip-block, Flip-inline; }
Vetia position-try-fallbacks është ajo që e bën këtë të vlefshme për t'u përdorur gjatë një llogaritjeje manuale. Shfletuesi provon vendosje alternative përpara se të heqë dorë, kështu që një listë rënëse në fund të portës së pamjes kthehet automatikisht lart në vend që të ndërpritet. Mbështetja e shfletuesit është e fortë në shfletuesit e bazuar në Chromium dhe po rritet në Safari. Firefox-i ka nevojë për një mbushje. Paketa @oddbird/css-anchor-positioning mbulon specifikat kryesore. Unë kam goditur me të rastet e skajit të paraqitjes që kërkonin rikthim që nuk i kisha parashikuar, prandaj trajtojeni si një përmirësim progresiv ose çiftoje me njëRikthim i JavaScript për Firefox. Me pak fjalë, premtuese, por jo universale ende. Testoni në shfletuesit tuaj të synuar. Dhe për sa i përket aksesueshmërisë, deklarimi i një marrëdhënie vizuale në CSS nuk i tregon asgjë pemës së aksesueshmërisë. aria-controls, aria-expanded, aria-haspopup - ajo pjesë është ende mbi ju. Ndonjëherë rregullimi është thjesht duke lëvizur elementin Përpara se të arrij për një portal ose të bëj llogaritjet e koordinatave, unë gjithmonë bëj një pyetje fillimisht: A duhet në të vërtetë kjo listë me listë të jetë brenda kontejnerit të rrotullës? Nëse jo, zhvendosja e shënimit në një mbështjellës të nivelit më të lartë e eliminon plotësisht problemin, pa JavaScript dhe pa llogaritje të koordinatave. Kjo nuk është gjithmonë e mundur. Nëse butoni dhe pika e lëshimit janë të kapsuluara në të njëjtin komponent, lëvizja e njërit pa tjetrin do të thotë të rimendoni të gjithë API-në. Por kur mund ta bësh, nuk ka asgjë për të korrigjuar. Problemi thjesht nuk ekziston. Çfarë CSS moderne ende nuk zgjidh CSS ka bërë një rrugë të gjatë këtu, por ka ende vende që ju zhgënjen. Pozicioni: çështjet e fiksuara dhe të transformuara janë ende atje. Është në specifikim qëllimisht, që do të thotë se nuk ekziston asnjë zgjidhje CSS. Nëse jeni duke përdorur një bibliotekë animacioni që mbështjell paraqitjen tuaj me një element të transformuar, ju jeni kthyer në nevojë për portalet ose pozicionimin e ankorimit. CSS Anchor Positioning është premtues, por i ri. Siç u përmend më herët, Firefox-i ka ende nevojë për një mbushje të plotë në kohën që po shkruaj këtë. Unë kam goditur rastet e skajit të paraqitjes me të që kërkonin rikthim që nuk i kisha parashikuar. Nëse keni nevojë për sjellje të qëndrueshme në të gjithë shfletuesit sot, ju ende po kërkoni JavaScript për pjesët e ndërlikuara. Shtesa për të cilën kam ndryshuar në të vërtetë rrjedhën time të punës është HTML Popover API, tani i disponueshëm në të gjithë shfletuesit modernë. Elementet me atributin popover paraqiten në shtresën e sipërme të shfletuesit, mbi gjithçka, pa nevojë për pozicionim JavaScript.
Trajtimi i arratisjes, heqja mbi klikim nga jashtë dhe semantika e qëndrueshme e aksesueshmërisë janë falas për gjëra të tilla si këshillat e veglave, miniaplikacionet e zbulimit dhe mbivendosjet e thjeshta. Është mjeti i parë që kam arritur tani për tani. Thënë kjo, nuk zgjidh pozicionimin. Zgjidh shtresimin. Ju duhet ende pozicionimi i ankorimit ose JavaScript për të lidhur një popover me shkasin e tij. Popover API trajton shtresimin. Pozicionimi i ankorimit trajton vendosjen. Të përdorura së bashku, ato mbulojnë pjesën më të madhe të asaj që do të kishit arritur më parë për të bërë një bibliotekë. Një udhëzues vendimi për situatën tuaj Pasi e kalova gjithë këtë në rrugën e vështirë, ja se si mendoj në të vërtetë për zgjedhjen tani.
Përdorni një portal. Unë do ta përdorja këtë kur këmbëza jeton thellë në kontejnerët e rrotullimit të mbivendosur. E përdora këtë model për menutë e veprimit të tabelave dhe e lidha me rivendosjen e fokusit dhe kontrollet e aksesueshmërisë. Është opsioni më i besueshëm, por buxheti i kohës për instalime elektrike shtesë. Përdorni pozicionim fiks. Kjo është kur jeni në JavaScript vanilje ose një kornizë të lehtë dhe mund të verifikoni se asnjë paraardhës nuk aplikon transformime ose filtra. Është e thjeshtë për t'u konfiguruar dhe e thjeshtë për t'u korrigjuar, për sa kohë që qëndron ai një kufizim. Përdorni CSS Anchor Positioning.Arrijeni këtë kur mbështetja e shfletuesit tuaj e lejon. Nëse kërkohet mbështetje për Firefox, çiftoje atë me polifillin @oddbird. Kjo është ajo ku platforma po shkon përfundimisht dhe përfundimisht do të bëhet qasja juaj e preferuar. Ristrukturoni DOM-in. Përdoreni këtë kur arkitektura e lejon dhe ju dëshironi zero kompleksitet të kohës së funksionimit. Unë besoj se është opsioni më i nënvlerësuar. Kombinoni modelet.Bëjeni këtë kur dëshironi pozicionimin e ankorimit si qasjen tuaj kryesore, të çiftuar me një kthim prapa JavaScript për shfletuesit e pambështetur. Ose një portal për vendosjen DOM i çiftuar me getBoundingClientRect() për saktësinë e koordinatave.
konkluzioni Dikur e trajtoja këtë defekt si një problem të vetëm - diçka për të rregulluar dhe për të vazhduar. Por sapo u ula me të mjaftueshëm për të kuptuar të tre sistemet e përfshira - prerja e tejmbushjes, grumbullimi i konteksteve dhe mbajtja e blloqeve - ai pushoi së ndjeri i rastësishëm. Mund të shikoja një listë të thyer dhe të gjurmoja menjëherë se cili paraardhës ishte përgjegjës. Ky ndryshim në mënyrën se si e lexova DOM-in ishte marrja e vërtetë. Nuk ka asnjë përgjigje të vetme të drejtë. Ajo që arrita varej nga ajo që mund të kontrolloja në bazën e kodeve: portalet kur pema paraardhëse ishte e paparashikueshme; pozicionimi fiks kur ishte i pastër dhe i thjeshtë; lëvizja e elementit kur asgjë nuk më ndalonte; dhe pozicionimi i ankorimit tani,ku mundem. Çfarëdo që të zgjidhni, mos e trajtoni aksesin si hapin e fundit. Në përvojën time, kjo është pikërisht kur ajo anashkalohet. Marrëdhëniet ARIA, menaxhimi i fokusit, sjellja e tastierës - ato nuk janë të shkëlqyera. Ato janë pjesë e asaj që e bën gjënë të funksionojë. Shikoni kodin e plotë burimor në depon time të GitHub. Lexim i mëtejshëm Këto janë referencat të cilave u kthehesha vazhdimisht gjatë punës me këtë:
Konteksti i grumbullimit (MDN) "Udhëzues për pozicionimin e ankorimit CSS", Juan Diego Rodriguez "Fillimi me API Popover", Godstime Aburu Ndërfaqja e përdoruesit lundrues (floating-ui.com) Vërshimi i CSS (MDN)