Slik bygger du en skiftende understreke-svingeffekt med CSS og JavaScript

I dagens veiledning skal vi bruke en liten bit av CSS og JavaScript for å lage en fancy meny-hover-effekt. Det er ikke et komplisert sluttresultat, men å bygge det vil være en flott mulighet til å øve våre ferdigheter.

Uten ytterligere intro, la oss sjekke ut hva vi skal bygge:

The Markup

Vi starter med noen veldig grunnleggende oppslag; en nav element som inneholder menyen og en tom span element:

 

CSS

Med markup klar, neste vi spesifiserer noen grunnleggende stiler for de relaterte elementene:

.mynav ul display: flex; begrunn-innhold: center; flex-wrap: wrap; liste-stil-type: none; polstring: 0;  .mynav li: ikke (: siste barn) margin-right: 20px;  .mynav a display: block; skriftstørrelse: 20px; farge svart; tekst-dekorasjon: ingen; polstring: 7px 15px;  .target posisjon: absolutt; grensebunn: 4px solid gjennomsiktig; z-indeks: -1; transformere: translateX (-60px);  .mynav a, .target overgang: alle .35s brukervennlighet; 

Legg merke til at span element (.mål) Er helt posisjonert. Som vi ser om et øyeblikk, bruker vi JavaScript til å bestemme sin eksakte posisjon. I tillegg bør det vises bak menyen kobler, så vi gir det en negativ z-indeks.

JavaScript

På dette punktet, la oss fokusere vår oppmerksomhet på det nødvendige JavaScript. Til å begynne med målretter vi mot de ønskede elementene. Vi definerer også en rekke farger som vi vil bruke senere.

const target = document.querySelector (". target"); const links = document.querySelectorAll (".mynav a"); const colors = ["deepskyblue", "orange", "firebrick", "gold", "magenta", "black", "darkblue");

arrangementer

Neste lytter vi etter klikk og mouseenter hendelser i menykoblingene. 

Når klikk Hendelsen skjer, vi forhindrer at siden lastes ned. Selvfølgelig virker dette i vårt tilfelle fordi alle koblinger har en tom href Egenskap. I et ekte prosjekt vil imidlertid hver menykobling sannsynligvis åpne en annen side.  

Viktigst, så snart som mouseenter hendelsesbranner, mouseenterFunc tilbakeringingsfunksjon utføres:

for (la jeg = 0; jeg < links.length; i++)  links[i].addEventListener("click", (e) => e.preventDefault ()); lenker [i] .addEventListener ("mouseenter", mouseenterFunc); 

mouseenterFunc

Kroppen til mouseenterFunc funksjonen ser slik ut:

funksjon mouseenterFunc () for (la i = 0; jeg < 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"; 

Inne i denne funksjonen gjør vi følgende:

  1. Legg til aktiv klasse til nærmeste forelder (li) av mållinken.
  2. Reduser opasitet fra alle menykoblinger, bortsett fra den "aktive" en.
  3. Bruke getBoundingClientRect metode for å hente størrelsen på den tilknyttede lenken og dens posisjon i forhold til visningsporten. 
  4. Få en tilfeldig farge fra ovennevnte array og send den som verdi til grensefarge eiendom av span element. Husk at den opprinnelige eiendomsverdien er satt til gjennomsiktig.
  5. Tilordne verdiene hentet fra getBoundingClientRect metode til de tilsvarende egenskapene til span element. Med andre ord, span tag arver størrelsen og posisjonen til lenken som hovered over.
  6. Tilbakestill standardtransformasjonen som ble brukt på span element. Denne oppførselen er bare viktig første gang vi svinger over en lenke. I dette tilfellet går transformasjonen av elementet fra transformere: translateX (-60px) til transformere: ingen. Det gir oss en fin lysbildeffekt.

Hvis aktiv

Det er viktig å merke seg at koden ovenfor blir utført hver gang vi svinger over en lenke. Det kjører derfor når vi svinger over en "aktiv" kobling også. For å forhindre denne oppførselen, pakker vi inn koden ovenfor inne i en hvis uttalelse:

funksjon mouseenterFunc () hvis (! this.parentNode.classList.contains ("active")) // kode her

Så langt ser vår demo ut som følger:

Nesten, men ikke helt

Så, alt ser ut til å fungere som forventet, ikke sant? Vel, det er ikke sant fordi hvis vi rulle gjennom siden, eller endre størrelsen på visningsporten, og deretter prøve å velge en kobling, blir ting rotete. Spesielt posisjonen til span elementet blir feil.

Spille rundt med demonstrasjonen på hele siden (sørg for at du har lagt til nok dummyinnhold) for å se hva jeg mener.

For å løse det må vi beregne hvor langt vi har rullet fra toppen av vinduet og legg til denne verdien til gjeldende topp verdien av målelementet. På samme måte skal vi beregne hvor langt dokumentet er rullet horisontalt (bare i tilfelle). Den resulterende verdien legges til gjeldende venstre verdien av målelementet.

Her er de to kodelinjene som vi oppdaterer:

const left = this.getBoundingClientRect (). left + window.pageXOffset; const top = this.getBoundingClientRect (). toppen + window.pageYOffset;

Husk at hele koden ovenfor blir utført så snart nettleseren behandler DOM og finner det aktuelle skriptet. Igjen, for dine egne implementeringer og design, vil du kanskje kjøre denne koden når siden lastes, eller noe sånt. I et slikt scenario må du legge det inn i en hendelseshandler (f.eks. laste hendelsehandler).

view

Det siste vi må gjøre er å sikre at effekten fortsatt fungerer når vi endrer størrelsen på nettleservinduet. For å oppnå dette, lytter vi etter endre størrelse på hendelse og registrer resizeFunc hendelse handler.

window.addEventListener ("resize", resizeFunc);

Her er kroppen til denne handleren:

funksjon resizeFunc () const active = document.querySelector (".mynav li.active"); hvis (aktiv) const left = active.getBoundingClientRect (). left + window.pageXOffset; const top = active.getBoundingClientRect (). toppen + window.pageYOffset; target.style.left = '$ left px'; target.style.top = '$ top px'; 

Innenfor funksjonen ovenfor gjør vi følgende:

  1. Sjekk om det finnes et menyliste med klassen aktiv. Hvis det er er Et slikt element, som sier at vi allerede har svevet over en lenke.
  2.  Få den nye venstre og topp egenskaper av det "aktive" elementet sammen med tilhørende vinduegenskaper og tilordne dem til span element. Vær oppmerksom på at vi bare henter verdiene for egenskapene som endres under endre størrelse på begivenhet. Det betyr at det ikke er nødvendig å beregne bredden og høyden på menykoblingene.

Nettleserstøtte

Demoen fungerer bra i alle nyere nettlesere. Hvis du støter på noen problemer, vennligst gi meg beskjed i kommentarene nedenfor. Også, som du kanskje har lagt merke til, bruker vi Babel til å kompilere ES6-koden ned til ES5.

Konklusjon

I denne opplæringen gikk vi gjennom prosessen med å skape en enkel, men likevel interessant meny-hover-effekt.

Jeg håper du likte det vi bygde her og tok inspirasjon for å utvikle enda kraftigere menyeffekter som den som vises (på skrivingstidspunktet) i Stripesiden.

Har du noen gang opprettet noe lignende? I så fall må du dele med oss ​​de utfordringene du møtte.