Neseniai aptikome seną „jQuery“ pamoką, demonstruojančią „slankiojančio paryškinimo“ naršymo juostą, ir nusprendėme, kad šiai koncepcijai reikia modernaus atnaujinimo. Naudojant šį modelį, rėmelis aplink aktyvų naršymo elementą animuojasi tiesiogiai nuo vieno elemento prie kito, kai vartotojas spusteli meniu punktus. 2025 metais turime daug geresnių įrankių DOM manipuliavimui naudojant gryną „JavaScript“. Naujos funkcijos, tokios kaip „View Transition“ API, leidžia lengviau pasiekti laipsnišką tobulinimą (angl. progressive enhancement) ir pasirūpina daugybe animacijos smulkmenų.

Šioje pamokoje pademonstruosime du metodus, kaip sukurti „slankiojančio paryškinimo“ naršymo juostą naudojant gryną „JavaScript“ ir CSS. Pirmasis pavyzdys naudoja getBoundingClientRect
metodą, kad aiškiai animuotų rėmelį tarp naršymo juostos elementų, kai jie yra paspaudžiami. Antrasis pavyzdys pasiekia tą patį funkcionalumą naudojant naująjį „View Transition“ API.
Pradinis žymėjimas
Tarkime, kad turime vieno puslapio programą (SPA), kurioje turinys keičiasi neperkraunant puslapio. Pradinis HTML ir CSS yra standartinė naršymo juosta su papildomu div
elementu, turinčiu id
#highlight
. Pirmajam naršymo elementui suteikiame klasę .active
.
(Žr. CodePen Moving Highlight Navbar Starting Markup)
Šiai versijai mes išdėstysime #highlight
elementą aplink elementą su .active
klase, kad sukurtume rėmelį. Galime pasinaudoti absoliučiu pozicionavimu ir animuoti elementą per naršymo juostą, kad pasiektume norimą efektą. Iš pradžių jį paslėpsime už ekrano ribų, pridėdami left: -200px
, ir įtrauksime transition
stilius visoms savybėms, kad bet kokie elemento padėties ir dydžio pokyčiai vyktų palaipsniui.
#highlight {
z-index: 0;
position: absolute;
height: 100%;
width: 100px;
left: -200px;
border: 2px solid green;
box-sizing: border-box;
transition: all 0.2s ease;
}
Pridėkite standartinį įvykio apdorotoją paspaudimų sąveikoms
Norime, kad paryškinimo elementas animuotųsi, kai vartotojas pakeičia .active
naršymo elementą. Pridėkime click
įvykio apdorotoją prie nav
elemento, tada filtruokime tik tuos įvykius, kuriuos sukėlė elementai, atitinkantys mūsų norimą selektorių. Šiuo atveju norime pakeisti .active
naršymo elementą tik tada, kai vartotojas spusteli nuorodą, kuri dar neturi .active
klasės.
Iš pradžių galime iškviesti console.log
, kad įsitikintume, jog apdorotojas suveikia tik tada, kai tikimasi:
const navbar = document.querySelector('nav');
navbar.addEventListener('click', function (event) {
// grįžti, jei paspaustas elementas neatitinka teisingo selektoriaus
if (!event.target.matches('nav a:not(active)')) {
return;
}
console.log('click');
});
Atidarykite savo naršyklės konsolę ir pabandykite spustelėti skirtingus naršymo juostos elementus. Turėtumėte matyti, kad „click“ yra registruojamas tik tada, kai pasirenkate naują naršymo juostos elementą.
Dabar, kai žinome, kad mūsų įvykio apdorotojas veikia su teisingais elementais, pridėkime kodą, kuris perkels .active
klasę į paspaustą naršymo elementą. Galime naudoti į įvykio apdorotoją perduotą objektą, kad rastume elementą, kuris inicijavo įvykį, ir suteiktume tam elementui klasę .active
, prieš tai pašalinę ją iš anksčiau aktyvaus elemento.
const navbar = document.querySelector('nav');
navbar.addEventListener('click', function (event) {
// grįžti, jei paspaustas elementas neatitinka teisingo selektoriaus
if (!event.target.matches('nav a:not(active)')) {
return;
}
- console.log('click');
+ document.querySelector('nav a.active').classList.remove('active');
+ event.target.classList.add('active');
});
Mūsų #highlight
elementas turi judėti per naršymo juostą ir pozicionuotis aplink aktyvų elementą. Parašykime funkciją, kuri apskaičiuos naują padėtį ir plotį. Kadangi #highlight
selektoriui pritaikyti transition
stiliai, jis judės palaipsniui, kai pasikeis jo padėtis.
Naudodami getBoundingClientRect
, galime gauti informaciją apie elemento padėtį ir dydį. Apskaičiuojame aktyvaus naršymo elemento plotį ir jo poslinkį nuo tėvinio elemento kairiosios ribos. Tada priskiriame stilius paryškinimo elementui, kad jo dydis ir padėtis sutaptų.
// apdorotojas paryškinimo judėjimui
const moveHighlight = () => {
const activeNavItem = document.querySelector('a.active');
const highlighterElement = document.querySelector('#highlight');
const width = activeNavItem.offsetWidth;
const itemPos = activeNavItem.getBoundingClientRect();
const navbarPos = navbar.getBoundingClientRect()
const relativePosX = itemPos.left - navbarPos.left;
const styles = {
left: `${relativePosX}px`,
width: `${width}px`,
};
Object.assign(highlighterElement.style, styles);
}
Iškvieskime mūsų naują funkciją, kai suveikia paspaudimo įvykis:
navbar.addEventListener('click', function (event) {
// grįžti, jei paspaustas elementas neatitinka teisingo selektoriaus
if (!event.target.matches('nav a:not(active)')) {
return;
}
document.querySelector('nav a.active').classList.remove('active');
event.target.classList.add('active');
+ moveHighlight();
});
Galiausiai, iškvieskime funkciją iškart, kad rėmelis atsirastų už mūsų pradinio aktyvaus elemento, kai puslapis pirmą kartą įkeliamas:
// apdorotojas paryškinimo judėjimui
const moveHighlight = () => {
// ...
}
// rodyti paryškinimą, kai puslapis įkeliamas
moveHighlight();
Dabar rėmelis juda per naršymo juostą, kai pasirenkamas naujas elementas. Pabandykite spustelėti skirtingas naršymo nuorodas, kad animuotumėte naršymo juostą.
(Žr. CodePen Moving Highlight Navbar)
Tam prireikė vos kelių eilučių gryno „JavaScript“ ir tai galima lengvai išplėsti, kad būtų atsižvelgta į kitas sąveikas, pavyzdžiui, mouseover
įvykius. Kitoje dalyje išnagrinėsime, kaip pertvarkyti šią funkciją naudojant „View Transition“ API.
„View Transition“ API naudojimas
„View Transition“ API suteikia funkcionalumą kurti animuotus perėjimus tarp svetainės vaizdų. Po gaubtu API sukuria „prieš“ ir „po“ vaizdų momentines nuotraukas ir tada tvarko perėjimą tarp jų. Vaizdų perėjimai yra naudingi kuriant animacijas tarp dokumentų, suteikiant įgimtos programėlės tipo vartotojo patirtį, būdingą tokiems karkasams kaip Astro. Tačiau API taip pat suteikia apdorotojus, skirtus SPA stiliaus programoms. Mes jį naudosime, kad sumažintume reikalingo „JavaScript“ kiekį ir lengviau sukurtume atsarginį funkcionalumą.
Šiam metodui mums nebereikia atskiro #highlight
elemento. Vietoj to, galime stilizuoti .active
naršymo elementą tiesiogiai, naudojant pseudo-selektorius, ir leisti „View Transition“ API tvarkyti animaciją tarp „prieš“ ir „po“ vartotojo sąsajos būsenų, kai spustelimas naujas naršymo elementas.
Pradėsime atsikratydami #highlight
elemento ir su juo susijusio CSS, pakeisdami jį stiliais nav a::after
pseudo-selektoriui:
<nav>
- <div id="highlight"></div>
<a href="#" class="active">Home</a>
<a href="#services">Services</a>
<a href="#about">About</a>
<a href="#contact">Contact</a>
</nav>
- #highlight {
- z-index: 0;
- position: absolute;
- height: 100%;
- width: 0;
- left: 0;
- box-sizing: border-box;
- transition: all 0.2s ease;
- }
+ nav a::after {
+ content: " ";
+ position: absolute;
+ left: 0;
+ top: 0;
+ width: 100%;
+ height: 100%;
+ border: none;
+ box-sizing: border-box;
+ }
.active
klasei įtraukiame view-transition-name
savybę, taip atrakindami „View Transition“ API magiją. Kai tik suaktyvinsime vaizdo perėjimą ir pakeisime .active
naršymo elemento vietą DOM, bus padarytos „prieš“ ir „po“ momentinės nuotraukos, o naršyklė animuos rėmelį per juostą. Savo vaizdo perėjimui suteiksime pavadinimą highlight
, bet teoriškai galėtume suteikti bet kokį pavadinimą.
nav a.active::after {
border: 2px solid green;
view-transition-name: highlight;
}
Kai turime selektorių, kuriame yra view-transition-name
savybė, vienintelis likęs žingsnis yra suaktyvinti perėjimą naudojant startViewTransition
metodą ir perduoti atgalinio iškvietimo (angl. callback) funkciją.
const navbar = document.querySelector('nav');
// Pakeisti aktyvų naršymo elementą paspaudus
navbar.addEventListener('click', async function (event) {
if (!event.target.matches('nav a:not(.active)')) {
return;
}
document.startViewTransition(() => {
document.querySelector('nav a.active').classList.remove('active');
event.target.classList.add('active');
});
});
Aukščiau pateikta atnaujinta click
apdorotojo versija. Užuot patys atlikę visus judančio rėmelio dydžio ir padėties skaičiavimus, „View Transition“ API viską padaro už mus. Mums tereikia iškviesti document.startViewTransition
ir perduoti atgalinio iškvietimo funkciją, kuri pakeis elementą, turintį .active
klasę!
Vaizdo perėjimo koregavimas
Šiame etape, spustelėjus naršymo nuorodą, pastebėsite, kad perėjimas veikia, tačiau matomos keistos dydžio problemos.

Šį dydžio neatitikimą sukelia kraštinių santykio (angl. aspect ratio) pokyčiai vaizdo perėjimo metu. Čia nesigilinsime, bet Jake Archibald turi išsamų paaiškinimą, kurį galite perskaityti, norėdami gauti daugiau informacijos. Trumpai tariant, norėdami užtikrinti, kad rėmelio aukštis išliktų vienodas per visą perėjimą, turime deklaruoti aiškų height
::view-transition-old
ir ::view-transition-new
pseudo-selektoriams, kurie atitinkamai atspindi statinę senojo ir naujojo vaizdo momentinę nuotrauką.
::view-transition-old(highlight) {
height: 100%;
}
::view-transition-new(highlight) {
height: 100%;
}
Atlikime galutinį kodo pertvarkymą, kad sutvarkytume kodą, perkeldami atgalinio iškvietimo funkciją į atskirą funkciją ir pridėdami atsarginį variantą, kai vaizdo perėjimai nėra palaikomi:
const navbar = document.querySelector('nav');
// pakeisti elementą, kuriam pritaikyta .active klasė
const setActiveElement = (elem) => {
document.querySelector('nav a.active').classList.remove('active');
elem.classList.add('active');
}
// Pradėti vaizdo perėjimą ir perduoti atgalinio iškvietimo funkciją paspaudus
navbar.addEventListener('click', async function (event) {
if (!event.target.matches('nav a:not(.active)')) {
return;
}
// Atsarginis variantas naršyklėms, kurios nepalaiko View Transitions:
if (!document.startViewTransition) {
setActiveElement(event.target);
return;
}
document.startViewTransition(() => setActiveElement(event.target));
});
Štai mūsų „View Transition“ pagrindu veikianti naršymo juosta! Stebėkite sklandų perėjimą, kai spustelite skirtingas nuorodas.
(Žr. CodePen Moving Highlight Navbar with View Transition)
Išvada
Anksčiau animacijoms ir perėjimams tarp svetainės vartotojo sąsajos būsenų reikėjo daug kilobaitų išorinių bibliotekų, kartu su išsamiu, painiu ir klaidų kupinu kodu, tačiau nuo to laiko grynas „JavaScript“ ir CSS įtraukė funkcijas, leidžiančias pasiekti įgimtos programėlės tipo sąveikas be didelių išlaidų. Mes tai pademonstravome, įgyvendindami „slankiojančio paryškinimo“ naršymo modelį dviem būdais: CSS perėjimais, derinant su getBoundingClientRect()
metodu, ir „View Transition“ API.