Scenārijs gandrīz vienmēr ir vienāds, kas ir datu tabula ritināmā konteinerā. Katrā rindā ir darbību izvēlne, neliela nolaižamā izvēlne ar dažām opcijām, piemēram, Rediģēt, Dublēt un Dzēst. Jūs to izveidojat, šķiet, ka tas lieliski darbojas atsevišķi, un tad kāds to ieliek tajā ritināmajā div un lietas sabrūk. Esmu redzējis tieši šo kļūdu trīs dažādās kodu bāzēs: konteinerā, skurstenī un ietvarā, kas visi atšķiras. Tomēr kļūda ir pilnīgi identiska. Nolaižamā izvēlne tiek apgriezta pie konteinera malas. Vai arī tas parādās aiz satura, kam loģiski vajadzētu būt zem tā. Vai arī tas darbojas labi, līdz lietotājs ritina, un tad tas novirzās. Jūs sasniedzat z-indeksu: 9999. Dažreiz tas palīdz, bet citreiz tas nedod absolūti neko. Šī nekonsekvence ir pirmā norāde, ka notiek kaut kas dziļāks. Iemesls, kā tas atkārtojas, ir tas, ka ir iesaistītas trīs atsevišķas pārlūkprogrammu sistēmas, un vairums izstrādātāju saprot katru atsevišķi, taču nekad nedomā par to, kas notiek, ja saduras visas trīs: pārpilde, kontekstu sakraušana un bloku saturs.
Tiklīdz jūs saprotat, kā visi trīs mijiedarbojas, atteices režīmi pārstāj justies nejauši. Patiesībā tie kļūst paredzami. Trīs lietas, kas to faktiski izraisa Apskatīsim katru no šiem elementiem sīkāk. Pārplūdes problēma Ja elementā iestatāt pārpilde: paslēpts, pārpilde: ritināšana vai pārpilde: automātiski, pārlūkprogramma izgriezīs visu, kas pārsniedz tās robežas, tostarp absolūti novietotos pēctečus. .scroll-container { pārplūde: auto; augstums: 300 pikseļi; /* Tiks izgriezta nolaižamā izvēlne, punkts */ }
.dropdown { pozīcija: absolūta; /* Nav nozīmes — joprojām izgrieza .scroll-container */ }
Tas mani pārsteidza, kad pirmo reizi uzskrēju. Es pieņēmu pozīciju: absolūtais ļautu elementam izvairīties no konteinera izgriezuma. Tā nav. Praksē tas nozīmē, ka absolūti pozicionētu izvēlni var izgriezt jebkurš priekštecis, kuram ir neredzama pārpildes vērtība, pat ja šis priekštecis nav izvēlni saturošais bloks. Apgriešana un pozicionēšana ir atsevišķas sistēmas. Viņi vienkārši saduras veidos, kas izskatās pilnīgi nejauši, līdz jūs saprotat abus.
Šeit ir React piemērs, izmantojot CreatePortal:
importēt { CreatePortal } no 'react-dom'; importēt { useState, useEffect, useRef } no 'react';
function Dropdown ({ anchorRef, isOpen, bērni }) { const [pozīcija, setPosition] = useState({ augšā: 0, pa kreisi: 0 });
useEffect(() => { if (isOpen && anchorRef.current) { const rect = anchorRef.current.getBoundingClientRect(); setPosition({ augšā: taisnais.apakšā + window.scrollY, pa kreisi: rect.left + window.scrollX, }); } }, [isOpen, anchorRef]);
if (!isOpen) return null;
atgriezt CreatePortal(
Un, protams, mēs nevaram ignorēt pieejamību. Fiksētajiem elementiem, kas parādās virs satura, joprojām ir jābūt sasniedzamiem ar tastatūru. Ja fokusa secība dabiski nenonāk fiksētajā nolaižamajā izvēlnē, jums tas būs jāpārvalda, izmantojot kodu. Ir arī vērts pārbaudīt, vai tas nav novietots pāri citam interaktīvajam saturam un nav iespējams to noraidīt. Tas jums iekost tastatūras testēšanā. CSS enkura pozicionēšana: uz kurieni, manuprāt, tas virzās CSS enkura pozicionēšana ir virziens, kas mani šobrīd interesē visvairāk. Es nebiju pārliecināts, cik lielu daļu specifikāciju var izmantot, kad pirmo reizi to aplūkoju. Tas ļauj deklarēt attiecības starp nolaižamo izvēlni un tā aktivizētāju tieši CSS, un pārlūkprogramma apstrādā koordinātas. .trigger { enkura nosaukums: --my-trigger; }
.dropdown-menu { pozīcija: absolūta; pozīcijas enkurs: --my-trigger; augšā: enkurs (apakšā); pa kreisi: enkurs(pa kreisi); pozīcija-mēģināt-atkāpšanās: flip-block, flip-inline; }
Pozīcija-try-fallbacks rekvizīts ir tas, kas padara to par vērtīgāku, salīdzinot ar manuālu aprēķinu. Pārlūkprogramma izmēģina alternatīvus izvietojumus, pirms padodas, tāpēc skata loga apakšā esošā nolaižamā izvēlne automātiski tiek pagriezta uz augšu, nevis tiek pārtraukta. Pārlūkprogrammu atbalsts ir stabils pārlūkprogrammās, kuru pamatā ir Chromium, un pieaug pārlūkprogrammā Safari. Firefox ir nepieciešams polifills. @oddbird/css-enkura pozicionēšanas pakotne aptver galveno specifikāciju. Esmu izmantojis to izkārtojuma malas gadījumos, kad bija nepieciešami atkāpšanās gadījumi, kurus es nebiju paredzējis, tāpēc uzskatiet to par progresīvu uzlabojumu vai savienojiet to arJavaScript rezerves Firefox. Īsāk sakot, daudzsološi, bet vēl ne universāli. Pārbaudiet mērķa pārlūkprogrammās. Un, kas attiecas uz pieejamību, vizuālo attiecību deklarēšana CSS pieejamības kokam neko nenorāda. aria-controls, aria-expanded, aria-haspopup — šī daļa joprojām ir jūsu ziņā. Dažreiz labojums ir tikai elementa pārvietošana Pirms meklēju portālu vai veicu koordinātu aprēķinus, es vienmēr vispirms uzdodu vienu jautājumu: vai šai nolaižamajai izvēlnei tiešām ir jāatrodas ritināšanas konteinerā? Ja tā nenotiek, marķējuma pārvietošana uz augstāka līmeņa iesaiņojumu pilnībā novērš problēmu, neizmantojot JavaScript un koordinātu aprēķinus. Tas ne vienmēr ir iespējams. Ja poga un nolaižamā izvēlne ir iekapsulēti vienā un tajā pašā komponentā, viena pārvietošana bez otra nozīmē visa API pārdomāšanu. Bet, kad varat to izdarīt, nav ko atkļūdot. Problēma vienkārši nepastāv. Ko mūsdienu CSS joprojām neatrisina CSS ir nogājusi garu ceļu, taču joprojām ir vietas, kas jūs pieviļ. Nostāja: fiksētās un pārveidošanas problēmas joprojām pastāv. Tas ir iekļauts specifikācijā ar nolūku, kas nozīmē, ka nav CSS risinājuma. Ja izmantojat animācijas bibliotēku, kas iesaiņo jūsu izkārtojumu pārveidotā elementā, jums atkal ir nepieciešami portāli vai enkura pozicionēšana. CSS enkura pozicionēšana ir daudzsološa, taču jauna. Kā minēts iepriekš, laikā, kad es rakstu, Firefox joprojām ir nepieciešams polifills. Ar to esmu trāpījis izkārtojuma malās, kurās bija nepieciešami atkāpšanās gadījumi, kurus es nebiju paredzējis. Ja jums šodien nepieciešama konsekventa rīcība visās pārlūkprogrammās, jūs joprojām meklējat JavaScript, lai atrisinātu sarežģītās daļas. Papildinājums, kuram esmu mainījis savu darbplūsmu, ir HTML Popover API, kas tagad ir pieejama visās mūsdienu pārlūkprogrammās. Elementi ar popover atribūtu tiek renderēti pārlūkprogrammas augšējā slānī, virs visa, un nav nepieciešama JavaScript pozicionēšana.
Escape apstrāde, noraidīšana, noklikšķinot ārpusē un stabila pieejamības semantika ir pieejamas bez maksas, piemēram, rīka padomiem, informācijas atklāšanas logrīkiem un vienkāršiem pārklājumiem. Tas ir pirmais rīks, pēc kura es šobrīd sasniedzu. Tas nozīmē, ka tas neatrisina pozicionēšanu. Tas atrisina slāņošanu. Jums joprojām ir nepieciešama enkura pozicionēšana vai JavaScript, lai uznirstošo logu pielāgotu tā aktivizētājam. Popover API apstrādā slāņošanu. Enkura pozicionēšana nodrošina izvietojumu. Ja tos izmanto kopā, tie aptver lielāko daļu no tā, ko iepriekš meklējāt bibliotēkai. Lēmumu ceļvedis jūsu situācijai Pēc tam, kad esmu izgājis visu šo grūto ceļu, es tagad domāju par izvēli.
Izmantojiet portālu. Es to izmantotu, ja aktivizētājs atrodas dziļi ligzdotos ritināšanas konteineros. Es izmantoju šo modeli galda darbību izvēlnēm un savienoju to pārī ar fokusa atjaunošanu un pieejamības pārbaudēm. Tā ir visdrošākā iespēja, taču papildu elektroinstalācijas izveidei ir nepieciešams budžeta laiks. Izmantojiet fiksētu pozicionēšanu. Tas ir paredzēts, ja izmantojat vaniļas JavaScript vai vieglo ietvaru un varat pārbaudīt, vai neviens sencis neizmanto transformācijas vai filtrus. To ir vienkārši iestatīt un vienkārši atkļūdot, ja vien ir spēkā šis viens ierobežojums. Izmantojiet CSS enkura pozicionēšanu. Sasniedziet to, kad to atļauj jūsu pārlūkprogrammas atbalsts. Ja ir nepieciešams Firefox atbalsts, savienojiet to pārī ar @oddbird polyfill. Tas ir tas, kur platforma galu galā virzās un galu galā kļūs par jūsu iecienītāko pieeju. Pārstrukturējiet DOM. Izmantojiet to, kad arhitektūra to atļauj un nevēlaties, lai izpildlaika sarežģītība būtu nulle. Es uzskatu, ka tas, iespējams, ir visvairāk nenovērtēts risinājums. Apvienojiet modeļus. Dariet to, ja vēlaties enkura pozicionēšanu kā savu galveno pieeju kopā ar JavaScript atkāpšanos neatbalstītām pārlūkprogrammām. Vai arī portāls DOM izvietojumam, kas savienots pārī ar getBoundingClientRect(), lai nodrošinātu koordinātu precizitāti.
Secinājums Es šo kļūdu uztvēru kā vienreizēju problēmu — kaut ko aizlāpīt un turpināt. Bet, tiklīdz es nosēdēju ar to pietiekami ilgi, lai saprastu visas trīs iesaistītās sistēmas — pārpildes izgriešana, kontekstu sakraušana un bloku saturēšana, tas pārstāja justies nejauši. Es varēju apskatīt bojātu nolaižamo izvēlni un nekavējoties izsekot, kurš sencis bija atbildīgs. Šīs izmaiņas tajā, kā es lasīju DOM, bija īsts risinājums. Nav vienas pareizās atbildes. Tas, pēc kā es sasniedzu, bija atkarīgs no tā, ko es varēju kontrolēt kodu bāzē: portālus, kad senču koks bija neparedzams; fiksēta pozicionēšana, kad tā bija tīra un vienkārša; elementa pārvietošana, kad nekas mani neapturēja; un enkura pozicionēšana tagad,kur es varu. Neatkarīgi no tā, ko izvēlaties, neuzskatiet pieejamību par pēdējo soli. Pēc manas pieredzes, tieši tad tas tiek izlaists. ARIA attiecības, fokusa pārvaldība, tastatūras izturēšanās — tās nav smalkas. Tie ir daļa no tā, kas liek lietai faktiski darboties. Skatiet pilnu avota kodu manā GitHub repo. Tālāka lasīšana Šīs ir atsauces, pie kurām es turpināju atgriezties, strādājot ar šo:
Kraušanas konteksts (MDN) “CSS enkura pozicionēšanas ceļvedis”, Huans Djego Rodrigess “Darba sākšana ar Popover API”, Godstime Aburu Peldošā lietotāja saskarne (floating-ui.com) CSS pārpilde (MDN)