Сцэнар амаль заўсёды аднолькавы, які ўяўляе сабой табліцу даных у кантэйнеры, які можна пракручваць. У кожным радку ёсць меню дзеянняў, невялікае выпадальнае меню з некаторымі опцыямі, такімі як «Праўка», «Дублікат» і «Выдаліць». Вы ствараеце яго, і здаецца, што ён выдатна працуе ў ізаляцыі, а потым нехта змяшчае яго ў гэты div, які можна пракручваць, і ўсё развальваецца. Я бачыў гэту дакладную памылку ў трох розных кодавых базах: кантэйнер, стэк і структура, усе розныя. Памылка, аднак, цалкам ідэнтычная. Выпадальнае меню абразаецца на краі кантэйнера. Або ён з'яўляецца за змесцівам, якое па логіцы павінна знаходзіцца пад ім. Або ён працуе нармальна, пакуль карыстальнік не пракручвае, а потым рухаецца. Вы дасягаеце z-індэкс: 9999. Часам гэта дапамагае, але іншы раз абсалютна нічога не робіць. Гэта неадпаведнасць - першая падказка таго, што адбываецца нешта больш глыбокае. Прычына, па якой гэта пастаянна вяртаецца, заключаецца ў тым, што задзейнічаны тры асобныя сістэмы браўзераў, і большасць распрацоўшчыкаў разумеюць кожную з іх паасобку, але ніколі не задумваюцца аб тым, што адбываецца, калі ўсе тры сутыкаюцца: перапаўненне, кантэксты стэкавання і ўтрымліваючыя блокі.

Як толькі вы зразумееце, як усе тры ўзаемадзейнічаюць, рэжымы адмовы перастануць адчуваць сябе выпадковымі. Фактычна яны становяцца прадказальнымі. Тры рэчы, якія сапраўды выклікаюць гэта Давайце разгледзім кожны з гэтых пунктаў падрабязна. Праблема перапаўнення Калі вы ўсталюеце для элемента overflow: hidden, overflow: scroll або overflow: auto, браўзер будзе выразаць усё, што выходзіць за яго межы, у тым ліку абсалютна пазіцыянаваныя нашчадкі. .scroll-container { перапаўненне: аўта; вышыня: 300 пікселяў; /* Гэта абразае выпадальнае меню, кропка */ }

.dropdown { пазіцыя: абсалютная; /* Не мае значэння -- усё яшчэ абразаецца .scroll-container */ }

Гэта мяне здзівіла, калі я ўпершыню сутыкнуўся з гэтым. Я прыняў пазіцыю: absolute дазволіць элементу пазбегнуць абразання кантэйнера. Гэта не так. На практыцы гэта азначае, што абсалютна пазіцыянаванае меню можа быць адрэзана любым продкам, які мае нябачнае значэнне перапаўнення, нават калі гэты продак не з'яўляецца блокам, які змяшчае меню. Абразанне і пазіцыянаванне - гэта розныя сістэмы. Яны проста сутыкаюцца спосабамі, якія выглядаюць цалкам выпадковымі, пакуль вы не зразумееце абодва.

Вось прыклад React з выкарыстаннем createPortal:

імпарт {createPortal} з 'react-dom'; імпарт {useState, useEffect, useRef} з 'react';

функцыя Dropdown({anchorRef, isOpen, дзеці}) { const [position, setPosition] = useState({ top: 0, left: 0 });

useEffect(() => { калі (isOpen && anchorRef.current) { const rect = anchorRef.current.getBoundingClientRect(); setPosition({ зверху: rect.bottom + window.scrollY, злева: rect.left + window.scrollX, }); } }, [isOpen, anchorRef]);

if (!isOpen) вяртае нуль;

вярнуць createPortal( <разм id="выпадаючае-дэма" роля="меню" className="выпадальнае меню" style={{ position: 'absolute', top: position.top, left: position.left }} > {дзеці}

, дакумент.цела ); }

І, вядома ж, мы не можам ігнараваць даступнасць. Фіксаваныя элементы, якія з'яўляюцца па-над змесцівам, павінны быць даступнымі з клавіятуры. Калі парадак факусіроўкі не перамяшчаецца ў фіксаванае выпадальнае меню, вам трэба будзе кіраваць ім з дапамогай кода. Варта таксама пераканацца, што ён не знаходзіцца над іншым інтэрактыўным змесцівам і не можа яго адхіліць. Гэта кусае вас падчас тэсціравання клавіятуры. Якарнае пазіцыянаванне CSS: куды, на маю думку, гэта ідзе Якарнае пазіцыянаванне CSS - гэта кірунак, які мяне зараз больш за ўсё цікавіць. Я не быў упэўнены, колькі спецыфікацый сапраўды можна выкарыстоўваць, калі я ўпершыню паглядзеў на іх. Гэта дазваляе аб'явіць сувязь паміж выпадальным спісам і яго трыгерам непасрэдна ў CSS, а браўзер апрацоўвае каардынаты. .trigger { імя якара: --my-trigger; }

.выпадальнае меню { пазіцыя: абсалютная; position-anchor: --my-trigger; зверху: якар(знізу); злева: якар (злева); пазіцыя-спроба-запасныя варыянты: фліп-блок, фліп-інлайн; }

Уласцівасць position-try-fallbacks - гэта тое, што робіць гэта варта выкарыстоўваць замест ручнога разліку. Браўзер спрабуе альтэрнатыўныя месцы размяшчэння, перш чым адмовіцца, таму выпадальны спіс унізе акна прагляду аўтаматычна перагортваецца ўверх, а не абразаецца. Падтрымка браўзераў надзейная ў браўзерах на аснове Chromium і расце ў Safari. Firefox патрэбна полізапаўненне. Пакет @oddbird/css-anchor-positioning ахоплівае асноўныя спецыфікацыі. Я дасягнуў з ім краёвых варыянтаў макета, якія патрабавалі рэзервовых варыянтаў, якіх я не чакаў, таму разглядайце яго як прагрэсіўнае ўдасканаленне або спалучайце яго зРэзервны варыянт JavaScript для Firefox. Карацей, перспектыўны, але пакуль не універсальны. Праверце ў мэтавых браўзерах. А што тычыцца даступнасці, аб'яўленне візуальнай сувязі ў CSS нічога не паведамляе дрэву даступнасці. aria-controls, aria-expanded, aria-haspopup — гэтая частка па-ранейшаму за вамі. Часам выпраўленне проста ў перамяшчэнні элемента Перш чым звярнуцца да партала або зрабіць вылічэнні каардынатаў, я заўсёды спачатку задаю адно пытанне: ці сапраўды гэта выпадальнае меню павінна знаходзіцца ўнутры кантэйнера пракруткі? Калі гэтага не адбываецца, перанос разметкі ў абгортку больш высокага ўзроўню цалкам ліквідуе праблему, без JavaScript і вылічэнняў каардынат. Гэта не заўсёды магчыма. Калі кнопка і выпадальны спіс заключаны ў адзін і той жа кампанент, перасоўванне аднаго без іншага азначае пераасэнсаванне ўсяго API. Але калі вы можаце гэта зрабіць, няма чаго адладжваць. Праблемы проста не існуе. Што сучасны CSS яшчэ не вырашае CSS прайшоў доўгі шлях тут, але ўсё яшчэ ёсць месцы, дзе ён вас падводзіць. Пазіцыя: праблемы з выпраўленнем і трансфармацыяй усё яшчэ існуюць. Гэта ў спецыфікацыі наўмысна, што азначае, што абыходнага шляху CSS не існуе. Калі вы выкарыстоўваеце бібліятэку анімацыі, якая абгортвае ваш макет трансфармаваным элементам, вам зноў патрэбныя парталы або размяшчэнне якара. CSS Anchor Positioning з'яўляецца перспектыўным, але новым. Як згадвалася раней, у той час, калі я пішу гэта, Firefox усё яшчэ патрабуе поліфілу. Я дасягнуў з ім краёвых выпадкаў макета, якія патрабавалі запасных варыянтаў, якіх я не чакаў. Калі сёння вам патрэбны аднастайныя паводзіны ва ўсіх браўзерах, вы па-ранейшаму карыстаецеся JavaScript для складаных частак. Дапаўненне, для якога я фактычна змяніў свой працоўны працэс, - гэта HTML Popover API, цяпер даступны ва ўсіх сучасных браўзерах. Элементы з атрыбутам popover адлюстроўваюцца ў верхнім пласце браўзера, над усім, без неабходнасці пазіцыянавання JavaScript.

Апрацоўка ўцёкаў, адхіленне пры пстрычцы па-за межамі і надзейная семантыка даступнасці бясплатныя для такіх рэчаў, як падказкі, віджэты раскрыцця інфармацыі і простыя накладкі. Гэта першы інструмент, да якога я цяпер дацягваюся. Тым не менш, гэта не вырашае пазіцыянаванне. Гэта вырашае шматслойнасць. Вам усё яшчэ спатрэбіцца пазіцыянаванне прывязкі або JavaScript, каб выраўнаваць усплывальнае акно да яго трыгера. Popover API апрацоўвае напластаванне. Якарнае пазіцыянаванне апрацоўвае размяшчэнне. Выкарыстоўваючыся разам, яны ахопліваюць большую частку таго, што вы б раней рабілі ў бібліятэцы. Кіраўніцтва па прыняцці рашэнняў у вашай сітуацыі Прайшоўшы праз усё гэта цяжкі шлях, вось як я цяпер думаю пра выбар.

Выкарыстоўвайце партал. Я б выкарыстаў гэта, калі трыгер знаходзіцца глыбока ва ўкладзеных кантэйнерах пракруткі. Я выкарыстаў гэты шаблон для меню дзеянняў табліцы і спалучыў яго з аднаўленнем фокусу і праверкай даступнасці. Гэта самы надзейны варыянт, але бюджэтны час на дадатковую праводку. Выкарыстоўвайце фіксаванае пазіцыянаванне. Гэта для выпадкаў, калі вы выкарыстоўваеце ванільны JavaScript або палегчаны фрэймворк і можаце пераканацца, што ніводны продак не прымяняе пераўтварэнні або фільтры. Гэта проста наладзіць і лёгка адладзіць, пакуль выконваецца адно абмежаванне. Выкарыстоўвайце CSS Anchor Positioning. Reach для гэтага, калі падтрымка вашага браўзера гэта дазваляе. Калі патрабуецца падтрымка Firefox, спалучыце яе з @oddbird polyfill. Гэта тое, куды платформа ў канчатковым рахунку накіроўваецца і ў канчатковым выніку стане вашым падыходам. Рэструктуруйце DOM. Выкарыстоўвайце гэта, калі гэта дазваляе архітэктура і вам патрэбна нулявая складанасць падчас выканання. Я лічу, што гэта, верагодна, самы недаацэнены варыянт. Камбінуйце шаблоны. Рабіце гэта, калі вам патрэбны якарны пазіцыянаванне ў якасці асноўнага падыходу ў спалучэнні з рэзервовым варыянтам JavaScript для браўзераў, якія не падтрымліваюцца. Або партал для размяшчэння DOM у спалучэнні з getBoundingClientRect() для дакладнасці каардынат.

Заключэнне Раней я разглядаў гэтую памылку як разавую праблему — нешта, што трэба выправіць і рухацца далей. Але як толькі я пасядзеў з ім дастаткова доўга, каб зразумець усе тры задзейнічаныя сістэмы — адсячэнне перапаўнення, кантэкст стэкавання і блокі, якія змяшчаюць — гэта перастала адчуваць сябе выпадковым. Я мог бы паглядзець на зламанае выпадальнае меню і адразу прасачыць, які продак быў адказным. Гэтая змена ў тым, як я чытаў DOM, стала сапраўдным высновай. Адназначнага правільнага адказу няма. Да чаго я імкнуўся, залежала ад таго, што я мог кантраляваць у кодавай базе: парталы, калі дрэва продка было непрадказальным; фіксаванае пазіцыянаванне, калі яно было чыстым і простым; рухаць элемент, калі мяне нішто не спыняла; і размяшчэнне якара зараз,дзе магу. Што б вы ні абралі, не разглядайце даступнасць як апошні крок. З майго вопыту, менавіта тады яго прапускаюць. Узаемаадносіны ARIA, кіраванне фокусам, паводзіны клавіятуры - гэта не вытанчана. Яны з'яўляюцца часткай таго, што прымушае рэч сапраўды працаваць. Праверце поўны зыходны код у маім сховішчы GitHub. Далейшае чытанне Гэта спасылкі, да якіх я ўвесь час вяртаўся, працуючы над гэтым:

Кантэкст кладкі (MDN) «Кіраўніцтва па пазіцыянаванні прывязкі CSS», Хуан Дыега Радрыгес «Пачатак працы з Popover API», Godstime Aburu Плаваючы карыстацкі інтэрфейс (floating-ui.com) Перапаўненне 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