Nel tutorial di oggi, useremo un po 'di CSS e JavaScript per creare un effetto hover del menu di fantasia. Non è un risultato finale complicato, tuttavia costruirlo sarà una grande opportunità per mettere in pratica le nostre competenze front-end.
Senza ulteriori intro, diamo un'occhiata a cosa costruiremo:
Iniziamo con un markup molto semplice; un nav
elemento che contiene il menu e un vuoto campata
elemento:
Con la marcatura pronta, successivamente specifichiamo alcuni stili di base per gli elementi correlati:
.mynav ul display: flex; justify-content: center; flex-wrap: wrap; list-style-type: none; padding: 0; .mynav li: not (: last-child) margin-right: 20px; .mynav a display: block; font-size: 20px; colore nero; decorazione del testo: nessuna; imbottitura: 7px 15px; .target position: absolute; border-bottom: 4px solid transparent; z-index: -1; transform: translateX (-60px); .mynav a, .target transition: all .35s easy-in-out;
Si noti che il campata
elemento (.bersaglio
) È assolutamente posizionato. Come vedremo tra un momento, utilizzeremo JavaScript per determinare la sua posizione esatta. Inoltre, dovrebbe apparire dietro a i collegamenti del menu, quindi diamo un negativo z-index
.
A questo punto, concentriamo la nostra attenzione sul JavaScript richiesto. Per cominciare, miriamo agli elementi desiderati. Definiamo anche una serie di colori che useremo in seguito.
const target = document.querySelector (". target"); const links = document.querySelectorAll (". mynav a"); const colors = ["deepskyblue", "orange", "firebrick", "gold", "magenta", "black", "darkblue"];
Quindi ascoltiamo per il clic
e MouseEnter
eventi dei collegamenti del menu.
Quando il clic
evento accade, impediamo alla pagina di ricaricarsi. Naturalmente, questo funziona nel nostro caso perché tutti i link hanno un vuoto href
attributo. In un progetto reale, tuttavia, ognuno dei collegamenti del menu aprirebbe probabilmente una pagina diversa.
Soprattutto, non appena il MouseEnter
fuochi di eventi, il mouseenterFunc
la funzione di callback è eseguita:
for (let i = 0; i < links.length; i++) links[i].addEventListener("click", (e) => e.preventDefault ()); link [i] .addEventListener ("mouseenter", mouseenterFunc);
Il corpo del mouseenterFunc
la funzione si presenta così:
function mouseenterFunc () for (lascia che 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";
All'interno di questa funzione facciamo quanto segue:
attivo
classe al genitore immediato (Li
) del link di destinazione.opacità
da tutti i collegamenti dei menu, a parte quello "attivo".getBoundingClientRect
metodo per recuperare la dimensione del collegamento associato e la sua posizione rispetto al viewport. colore del bordo
proprietà del campata
elemento. Ricorda, il suo valore di proprietà iniziale è impostato su trasparente
.getBoundingClientRect
metodo alle proprietà corrispondenti del campata
elemento. In altre parole, il campata
il tag eredita la dimensione e la posizione del link su cui si trova il passaggio del mouse.campata
elemento. Questo comportamento è importante solo la prima volta che passiamo il mouse su un link. In questo caso, la trasformazione dell'elemento va da trasformare: translateX (-60px)
a trasformare: nessuno
. Questo ci dà un buon effetto slide-in.È importante notare che il codice sopra riportato viene eseguito ogni volta che si passa il mouse su un collegamento. Funziona quindi quando si passa con il mouse su un collegamento "attivo". Per evitare questo comportamento, avvolgiamo il codice sopra all'interno di Se
dichiarazione:
function mouseenterFunc () if (! this.parentNode.classList.contains ("active")) // code here
Finora, la nostra demo ha il seguente aspetto:
Quindi, tutto sembra funzionare come previsto, giusto? Bene, non è vero perché se scorriamo la pagina, o ridimensioniamo il viewport, e poi proviamo a selezionare un collegamento, le cose si complicano. In particolare, la posizione del campata
l'elemento diventa errato.
Gioca con la demo della pagina completa (assicurati di aver aggiunto abbastanza contenuti fittizi) per vedere cosa intendo.
Per risolverlo, dobbiamo calcolare fino a che punto siamo scorsi dalla parte superiore della finestra e aggiungere questo valore alla corrente superiore
valore dell'elemento obiettivo. Allo stesso modo dovremmo calcolare fino a che punto il documento è stato scostato orizzontalmente (per ogni evenienza). Il valore risultante viene aggiunto alla corrente sinistra
valore dell'elemento obiettivo.
Ecco le due righe di codice che aggiorniamo:
const left = this.getBoundingClientRect (). left + window.pageXOffset; const top = this.getBoundingClientRect (). top + window.pageYOffset;
Tieni presente che tutto il codice sopra riportato viene eseguito non appena il browser elabora il DOM e trova lo script pertinente. Ancora una volta, per le tue implementazioni e i tuoi progetti potresti voler eseguire questo codice quando la pagina viene caricata, o qualcosa del genere. In uno scenario del genere, dovrai incorporarlo all'interno di un gestore di eventi (ad es. caricare
gestore di eventi).
L'ultima cosa che dobbiamo fare è assicurarci che l'effetto funzioni ancora mentre ridimensioniamo la finestra del browser. Per realizzare ciò, ascoltiamo il ridimensionare
evento e registrare il resizeFunc
gestore di eventi.
window.addEventListener ("ridimensiona", resizeFunc);
Ecco il corpo di questo gestore:
function resizeFunc () const active = document.querySelector (". mynav li.active"); if (attivo) const left = active.getBoundingClientRect (). left + window.pageXOffset; const top = active.getBoundingClientRect (). top + window.pageYOffset; target.style.left = '$ left px'; target.style.top = '$ top px';
All'interno della funzione sopra, facciamo quanto segue:
attivo
. Se ci è un tale elemento, che afferma che abbiamo già passato il tempo sopra un link.sinistra
e superiore
proprietà dell'elemento "attivo" insieme alle relative proprietà della finestra e assegnarle a campata
elemento. Si noti che recuperiamo i valori solo per le proprietà che cambiano durante il ridimensionare
evento. Ciò significa che non è necessario ricalcolare la larghezza e l'altezza dei collegamenti del menu.La demo funziona bene in tutti i browser recenti. Se riscontri dei problemi, fammelo sapere nei commenti qui sotto. Inoltre, come forse avrete notato, usiamo Babel per compilare il nostro codice ES6 fino a ES5.
In questo tutorial abbiamo esaminato il processo di creazione di un effetto hover di menu semplice ma interessante.
Spero vi sia piaciuto ciò che abbiamo costruito qui e ci siamo ispirati per sviluppare effetti di menu ancora più potenti come quello che appare (al momento della scrittura) nel sito Stripe.
Hai mai creato qualcosa di simile? Se è così, assicurati di condividere con noi le sfide che hai affrontato.