Сенария қариб ҳамеша якхела аст, ки ҷадвали маълумот дар дохили контейнери ҳаракатшаванда мебошад. Ҳар як сатр дорои менюи амал, афтанда хурд бо баъзе интихобҳо, ба монанди Таҳрир, Нусхабардорӣ ва Нест кардан. Шумо онро месозед, ба назар чунин мерасад, ки он дар алоҳидагӣ комилан кор мекунад ва он гоҳ касе онро дар дохили он div ҳаракатшаванда мегузорад ва чизҳо ба ҳам меафтанд. Ман ин хатои дақиқро дар се пойгоҳи кодҳои гуногун дидаам: контейнер, стек ва чаҳорчӯба, ҳама гуногун. Бо вуҷуди ин, хатогӣ комилан якхела аст.
Раванди афтанда дар канори контейнер бурида мешавад. Ё он паси мундариҷаеро нишон медиҳад, ки мантиқан бояд дар зери он бошад. Ё он то он даме, ки корбар ҳаракат мекунад, хуб кор мекунад ва он гоҳ он дрейф мешавад.
Шумо ба z-index: 9999 мерасед. Баъзан он кӯмак мекунад, аммо дар дигар мавридҳо комилан ҳеҷ кор намекунад. Ин номувофиқатӣ далели аввалинест, ки чизи амиқтар рух медиҳад.
Сабаби бозгашти он дар он аст, ки се системаи браузери алоҳида ҷалб карда мешаванд ва аксари таҳиягарон ҳар яки онҳоро мустақилона мефаҳманд, аммо ҳеҷ гоҳ дар бораи он фикр намекунанд, ки ҳангоми бархӯрд кардани ҳар се чӣ мешавад: пурборшавӣ, контекстҳо ва блокҳо.
Вақте ки шумо фаҳмед, ки ҳар се чӣ гуна бо ҳам амал мекунанд, режимҳои нокомӣ эҳсоси тасодуфиро қатъ мекунанд. Дар асл, онҳо пешгӯишаванда мешаванд.
Се чиз, ки воқеан ба ин сабаб мешаванд
Биёед ҳар яке аз ин чизҳоро ба таври муфассал дида бароем.
Мушкилоти обхезӣ
Вақте ки шумо overflow: hidden, overflow: scroll ё overflow: auto-ро дар элемент муқаррар мекунед, браузер ҳама чизеро, ки берун аз ҳудуди он аст,, аз ҷумла насли комилан мавқеъро бурида мебарад.
.scroll-container {
пур кардан: худкор;
баландӣ: 300px;
/* Ин афтандаро пахш мекунад, қатъи пурра */
}
.афтанда {
мавқеъ: мутлақ;
/* Фарқ надорад -- то ҳол аз ҷониби .scroll-container бурида шудааст */
}
Вақте ки ман бори аввал ба он дучор шудам, ин маро ба ҳайрат овард. Ман мавқеъро қабул мекардам: мутлақ имкон медиҳад, ки элемент аз буридани контейнер гурезад. Ин не.
Дар амал, ин маънои онро дорад, ки менюи комилан ҷойгиршуда метавонад аз ҷониби ҳар як аҷдоди дорои арзиши изофанашаванда бурида шавад, ҳатто агар он аҷдод блоки дорои меню набошад. Клип ва ҷойгиркунӣ системаҳои алоҳида мебошанд. Онҳо танҳо ба таври тасодуфӣ бархӯрд мекунанд, то даме ки шумо ҳардуро фаҳмед.
Ин аст як мисоли React бо истифода аз createPortal:
ворид кардани {createPortal } аз 'react-dom';
import { useState, useEffect, useRef } аз 'react';
Функсияи афтанда ({anchorRef, isOpen, кӯдакон }) {
const [мавқеъ, setPosition] = useState ({боло: 0, чап: 0 });
useEffect(() => {
агар (isOpen && anchorRef.current) {
const rect = anchorRef.current.getBoundingClientRect();
setPosition({
боло: rect.bottom + window.scrollY,
чап: rect.left + window.scrollX,
});
}
}, [isOpen, anchorRef]);
агар (!isOpen) нулро баргардонад;
Бозгашти эҷоди Портал (
<див
id = "афтанда-демо"
нақш = "меню"
className = "менюи афтанда"
style={{ мавқеъ: 'мутлақо', боло: мавқеъ.боло, чап: мавқеъ.чап }}
>
{кӯдакон}
,
ҳуҷҷат.бадан
);
}
Ва, албатта, мо наметавонем дастрасиро нодида гирем. Унсурҳои собит, ки дар болои мундариҷа пайдо мешаванд, бояд ҳанӯз ҳам аз ҷониби клавиатура дастрас бошанд. Агар тартиби фокус табиатан ба афтанда собит нагузарад, шумо бояд онро бо истифода аз код идора кунед. Инчунин бояд тафтиш кард, ки он дар болои мундариҷаи интерактивии дигар наменишинад ва ҳеҷ гуна роҳи рад кардани он. Он шуморо дар санҷиши клавиатура газад.
Ҷойгиркунии лангари CSS: Ман фикр мекунам, ки ин ба куҷо меравад
Ҷойгиркунии CSS ин самтест, ки ман ҳоло ба он бештар таваҷҷӯҳ дорам. Вақте ки ман бори аввал ба он нигоҳ кардам, намедонистам, ки чӣ қадар ин хусусият воқеан қобили истифода аст. Он ба шумо имкон медиҳад, ки муносибати байни афтанда ва триггери онро мустақиман дар CSS эълон кунед ва браузер координатҳоро идора мекунад.
.триггер {
лангар-ном: --my-триггер;
}
менюи афтанда {
мавқеъ: мутлақ;
мавқеъ-лангар: --my-триггер;
боло: лангар (поён);
чап: лангар (аз чап);
мавқеъ-кӯшиш-фаллбакҳо: флип-блок, флип-inline;
}
Амволи position-try-fallbacks он чизест, ки онро дар ҳисоби дастӣ истифода бурдан лозим аст. Браузер пеш аз даст кашидан аз ҷойгоҳҳои алтернативӣ кӯшиш мекунад, аз ин рӯ, афтанда дар поёни намоишгоҳ ба ҷои қатъ шудан ба таври худкор ба боло ҳаракат мекунад.
Дастгирии браузер дар браузерҳои Chromium устувор аст ва дар Safari афзоиш меёбад. Firefox ба polyfill ниёз дорад. Бастаи @oddbird/css-anchor-positioning мушаххасоти асосиро дар бар мегирад. Ман бо он парвандаҳои канори тарҳро задам, ки бозгаштҳоро талаб мекард, ки ман интизор набудам, аз ин рӯ онро ҳамчун такмили прогрессивӣ ҳисоб кунед ё онро боБозгашти JavaScript барои Firefox.
Хулоса, умедбахш, аммо ҳанӯз универсалӣ нест. Дар браузерҳои мақсадноки худ санҷед.
Ва дар мавриди дастрасӣ, эълон кардани муносибати визуалӣ дар CSS ба дарахти дастрасӣ чизе намегӯяд. aria-controls, aria-expanded, aria-haspopup - он қисм то ҳол дар шумост.
Баъзан ислоҳ танҳо элементро интиқол медиҳад
Пеш аз расидан ба портал ё ҳисоб кардани координатҳо, ман ҳамеша як саволро медиҳам: Оё ин афтанда воқеан бояд дар дохили контейнери гардиш зиндагӣ кунад?
Агар ин тавр накунад, интиқоли нишона ба печи сатҳи баландтар мушкилотро комилан бартараф мекунад, бидуни JavaScript ва ҳисобҳои координатӣ.
Ин на ҳамеша имконпазир аст. Агар тугма ва афтанда дар як ҷузъ фаро гирифта шуда бошанд, интиқол додани яке бе дигаре маънои аз нав дида баромадани тамоми API-ро дорад. Аммо вақте ки шумо ин корро карда метавонед, ҳеҷ чиз барои ислоҳ кардан нест. Мушкилот танҳо вуҷуд надорад.
Он чизе ки CSS-и муосир то ҳол ҳал намекунад
CSS дар ин ҷо роҳи дарозеро тай кардааст, аммо то ҳол ҷойҳое ҳастанд, ки он шуморо ноумед мекунад.
Мавқеъ: мушкилоти собит ва тағирёбанда ҳоло ҳам вуҷуд доранд. Он дар мушаххасот қасдан аст, ки маънои онро дорад, ки ҳеҷ гуна роҳи ҳалли CSS вуҷуд надорад. Агар шумо китобхонаи аниматсияро истифода баред, ки тарҳи шуморо дар як унсури табдилшуда печонида бошад, шумо ба порталҳо ё ҷойгиркунии лангар бармегардед.
Ҷойгиркунии Anchor CSS умедбахш, аммо нав аст. Тавре ки қаблан зикр гардид, Firefox ҳоло ҳам ба полифилл ниёз дорад, ки ман инро менависам. Ман бо он парвандаҳои канори тарҳро задам, ки бозгаштҳоро талаб мекардам, ки ман интизор набудам. Агар ба шумо имрӯз дар тамоми браузерҳо рафтори доимӣ лозим бошад, шумо то ҳол барои қисматҳои душвор барои JavaScript муроҷиат мекунед.
Иловае, ки ман воқеан ҷараёни кори худро тағир додам, ин HTML Popover API мебошад, ки ҳоло дар ҳама браузерҳои муосир дастрас аст. Унсурҳои дорои атрибути popover дар қабати болоии браузер, аз ҳама болотар, бидуни ҷойгиркунии JavaScript талаб карда мешаванд.
Кушодан
Мӯҳтавои Popover
Муносибати фирорӣ, клик кардан дар берун ва семантикаи устувори дастрасӣ барои чизҳое ба монанди маслиҳатҳои асбобҳо, виджетҳои ифшо ва қабатҳои оддӣ ройгон меоянд. Ин аввалин асбобест, ки ман ҳоло ба даст меорам.
Гуфта мешавад, он мавқеъро ҳал намекунад. Он қабатро ҳал мекунад. Ба шумо ҳоло ҳам ҷойгиркунии лангар ё JavaScript лозим аст, то поповро ба триггери он мувофиқ созед. Popover API қабатбандиро идора мекунад. Ҷойгиркунии лангар ҷойгиркуниро идора мекунад. Якҷоя истифода мешаванд, онҳо бештари он чизеро, ки шумо қаблан барои анҷом додани китобхона дастрас карда будед, фаро мегиранд.
Роҳнамои тасмим барои вазъияти шумо
Пас аз гузаштани ҳамаи ин роҳи душвор, ин аст, ки ман воқеан ҳоло дар бораи интихоб фикр мекунам.
Порталро истифода баред. Ман инро вақте истифода мебарам, ки триггер дар контейнерҳои гардиши лона ҷойгир аст. Ман ин намунаро барои менюҳои амали ҷадвал истифода кардам ва онро бо барқарорсозии фокус ва санҷишҳои дастрасӣ ҷуфт кардам. Ин боэътимодтарин вариант аст, аммо вақти буҷет барои ноқилҳои иловагӣ.
Ҷойгиркунии собитро истифода баред. Ин барои он вақтест, ки шумо дар JavaScript ванилӣ ё чаҳорчӯбаи сабук ҳастед ва наметавонад тафтиш кунад, ки ҳеҷ аҷдод тағирот ё филтрҳоро татбиқ намекунад. Насб кардан ва ислоҳ кардан осон аст, ба шарте ки як маҳдудият нигоҳ дошта шавад.
Барои ин, вақте ки дастгирии браузери шумо ба он иҷозат медиҳад, CSS Anchor Positioning.Reach-ро истифода баред. Агар дастгирии Firefox лозим бошад, онро бо polyfill @oddbird ҷуфт кунед. Ин аст, ки платформа дар ниҳоят ба он ҷое меравад ва дар ниҳоят ба равиши шумо табдил хоҳад ёфт.
DOM-ро аз нав созед. Инро вақте истифода баред, ки меъморӣ ба он иҷозат медиҳад ва шумо мехоҳед, ки мураккабии сифр вақти корӣ дошта бошед. Ман боварӣ дорам, ки ин эҳтимолан варианти пасттарин аст.
Намунаҳоро муттаҳид кунед. Инро вақте иҷро кунед, вақте ки шумо мехоҳед ҷойгиркунии лангарро ҳамчун равиши асосии худ, ки бо бозгашти JavaScript барои браузерҳои дастгирӣнашаванда пайваст кардаед, иҷро кунед. Ё портал барои ҷойгиркунии DOM бо getBoundingClientRect() барои дақиқии координат ҷуфт карда шудааст.
Хулоса
Ман пештар ин хатогиро ҳамчун як масъалаи якдафъаина баррасӣ мекардам - чизе барои ислоҳ кардан ва идома додан. Аммо вақте ки ман бо он кофӣ дароз нишастам, то ҳама се системаро дарк кунам - буридани пурбор, контекстҳо ва дорои блокҳо - он эҳсоси тасодуфиро қатъ кард. Ман метавонистам як афтанда вайроншударо бубинам ва фавран пайгирӣ кунам, ки кадом аҷдод масъул аст. Ин тағирот дар он ки ман DOM-ро хондам, роҳи воқеӣ буд.
Ягон ҷавоби дуруст вуҷуд надорад. Он чизе, ки ман ба он расидам, аз он чизе, ки ман метавонистам дар пойгоҳи код назорат мекардам, вобаста буд: порталҳо, вақте ки дарахти аҷдодӣ пешгӯинашаванда буд; ҷойгиршавии собит вақте ки он тоза ва оддӣ буд; ҳаракат кардани элемент, вақте ки ҳеҷ чиз маро бозмедорад; ва ҷойгиркунии лангар ҳоло,ки ман метавонам.
Новобаста аз он ки шумо интихоб мекунед, дастрасӣ ба қадами охирин набошед. Дар таҷрибаи ман, маҳз ҳамон вақт он партофта мешавад. Муносибатҳои ARIA, идоракунии фокус, рафтори клавиатура - инҳо лаҳистон нестанд. Онҳо як қисми он чизе мебошанд, ки ин корро воқеан кор мекунад.
Рамзи пурраи сарчашмаро дар репои GitHub ман санҷед.
Хониши минбаъда
Инҳо истинодҳое ҳастанд, ки ман ҳангоми кор дар ин бора бозмегардам:
Контексти stacking (MDN)
"Дастур оид ба ҷойгиркунии лангари CSS", Хуан Диего Родригес
"Оғози кор бо API Popover", Godstime Aburu
UI шинокунанда (floating-ui.com)
CSS Overflow (MDN)