In de tutorial van vandaag gaan we een beetje CSS en JavaScript gebruiken om een chique menu-hovereffect te creëren. Het is geen gecompliceerd eindresultaat, maar het is een geweldige kans om onze front-endvaardigheden te oefenen.
Zonder verdere intro, laten we eens kijken wat we gaan bouwen:
We beginnen met een paar heel eenvoudige markeringen; een nav
element dat het menu bevat en een leeg element span
element:
Nu de markup klaar is, specificeren we enkele basisstijlen voor de gerelateerde elementen:
.mynav ul display: flex; justify-content: center; flex-wrap: wrap; list-style-type: none; opvulling: 0; .mynav li: not (: last-child) margin-right: 20px; .mynav a display: block; lettertypegrootte: 20px; de kleur zwart; tekstdecoratie: geen; opvulling: 7px 15px; .target positie: absoluut; border-bottom: 4px solid transparant; z-index: -1; transform: translateX (-60px); .mynav a, .target transition: all .35s ease-in-out;
Merk op dat de span
element (.doelwit
) Is absoluut gepositioneerd. Zoals we zo meteen zullen zien, zullen we JavaScript gebruiken om de exacte positie te bepalen. Bovendien zou het moeten verschijnen achter de menulinks, dus we geven het een negatief z-index
.
Laten we op dit punt onze aandacht richten op het vereiste JavaScript. Om te beginnen richten we ons op de gewenste elementen. We definiëren ook een reeks kleuren die we later zullen gebruiken.
const target = document.querySelector (". target"); const links = document.querySelectorAll (". mynav a"); const colors = ["deepskyblue", "orange", "firebrick", "gold", "magenta", "black", "darkblue"];
Vervolgens luisteren we naar de Klik
en MouseEnter
evenementen van de menulinks.
Wanneer de Klik
er gebeurt een gebeurtenis, we voorkomen dat de pagina opnieuw wordt geladen. Dit werkt in ons geval natuurlijk omdat alle links leeg zijn href
attribuut. In een echt project zou echter elk van de menulinks waarschijnlijk een andere pagina openen.
Belangrijker nog, zodra de MouseEnter
evenementbranden, de mouseenterFunc
callback-functie wordt uitgevoerd:
for (let i = 0; i < links.length; i++) links[i].addEventListener("click", (e) => e.preventDefault ()); links [i] .addEventListener ("mouseenter", mouseenterFunc);
Het lichaam van de mouseenterFunc
functie ziet er als volgt uit:
function mouseenterFunc () for (let i = 0; i < links.length; i++) if (links[i].parentNode.classList.contains("active")) links[i].parentNode.classList.remove("active"); links[i].style.opacity = "0.25"; this.parentNode.classList.add("active"); this.style.opacity = "1"; const width = this.getBoundingClientRect().width; const height = this.getBoundingClientRect().height; const left = this.getBoundingClientRect().left; const top = this.getBoundingClientRect().top; const color = colors[Math.floor(Math.random() * colors.length)]; target.style.width = '$widthpx'; target.style.height = '$heightpx'; target.style.left = '$leftpx'; target.style.top = '$toppx'; target.style.borderColor = color; target.style.transform = "none";
Binnen deze functie doen we het volgende:
actief
klasse aan de directe ouder (li
) van de doellink.ondoorzichtigheid
van alle menulinks, behalve de "actieve".getBoundingClientRect
methode om de grootte van de bijbehorende link op te halen en de positie ervan ten opzichte van de viewport. rand kleur
eigendom van de span
element. Onthoud dat de beginwaarde van de eigenschap is ingesteld op transparant
.getBoundingClientRect
methode om de overeenkomstige eigenschappen van de span
element. Met andere woorden, de span
tag erft de grootte en de positie van de link waarop de muisaanwijzer staat.span
element. Dit gedrag is alleen belangrijk als we de eerste keer over een link gaan. In dit geval gaat de transformatie van het element van transformeren: translateX (-60px)
naar transformeren: geen
. Dat geeft ons een leuk slide-in effect.Het is belangrijk om te weten dat bovenstaande code telkens wordt uitgevoerd als we de muisaanwijzer over een link plaatsen. Het werkt dus ook als we over een "actieve" link zweven. Om dit gedrag te voorkomen, verpakken we de code hierboven in een als
uitspraak:
function mouseenterFunc () if (! this.parentNode.classList.contains ("active")) // code here
Tot nu toe ziet onze demo er als volgt uit:
Dus alles lijkt te werken zoals verwacht, toch? Nou, dat is niet waar, want als we door de pagina scrollen of het formaat van de viewport wijzigen en vervolgens een link proberen te selecteren, worden de zaken rommelig. Specifiek, de positie van de span
element wordt onjuist.
Speel rond met de demo van de volledige pagina (zorg ervoor dat je genoeg dummy-inhoud hebt toegevoegd) om te zien wat ik bedoel.
Om dit op te lossen, moeten we berekenen tot hoever we hebben gescrold vanaf de bovenkant van het venster en deze waarde toevoegen aan de huidige top
waarde van het doelelement. Op dezelfde manier moeten we berekenen hoe ver het document horizontaal is geschoven (voor het geval dat). De resulterende waarde wordt toegevoegd aan de stroom links
waarde van het doelelement.
Dit zijn de twee coderegels die we updaten:
const left = this.getBoundingClientRect (). left + window.pageXOffset; const top = this.getBoundingClientRect (). top + window.pageYOffset;
Houd er rekening mee dat alle bovenstaande code wordt uitgevoerd zodra de browser de DOM verwerkt en het relevante script vindt. Nogmaals, voor uw eigen implementaties en ontwerpen wilt u misschien deze code uitvoeren wanneer de pagina wordt geladen, of iets dergelijks. In een dergelijk scenario moet u het insluiten in een gebeurtenishandler (bijv. laden
event handler).
Het laatste wat we moeten doen is zorgen dat het effect nog steeds werkt als we het formaat van het browservenster aanpassen. Om dit te bereiken, luisteren we naar de verkleinen
evenement en registreer het resizeFunc
gebeurtenishandler.
window.addEventListener ("resize", resizeFunc);
Dit is het lichaam van deze handler:
function resizeFunc () const active = document.querySelector (". mynav li.active"); if (actief) const left = active.getBoundingClientRect (). left + window.pageXOffset; const top = active.getBoundingClientRect (). top + window.pageYOffset; target.style.left = '$ left px'; target.style.top = '$ top px';
Binnen de bovenstaande functie doen we het volgende:
actief
. Als er is een dergelijk element dat beweert dat we al boven een link zweven.links
en top
eigenschappen van het "actieve" item samen met de gerelateerde venstereigenschappen en wijs ze toe aan de span
element. Merk op dat we de waarden alleen ophalen voor de eigenschappen die tijdens de verkleinen
evenement. Dat betekent dat het niet nodig is om de breedte en hoogte van de menulinks te herberekenen.De demo werkt goed in alle recente browsers. Als je echter problemen tegenkomt, laat het me weten in de reacties hieronder. Zoals je misschien hebt gemerkt, gebruiken we Babel om onze ES6-code te compileren naar ES5.
In deze zelfstudie hebben we het proces doorlopen van het maken van een eenvoudig, maar toch interessant menu-hovereffect.
Ik hoop dat je genoten hebt van wat we hier hebben gebouwd en heb inspiratie opgedaan voor het ontwikkelen van nog krachtiger menu-effecten zoals die verschijnen (op het moment van schrijven) in de Stripe-site.
Heb je ooit iets soortgelijks gemaakt? Als dat het geval is, deel dan de uitdagingen die je tegenkwam met ons.