Avastage võimas, kokkupõrkeid arvestav positsioneerimine CSS-is. Õppige, kuidas @position-try ja ankurpositsioneerimine lahendavad keerulisi kasutajaliidese väljakutseid, vähendades JavaScripti vajadust.
Absoluutsest positsioneerimisest kaugemale: Sügavuti CSS @position-try ja ankurpositsioneerimisest
Aastakümneid on veebiarendajad maadelnud tavapäraste kasutajaliidese väljakutsetega: luua tööriistavihjeid, hüpikaknaid, kontekstimenüüsid ja muid hõljuvaid elemente, mis paigutavad end arukalt päästikuga (trigger) seotud asukohta. Traditsiooniline lähenemine on peaaegu alati hõlmanud peent tantsu CSS-i `position: absolute` ja suure hulga JavaScripti vahel, et arvutada asukohti, tuvastada vaateakna kokkupõrkeid ja muuta elemendi paigutust käigu pealt.
See JavaScripti-rohke lahendus, kuigi tõhus, toob kaasa omajagu probleeme: jõudluse lisakulu, hoolduse keerukus ja pidev võitlus loogika robustsena hoidmiseks. Teegid nagu Popper.js said tööstusharu standardiks just seetõttu, et seda probleemi oli nii raske lahendada platvormi-omaste vahenditega. Aga mis siis, kui saaksime need keerulised positsioneerimisstrateegiad deklareerida otse CSS-is?
Siin tuleb mängu CSS-i ankurpositsioneerimise API – murranguline ettepanek, mis on valmis muutma revolutsiooniliselt seda, kuidas me neid stsenaariume käsitleme. Selle keskmes on kaks võimsat kontseptsiooni: võime "ankurdada" üks element teise külge, sõltumata nende DOM-suhtest, ja varuvariantide reeglite kogum, mis on defineeritud @position-try abil. See artikkel pakub põhjaliku ülevaate sellest uuest piirist CSS-is, andes teile võimaluse ehitada vastupidavamaid, jõudlusvõimelisemaid ja deklaratiivsemaid kasutajaliideseid.
Traditsioonilise positsioneerimise püsiv probleem
Enne kui saame hinnata uue lahenduse elegantsi, peame esmalt mõistma vana lahenduse piiranguid. Dünaamilise positsioneerimise tööhobune on alati olnud `position: absolute`, mis positsioneerib elemendi selle lähima positsioneeritud esivanema suhtes.
JavaScripti kark
Kujutage ette lihtsat tööriistavihjet, mis peaks ilmuma nupu kohale. `position: absolute` abil saate selle õigesti paigutada. Aga mis juhtub siis, kui see nupp on brauseriakna ülemise serva lähedal? Tööriistavihje lõigatakse ära. Või kui see on parema serva lähedal? Tööriistavihje voolab üle ja käivitab horisontaalse kerimisriba.
Selle lahendamiseks on arendajad ajalooliselt tuginenud JavaScriptile:
- Ankurelemendi asukoha ja mõõtmete hankimine `getBoundingClientRect()` abil.
- Tööriistavihje mõõtmete hankimine.
- Vaateakna mõõtmete hankimine (`window.innerWidth`, `window.innerHeight`).
- Mitmete arvutuste tegemine, et määrata ideaalsed `top` ja `left` väärtused.
- Kontrollimine, kas see ideaalne asukoht põhjustab kokkupõrke vaateakna servadega.
- Kui põhjustab, siis uuesti arvutamine alternatiivse asukoha jaoks (nt selle pööramine nupu alla).
- `scroll` ja `resize` sündmuste kuulajate lisamine, et korrata kogu seda protsessi iga kord, kui paigutus võib muutuda.
See on märkimisväärne hulk loogikat ülesande jaoks, mis tundub olevat puhtalt esitluslik. See on habras, võib hoolikal rakendamisel põhjustada paigutuse värinaid (layout jank) ning suurendab teie rakenduse paketi suurust ja põhilõime tööd.
Uus paradigma: tutvustame CSS-i ankurpositsioneerimist
CSS-i ankurpositsioneerimise API pakub deklaratiivset, ainult CSS-il põhinevat viisi nende suhete haldamiseks. Põhiidee on luua ühendus kahe elemendi vahel: positsioneeritud element (nt tööriistavihje) ja selle ankur (nt nupp).
Põhiomadused: `anchor-name` ja `position-anchor`
Maagia algab kahe uue CSS-i omadusega:
- `anchor-name`: See omadus rakendatakse elemendile, mida soovite kasutada võrdluspunktina. See annab ankur-elemendile unikaalse, sidekriipsuga algava nime, millele saab mujal viidata.
- `position-anchor`: See omadus rakendatakse positsioneeritavale elemendile ja ütleb sellele, millist nimega ankrut oma asukoha arvutamiseks kasutada.
Vaatame põhinäidet:
<!-- HTML Structure -->
<button id="my-button">Hover Me</button>
<div class="tooltip">This is a tooltip!</div>
<!-- CSS -->
#my-button {
anchor-name: --my-button-anchor;
}
.tooltip {
position: absolute;
position-anchor: --my-button-anchor;
/* Now we can position relative to the anchor */
bottom: anchor(top);
left: anchor(center);
}
Selles koodilõigus on nupp määratud ankruks nimega `--my-button-anchor`. Seejärel kasutab tööriistavihje `position-anchor` omadust, et end selle ankur-elemendiga siduda. Tõeliselt revolutsiooniline osa on `anchor()` funktsioon, mis võimaldab meil kasutada ankru piire (`top`, `bottom`, `left`, `right`, `center`) meie positsioneerimisomaduste väärtustena.
See juba lihtsustab asju, kuid ei lahenda veel vaateakna kokkupõrke probleemi. Siin tulebki mängu @position-try.
Lahenduse süda: `@position-try` ja `position-fallback`
Kui ankurpositsioneerimine loob sideme elementide vahel, siis `@position-try` pakub intelligentsust. See võimaldab teil defineerida prioriteetide nimekirja alternatiivsetest positsioneerimisstrateegiatest. Seejärel proovib brauser iga strateegiat järjekorras, valides esimese, mis võimaldab positsioneeritud elemendil mahtuda oma sisaldavasse plokki (tavaliselt vaateaknasse) ilma, et seda kärbitaks.
Varuvariantide defineerimine
`@position-try` plokk on nimega CSS-reeglite kogum, mis defineerib ühe positsioneerimisvaliku. Saate neid luua nii palju, kui vaja.
/* Variant 1: Paiguta ankru kohale */
@position-try --tooltip-top {
bottom: anchor(top);
left: anchor(center);
transform: translateX(-50%);
}
/* Variant 2: Paiguta ankru alla */
@position-try --tooltip-bottom {
top: anchor(bottom);
left: anchor(center);
transform: translateX(-50%);
}
/* Variant 3: Paiguta ankrust paremale */
@position-try --tooltip-right {
left: anchor(right);
top: anchor(center);
transform: translateY(-50%);
}
/* Variant 4: Paiguta ankrust vasakule */
@position-try --tooltip-left {
right: anchor(left);
top: anchor(center);
transform: translateY(-50%);
}
Pange tähele, kuidas iga plokk defineerib täieliku positsioneerimisstrateegia. Oleme loonud neli erinevat varianti: üles, alla, paremale ja vasakule ankru suhtes.
Varuvariantide rakendamine `position-fallback` abil
Kui teil on `@position-try` plokid olemas, ütlete positsioneeritud elemendile, et ta kasutaks neid `position-fallback` omaduse abil. Järjekord on oluline – see määrab prioriteedi.
.tooltip {
position: absolute;
position-anchor: --my-button-anchor;
position-fallback: --tooltip-top --tooltip-bottom --tooltip-right --tooltip-left;
}
Selle üheainsa CSS-i reaga olete andnud brauserile juhised:
- Esiteks, proovi positsioneerida tööriistavihjet reeglitega, mis on plokis `--tooltip-top`.
- Kui see asukoht põhjustab tööriistavihje kärpimist vaateaknas, hülga see ja proovi reegleid plokist `--tooltip-bottom`.
- Kui ka see ebaõnnestub, proovi `--tooltip-right`.
- Ja kui kõik muu ebaõnnestub, proovi `--tooltip-left`.
Brauser tegeleb kogu kokkupõrgete tuvastamise ja asukoha vahetamisega automaatselt. Ei mingit `getBoundingClientRect()`-i, ei mingeid `resize` sündmusekuulajaid, ei mingit JavaScripti. See on monumentaalne nihe imperatiivsest JavaScripti loogikast deklaratiivsele CSS-i lähenemisele.
Täielik, praktiline näide: kokkupõrkeid arvestav hüpikaken
Ehitame robustsema näite, mis ühendab ankurpositsioneerimise kaasaegse hüpikakna API-ga, et luua täisfunktsionaalne, ligipääsetav ja intelligentne kasutajaliidese komponent.
Samm 1: HTML-struktuur
Kasutame platvormi-omast `popover` atribuuti, mis annab meile tasuta olekuhalduse (avatud/suletud), kerge sulgemise funktsionaalsuse (väljaspool klõpsamine sulgeb selle) ja ligipääsetavuse eelised.
<button popovertarget="my-popover" id="popover-trigger">
Click Me
</button>
<div id="my-popover" popover>
<h3>Popover Title</h3>
<p>This popover will intelligently reposition itself to stay within the viewport. Try resizing your browser or scrolling the page!</p>
</div>
Samm 2: Ankru defineerimine
Määrame oma nupu ankruks. Lisame ka veidi põhistiili.
#popover-trigger {
/* See on võtmetähtsusega osa */
anchor-name: --popover-anchor;
/* Põhistiilid */
padding: 10px 20px;
font-size: 16px;
cursor: pointer;
}
Samm 3: `@position-try` valikute defineerimine
Nüüd loome oma positsioneerimisvalikute kaskaadi. Lisame igal juhul väikese `margin`'i, et luua hüpikakna ja päästiku vahele veidi ruumi.
/* Prioriteet 1: Positsioneerimine päästiku kohale */
@position-try --popover-top {
bottom: anchor(top, 8px);
left: anchor(center);
}
/* Prioriteet 2: Positsioneerimine päästiku alla */
@position-try --popover-bottom {
top: anchor(bottom, 8px);
left: anchor(center);
}
/* Prioriteet 3: Positsioneerimine paremale */
@position-try --popover-right {
left: anchor(right, 8px);
top: anchor(center);
}
/* Prioriteet 4: Positsioneerimine vasakule */
@position-try --popover-left {
right: anchor(left, 8px);
top: anchor(center);
}
Märkus: `anchor()` funktsioon võib võtta valikulise teise argumendi, mis toimib varuväärtusena. Siin kasutame aga ebastandardset süntaksit, et illustreerida potentsiaalset tulevast täiustust veeriste jaoks. Tänapäeval oleks õige viis kasutada `calc(anchor(top) - 8px)` või sarnast, kuid eesmärk on luua vahe.
Samm 4: Hüpikakna stiilimine ja varuvariandi rakendamine
Lõpuks stiilime oma hüpikakna ja ühendame kõik omavahel.
#my-popover {
/* Seo hüpikaken meie nimega ankur-elemendiga */
position-anchor: --popover-anchor;
/* Defineeri meie varuvariantide prioriteet */
position-fallback: --popover-top --popover-bottom --popover-right --popover-left;
/* Selle toimimiseks peame kasutama fikseeritud või absoluutset positsioneerimist */
position: absolute;
/* Vaikestiilid */
width: 250px;
border: 1px solid #ccc;
border-radius: 8px;
padding: 16px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
margin: 0; /* Hüpikakna API lisab vaikimisi veerise, me lähtestame selle */
}
/* Hüpikaken on peidetud, kuni see avatakse */
#my-popover:not(:popover-open) {
display: none;
}
Ja ongi kõik! Selle koodiga on teil täielikult toimiv hüpikaken, mis muudab automaatselt oma asukohta, et vältida ekraani servadega kärpimist. Positsioneerimisloogika jaoks pole vaja JavaScripti.
Täpsemad kontseptsioonid ja peenhäälestus
Ankurpositsioneerimise API pakub veelgi rohkem kontrolli keerukate stsenaariumide jaoks.
Süvitsi `anchor()` funktsioonist
`anchor()` funktsioon on uskumatult mitmekülgne. See ei puuduta ainult nelja serva. Saate sihtida ka protsente ankru suurusest.
- `anchor(left)` või `anchor(start)`: Ankru vasak serv.
- `anchor(right)` või `anchor(end)`: Ankru parem serv.
- `anchor(top)`: Ankru ülemine serv.
- `anchor(bottom)`: Ankru alumine serv.
- `anchor(center)`: Horisontaalne või vertikaalne kese, sõltuvalt kontekstist. `left` või `right` puhul on see horisontaalne kese. `top` või `bottom` puhul on see vertikaalne kese.
- `anchor(50%)`: Samaväärne `anchor(center)`-ga.
- `anchor(25%)`: Punkt, mis asub 25% ulatuses piki ankru telge.
Lisaks saate oma arvutustes kasutada ankru mõõtmeid `anchor-size()` funktsiooniga:
.element {
/* Muuda element poole laiemaks kui selle ankur */
width: calc(anchor-size(width) * 0.5);
}
Kaudsed ankrud
Mõnel juhul ei pea te isegi `anchor-name` ja `position-anchor` omadusi selgesõnaliselt defineerima. Teatud suhete puhul suudab brauser tuletada kaudse ankru. Kõige levinum näide on hüpikaken, mis kutsutakse esile `popovertarget` nupuga. Sel juhul saab nupust automaatselt hüpikakna kaudne ankur, mis lihtsustab teie CSS-i:
#my-popover {
/* `position-anchor` pole vajalik! */
position-fallback: --popover-top --popover-bottom;
...
}
See vähendab korduvat koodi ja muudab päästiku ja hüpikakna vahelise suhte veelgi otsesemaks.
Brauserite tugi ja edasine tee
2023. aasta lõpu seisuga on CSS-i ankurpositsioneerimise API eksperimentaalne tehnoloogia. See on saadaval Google Chrome'is ja Microsoft Edge'is funktsioonilipu taga (otsige "Experimental Web Platform features" aadressilt `chrome://flags`).
Kuigi see pole veel valmis tootmiskasutuseks kõigis brauserites, annab selle olemasolu suures brauserimootoris märku tugevast pühendumusest selle pikaajalise CSS-i probleemi lahendamisele. Arendajatel on ülioluline sellega katsetada, anda tagasisidet brauseritootjatele ja valmistuda tulevikuks, kus JavaScripti kasutamine elementide positsioneerimiseks muutub erandiks, mitte reegliks.
Selle kasutuselevõtu staatust saate jälgida platvormidel nagu "Can I use...". Praegu tuleks seda pidada progressiivse täiustamise tööriistaks. Saate oma kasutajaliidese ehitada `@position-try` abil ja kasutada `@supports` päringut, et pakkuda lihtsamat, mitte-pööratavat asukohta brauseritele, mis seda ei toeta, samal ajal kui kaasaegsete brauserite kasutajad saavad täiustatud kogemuse.
Kasutusjuhud peale hüpikakende
Selle API potentsiaalsed rakendused on laiaulatuslikud ja ulatuvad palju kaugemale lihtsatest tööriistavihjetest.
- Kohandatud valikumenüüd: Looge kauneid, kohandatud `
- Kontekstimenüüd: Positsioneerige kohandatud paremklõpsu menüü täpselt kursori asukoha või sihtelemendi kõrvale.
- Sissejuhatavad ringkäigud: Juhendage kasutajaid läbi oma rakenduse, ankurdades õpetuse sammud konkreetsete kasutajaliidese elementide külge, mida nad kirjeldavad.
- Rikastekstiredaktorid: Positsioneerige vormindusribad valitud teksti kohale või alla.
- Keerukad armatuurlauad: Kuvage üksikasjalikke teabekaarte, kui kasutaja interakteerub andmepunktiga diagrammil või graafikul.
Kokkuvõte: deklaratiivne tulevik dünaamilistele paigutustele
CSS `@position-try` ja laiem ankurpositsioneerimise API kujutavad endast fundamentaalset nihet selles, kuidas me läheneme kasutajaliidese arendamisele. Nad viivad keeruka, imperatiivse positsioneerimisloogika JavaScriptist sobivamasse, deklaratiivsesse koju CSS-is.
Eelised on selged:
- Vähendatud keerukus: Pole enam vaja käsitsi arvutusi ega keerukaid JavaScripti teeke positsioneerimiseks.
- Parem jõudlus: Brauseri optimeeritud renderdusmootor tegeleb positsioneerimisega, mis tagab sujuvama jõudluse kui skriptipõhised lahendused.
- Vastupidavamad kasutajaliidesed: Paigutused kohanduvad automaatselt erinevate ekraanisuuruste ja sisu muutustega ilma lisakoodita.
- Puhtamad koodibaasid: Ülesannete lahusus on parem, kuna stiili- ja paigutusloogika asub täielikult CSS-is.
Samal ajal kui ootame laialdast brauserituge, on praegu aeg õppida, katsetada ja toetada neid võimsaid uusi tööriistu. Võttes omaks `@position-try`, astume tulevikku, kus veebiplatvorm ise pakub elegantseid lahendusi meie kõige levinumatele ja masendavamatele paigutuse väljakutsetele.