Hvem er ikke vild med et rolling banner (aka marquee banner)? Måske nogen af jer tænker hvad er det? Se toppen af sitet, lige under hero unit'en. Der har jeg lavet et:-)
Et rolling banner kan laves relativt nemt med lidt html, et par keyframe animationer og lidt css/tailwind. Først html'en: I dette eksempel er html'en placeret i Header.astro-filen, da den er en del af Hero unit'en. Men den kan placeres hvor du ønsker det:
For at få banneret til at scrolle i uendelighed, skal indholdet i banneret laves to gange, og derefter animeres: Derfor er der to <div>'er, der er ens.
De to <div>'er er pakket ind i en ydre <section>, der definerer bannerets udseende (farver mm.). Dertil har den egenskaben "whitespace-nowrap," som gør at de to <div>'er' placeres efter hinanden i stedet for oven på hinanden.
Første <div> er den, der er på skærmen til at starte med. Den scroller mod venstre ved hjælp af animate-infinite-scroll animationen.
[&_span]:mx-6 er en lille genvej: Den tilføjer mx-6 class'en på alle de child <span> elementer, der er i <div>'en.
Anden <div> identisk med den første, men fordi den ligger efter den første pga. "whitespace-nowrap", er den til at starte med skubbet ud af skærmen. Den animererer (også) fra langt ude i højre side, og ind i skærmen, ved hjælp af animate-infinite-scroll animationen.
aria-hidden="true" skjuler <div> nr. 2 for skærmlæsere/robotter
Dernæst animate-infinite-scroll-animationen: Den tilføjes og tilpasses via tailwind.css i @theme sektionen:
@theme { /*Infinite scroll animation*/ --animate-infinite-scroll: infinite-scroll 25s linear infinite; @keyframes infinite-scroll { from { transform: translateX(0);} to { transform: translateX(-100%);} } }
infinite-scroll animerer indholdet, fra dets aktuelle startposition, og 100% mod venstre, ud af skærmen (-100%).
OBS! Det er vigtigt at indholdet af de <div>'en er længere end containeren, de skal udfylde!
Lydeffekter
Det er ret nemt at lave lydeffekter på et website, specielt når alpine.js kan bruges til det.
Filerne ligger i forskellige formater – sørg for at konvertere til mp3. Det kan du gøre ved hjælp af Adobe Media Encoder eller online på f.eks. https://cloudconvert.com/
Upload din lydfil til public-mappen i dit Astro-site.
Definer "scopet"
Tilføj en x-data attribut for at definere “scopet” for lyden - du kan typisk bruge en section eller en component til at definere scopet for lyden. I dette eksempel, har jeg sat scopet til at være denne section:
x-ref er alpine.js, og fungerer som en reference til audio-elementet. Det svarer til noget lignende:
const trykpaafotoet = document.queryselector… i traditionel javascript.
Afspil lyden
For at afspille lyden bruges igen en lille stump alpine. I eksemplet afspilles lyden, når der klikkes på et foto:
Kodestumpen består af lidt html med en alpine @click attribut:
@click er en event listener, der lytter om hvorvidt der bliver klikket på img-elementet.
$refs.trykforatafspillelyd er en reference tilbage lydfilen, der blev inkluderet i lydafspilleren tidligere.
play() er en javascript-stump, der afspiller lyden.
Tilføj flere lyde
Gennemløb ovenstående for hver lyd, du vil tilføje.
Hvis du vil afspille en lyd ved hover i stedet for click, kan du bruge @mouseenter eller @mouseleave i stedet for @click. Besynderligt nok kræver @moseenter at nogen har klikket et vilkårligt sted på siden for at fungere...!?
Custom Cursor
Det er nemt og sjovt at tilføje sine egne cursors.
Lav grafikken
Først og fremmest gælder det om at få fat på en (lille) grafik-fil (max. 128 x 128 pixels). Se sektionen "usage notes" på https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#usage_notes vedr. filstørrelser og typer, for det med at lave grafikfilerne kan drille en del!
Så: lav/design en lille cursor-fil, og placer den i “public” mappen i dit Astro website.
Det kan gøres i tailwind.css filen, hvor man kan tilføje diverse nye CSS-regler til tailwind – se mit eksemplet nedenfor, der først tilføjer en ny CSS cursor-variabel til Tailwind.
Giv din cursor et navn (I eksemplet er cursoren navngivet 'handcursor').
Lav den css der skal til: en url() med stien til dit cursor-billede og afslut med “, pointer” (det er et obligatorisk fallback). I mit eksempel står der også 25 25, som er et par værdier, der justerer placeringen af din cursor. Se https://developer.mozilla.org/en-US/docs/Web/CSS/cursor#syntax for yderligere info.
Brug din nye cursor ved at tilføje classerne "cursor cursor-(--handcursor)" til de html-elementer, der skal have din custom cursor på hover, jvf. eksemplet nedenfor, der tilføjer cursoren til Link komponenten.
Hvis cursoren skal bruges på mange elementer, f.eks. alle links og knapper, kan du også tilføje en @apply regel til tailwind.css filen.
Det kan gøres jvf. eksemplet nedenfor.
@layer base { a, button{ @apply cursor-(--handcursor); } }
@layer base betyder at vi “bygger videre” på Tailwind, og er en konvention for det med at arbejde med Tailwind.
Dernæst defineres de elementer (a og button), som cursoren skal være aktiv ved – du kan tilføje alle de elementer du vil. @apply tilføjer Tailwind-classes til de valgte elementer, i dette tilfælde den nye custom cursor class.
:hover video
Internettet elsker videoer. Også små effektvideoer og GIF'er. GIF'er skal dog (typisk) ikke være GIF'er - brug små videoer i stedet. Men alt i alt: Der skal nogen på dit website!
Først og fremmest kan du lave små videoer, der afspiller når brugeren kører musen over dem (eller noget tekst?), som i eksemplet nedenfor.
Definer scopet
Det er ret nemt. Start med at tilføje en x-data attribut for at definere “scopet” for videoen - du kan typisk bruge en section eller en component til at definere scopet for videoen. I dette eksempel, har jeg sat scopet til at være denne section:
<section id="videoonhover" x-data>
Tilføj videoen og start/stop afspilning
Som det næste, skal der tilføjes en video. Videoen skal have lidt JS til at starte og stoppe afspilning, når musen køres over. Det klares med Alpine JS:
Dernæst kan du et element, tekst eksempelvis, der ændrer variablens værdi mellem true og false, når musen kører over det:
<span class="font-bold" @mouseover="videopopup = ! videopopup" @mouseleave="videopopup = ! videopopup">poppe op et andet sted</span>
Som det sidste, skal der også laves et video-element, der bruger true/false variablen og alpinejs x-show attributten til at vise/skjule videoen, alt afhængig af true/false variablens værdi:
For at bruge Motion One, skal du i bunden af din side/template/komponent importere Motion One biblioteket i et script tag:
<script> /* Import af Motion One bibliotek */ import { animate, stagger, inView, scroll } from "motion"; </script>
Så er Motion One installeret og klar til at blive brugt:-)
OBS! En del af animationerne kan komme til at gøre viewporten for bred, så der kommer horisontale scrollbars. Så det kan blive nødvendigt at sætte "overflow-hidden" på dele af sitet. Forsøg at være så restriktiv som muligt i brugen af overflow-hidden: Sørg for at gøre det på sektioner/komponenenter i stedet for hele sitet, da det i givet fald kan give problemer med sticky elementer:
Lad os starte med noget simpelt - at tilføje en entrance animation, der får hele websitet til at fade ind, når det loades - prøv at reloade siden for at se animationen.
Sådan en animation kan tilføjes i dit script-tag med ganske få kodestumper, lige efter det import statementet, der blev tilføjet i afsnittet "I gang med Motion One":
"body" er selectoren - den siger at det er vores body, der skal animeres. Den fungerer på samme måde som en CSS-selector.
I Første tuborg-klamme defineres keyframene i animationen: { opacity: [ 0, 1] }
I andet sæt tuborg-klammer defineres indstillingerne for keyframe-animationen: { duration: 1 }
Mere animate()
Prøv at gøre animate() funktionen lidt mere kompleks, som eksempelvis i overskriften herover. Her er der flere parametre i keyframe animationen: Opacity, scale, rotate, x, y, delay, duration, direction mm.
Det første sæt tuborg-klammer med "opacity, scale, rotate, x og y" definerer de transforms, der udføres, og de 4 keyframes, der er i denne animation. Her kan du tilføje alle de CSS transforms, du vil.
Det andet sæt tuborg-klammer med "delay, duration, repeatType mm.," definerer dine parametre for animationenm, altså det der svarer til CSS Animation egenskaben.
Læg mærke til at jeg har tilføjet et "delay" (i sekunder) - prøv at reloade siden, hvis du ikke kan se det i første omgang. Delayet måles fra når siden er loadet.
NB: Jeg har tilføjet en tailwind class til overskriften: origin-top-left. Det placerer orienteringspunktet for animationen øverst til venstre på elementet:
Indtil videre er animationerne bare blevet eksekveret når sitet er loadet. Men rigtig ofte vil vi gerne eksekvere animationerne, når brugeren ser det pågældende element i viewporten. Det kan vi gøre ved hjælp af inview()-funktionen. Fotoet herunder skubbes ind fra siden, når brugeren scroller ned til det
inView()-funktionen ser således ud for dette eksempel:
inView-funktionen tager først et element - i mit tilfælde et Image component med class'en "fotoinview"
Dernæst ser paranteserne og pilen lidt kryptiske ud - de definerer en callback funktion - det der skal ske når elementetet er "inview."
Callback funktionen består af en animate()-funktion, helt som anvendt i de sidste par eksempler. Den animerer blot på x-positionen i stedet for opacity og scale.
I de følgende eksempler bruges inView til at "omkranse" mange af animationerne. Animationerne behøver ikke nødvendigvis først at starte "inView," men vil i mange tilfælde være det. Derfor er "inView" inkluderet i eksemplerne.
Stagger animation
Stagger funktionen giver en række elementer den samme animation, men med et delay mellem hvert element. Se f.eks. listen nedenfor (reload evt. for at se animationen):
Stagger
Stagger senere
Stagger endnu senere
Stagger meget senere
Stagger sidst
Stagger animationer kan laves med følgende kodestump:
Først vælges alle de elementer, der skal "staggeres" - jeg har valgt alle list items nede i en ul med class'en staggeranimation. Men du kan lave selectoren som du ønsker.
Dernæst definerer jeg keyframe-indstillingerne for stagger animationen
Til sidst anvender jeg keyframe animationen med et delay, som tilføjer "stagger" på alle elementer.
I kodestumpen stagger(1, { startDelay: 2 } refererer 1-tallet til et delay i antal sekunder mellem hvert list item.
startDelay: 2 refererer til hvor lang tid der skal gå, før det første list item animeres ind.
I ovenstående eksempel har jeg brugt en unordered list og stagget alle list items. Men du kan sagtens bruge den på andre elementer - f.eks. billeder i en section, som nedenfor. Og du kan også lave din keyframe animation vildere:-) Og du behøver ikke nødvendigvis at pakke stagger animationen ind i inView-funktionen.
Timeline animation
Med en timeline kan flere animationer bindes sammen (chaines), så de eksekveres én efter én. Se animationerne på billedet nedenfor (reload eventuelt for at se animationen):
Timeline animationen er lavet med følgende kodestump:
Først oprettes et array til timelineanimationen, så animation kan deles op i små bidder/sekvenser.
Hver sekvens i animationen puttes i et sæt firkantede parenteser, og keyframe animationen for hver sekvens defineres.
OBS! Den første animation tager 5 sekunder, og ændrer "opacity" til 1. Opacity på 1 er også default-værdien, så for at gøre elementet usynligt til at starte med, skal html-element have tailwind-class'en opacity-0:
Indtil videre er animationerne blevet eksekveret én gang. Hvis du gerne vil have dem til at starte (forfra) hver gang elementet vises i viewporten, kan du bruge inView()s return funktion. Se eksempelvis billedet herunder. Det er roteret 180 grader, når det kommer ind i viewporten, og bliver så roteret tilbage til 0 grader med animate()-funktionen. Scroller du væk, vender det tilbage til 180 grader, og næste gang det kommer ind i viewporten igen, roterer det til 0 grader igen."
Return funktionen fyres af efter den første animate()-funktionen, jvf. nedenstående eksempel:
HTML'en består af to billeder, der ligger præcis samme sted ved hjælp af absolute/relative positionering. Parent elementet er positioneret "relative," så child elementerne (billeder) positioneres absolut i forhold til det relative element.
I eksemplet bruges et img elementet med billeder i public-mappen, men du kan med fordel bruge Astros Image component i stedet - Image componenten driller når man skal lave kode-dokumentation, derfor har jeg brugt et img-element.
Script stumpen bruger Motion One scroll-funktionen til at checke hvor langt ned i elementet med "crossfadeimages" classen (den relative container), brugeren er scrollet. Animate-funktionen bruges til at ændre opacity fra 1 til 0 på det nederste billede. Offset bruges til at styre hvornår crossfadet skal starte/være færdiggjort. I dette tilfælde starter opacity-animationen 25vh FØR det relative element kommer ind på skærmen.
Scrollzoom (eller scroll og Zoom)
I eksemplet nedenfor, scrolles først ned i et billede, og efter at billedet er scrollet et stykke ned, bliver der zoomet i det.
Det kan gøres ret let med en scrool og animate funktion. Først html'en:
"target" refererer til det element, der lyttes efter om der scrolles i - dvs. min section med class'en scrollzoom. Og den er lige så høj som billedet.
Offset referer til hvornår animate-funktionen skal startes og være færdiggjort, f.eks. ["0.75 end", "end end"].
"0.75 end" betyder at animationen skal startes når "0.75 (dvs. 75%) af billedet rammer "end" af containeren (dvs. bundend af skærmen)". Du kan putte de talværdier ind du vil: Første tal referer til hvor langt nede i billedet, andet tal referer til hvor langt nede i containeren kontaktpunktet skal være (0 er toppen, 1 bunden)
"end end" betyder at animationen skal være færdig når "end af target/billedet rammer end af containeren (bunden af skærmen). Igen: Første tal referer til hvor langt nede i billedet, andet tal referer til hvor langt nede i containeren kontaktpunktet skal være (0 er toppen, 1 bunden)
Det kan fungerer fint at lave scrollzoom i fuld skærmbredde:
Parallax med tekstboks
Parallax-sektioner ses ofte anvendt på webdoks. Parallax-sektioner kan laves med Motion Ones scroll-funktion. Scroll-funktionen lytter på hvor langt man er scrollet ned i et givent element, og så kan man animere et andet element oven på dette for at lave parallax-effekten. Se sektionen nedenfor, hvor teksten bevæger sig hurtigere end baggrunden.
scroll() bruges til at lytte om der scrolles i "noget", og hvis ja: Udfører animate()-funktionen, som laver en forskydelse af y-aksen jvf. værdierne 50 og 500
target: siger hvilket element, der skal lyttes efter, om der bliver scrollet i - i dette tilfælde det samme som det vi animerer med scroll-funktionen.
Parallaxgrafik
Parallax-sektioner kan også nemt bruges til at lave en fin, lille grafisk kollage:
HTML'en består af en section med class'en parallaxgrafik, som bruges til JS/Motion One stumpten. Dertil er der en <div> med et baggrundsbillede (inline styles) og et 12-kolonnet grid, som bruges til at placere de grafiske elementer (de små både). Alt er stylet med Tailwind, bort set fra baggrundsbilledet:
scroll()-funktionen bruges tre gange til at animere de forskellige grafik-elementer. Funktionen er stort set ens i alle tre tilfælde:
scroll() bruges til at lytte om der scrolles i "noget", og hvis ja: Udfører animate()-funktionen
animate()-funktionen tager grafikelementet (parallaxgrafik1, parallaxgrafik2 og parallaxgrafik3) og forskyder det i x- og y- retningen.
target: siger hvilket element, der skal lyttes efter, om der bliver scrollet i - i dette tilfælde <section>'en, der omkranser alt parallax-indholdet, og har class'en parallaxgrafik
offset: er en beskrivelse af hvornår animationen skal starte og slutte. "start end" betyder at animationen skal starte "når starten af target elementet rammer bunden/slutnignen af containeren (skærmen)" og "end start" betyder at animationen skal væres slut, når bunden/slutningen af target elementet rammer toppen/starten af containeren (skærmen).
Sticky
"Sticky" sektioner ses også ofte anvendt i webfeatures - indimellem kombineret med parallax. Målet er at give brugerne lidt ro til at læse tekstbidderne. Sticky-sektioner kan laves nemt bare med Tailwind. Se de tre sektioner nedenfor, som "sticyk'er" teksten fast i toppen af skærmen.
Well, the way they make shows is, they make one show. That show's called a pilot.
Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.
Some pilots get picked and become television programs. Some don't, become nothing.
For at lave sticky-sektioner gælder det egentlig bare om at tilføje tailwinds sticky class, og så definere hvor den skal være sticky - her top-0:
<div class="flex items-center h-screen w-full bg-cover bg-center" style="background-image: url('/astro.jpg')" > <p class="w-3/4 lg:w-1/2 mx-auto p-10 bg-slate-50 text-xl sticky top-1/4">Well, the way they make shows is, they make one show. That show's called a pilot.</p> </div>
En anden måde at bruge "sticky" sektioner på er at sticky'e hele sektioner, eventuelt med en lille parallaxe-effekt på:
Well, the way they make shows is, they make one show. That show's called a pilot.
Then they show that show to the people who make shows, and on the strength of that one show they decide if they're going to make more shows.
Some pilots get picked and become television programs. Some don't, become nothing.
Her er sticky class'en placeret på elementerne med billedbaggrunde på:
<div class="flex items-center h-screen w-full bg-cover bg-center sticky top-0" style="background-image: url('/astro.jpg')" > <p class="w-3/4 lg:w-1/4 lg:ml-64 p-10 bg-slate-50 text-xl stickyparallax1">Well, the way they make shows is, they make one show. That show's called a pilot.</p> </div>
Parallax'en er lavet med en JS/Motion One kodestump efter samme fremgangsmåde som Parallax med tekstboks" dokumentationen:
Stickyscroll-sektioner med infobokse ses ofte på blandt andet DR's webfeatures. De er nemme at lave med Tailwind - helt uden alle de der besværlige Javascrip-stumper.
Scrollende indhold 1
Scrollende indhold 2
Fast placeret indhold 1
Fast placeret indhold 2
Scrollende indhold 1
Scrollende indhold 2
Teknikken bag
Koden er realtivt simpel - det vigtige er at lave en container, som indeholder 3 elementer:
Et "position: sticky" element, hvor der også er et baggrundsbillede på
Et "position: relative" element, der bruges til at indeholde alle de infobokse, der skal scrolle over baggrundsbilledet
Et element, der bruges som "afstandsstykke" - det er i dette 100vh højt - samme højde som baggrundsbilledet. Det gør at indholdet/infoboksene er scrollet helt væk, inden næste sticky element begynder at scrolle ind over baggrundsbilledet.
I eksemplet bruges flexbox til at organisere indholdet, men det kan i princippet lige vel være CSS grid. I sektion 2 er der et par fast positionerede indholdssektioner - det er i bund og grund bare lidt ekstra indhold i sticky-sektionen:
For at bryde det vertikale flow (den uendelige scrollen nedad), kan det være sjovt at tilføje en horisontalt scrollende sektion, som reagerer på et op/nedadgående scroll. Se f.eks. Banana Blossom Salads, der bruger det rigtig fint til at fremvise en menu. Eller eksemplet nedenfor:
Dette fine, lille kamera er et Diana F, der skyder med 120-film.
Dette fine, lille kamera er et Diana F, der skyder med 120-film.
Dette fine, lille kamera er et Diana F, der skyder med 120-film.
Dette fine, lille kamera er et Diana F, der skyder med 120-film.
Dette fine, lille kamera er et Diana F, der skyder med 120-film.
Teknikken bag horisontal scroll
I eksemplet her er der en række forskellige ting, der skal arbejde sammen. Først og fremmest i html'en:
Den horisontale sektion er lidt tricky. Først er der en section, inde i den section er der en unordered list, og listen består så - i dette tilfælde - af 5 list items.
Der kommer højre-scrollbars på sitet, fordi den horisontale sektion fylder for meget. Så jeg har pakket den horisontale sektion ind i en <div> med class'en overflow-clip:
<div class="overflow-clip"> <section id="horisontalscrollsection" class="h-[500vw]"> <ul id="horisontalliste" class="list-none pl-0 flex sticky top-[10vh]"> <li class="pl-0 flex w-[100vw] items-start justify-center flex-col overflow-hidden flex-grow-0 flex-shrink-0 flex-auto"><figure class="flex flex-row max-w-[800px]"><Image src={lomo} class="w-2/3" alt="foto" /><figcaption class="pl-4 italic w-1/3">Dette fine, lille kamera er et Diana F, der skyder med 120-film.</figcaption></figure></li> <li class="flex w-[100vw] items-start justify-center flex-col overflow-hidden flex-grow-0 flex-shrink-0 flex-auto"><figure class="flex flex-row max-w-[800px]"><Image src={lomo} class="w-2/3" alt="foto" /><figcaption class="pl-4 italic w-1/3">Dette fine, lille kamera er et Diana F, der skyder med 120-film.</figcaption></figure></li> <li class="flex w-[100vw] items-start justify-center flex-col overflow-hidden flex-grow-0 flex-shrink-0 flex-auto"><figure class="flex flex-row max-w-[800px]"><Image src={lomo} class="w-2/3" alt="foto" /><figcaption class="pl-4 italic w-1/3">Dette fine, lille kamera er et Diana F, der skyder med 120-film.</figcaption></figure></li> <li class="flex w-[100vw] items-start justify-center flex-col overflow-hidden flex-grow-0 flex-shrink-0 flex-auto"><figure class="flex flex-row max-w-[800px]"><Image src={lomo} class="w-2/3" alt="foto" /><figcaption class="pl-4 italic w-1/3">Dette fine, lille kamera er et Diana F, der skyder med 120-film.</figcaption></figure></li> <li class="flex w-[100vw] items-start justify-center flex-col overflow-hidden flex-grow-0 flex-shrink-0 flex-auto"><figure class="flex flex-row max-w-[800px]"><Image src={lomo} class="w-2/3" alt="foto" /><figcaption class="pl-4 italic w-1/3">Dette fine, lille kamera er et Diana F, der skyder med 120-film.</figcaption></figure></li> </ul> </section> </div>
Et par vigtige ting ved html'en er:
Min section er sat til at have en højde på 500 vw med tailwinds class til at tilføje custom højder: h-[500vw]. Så matcher højden af elementet med bredden af scroll-sektionen. Højden på elementet afgør scroll-hastigheden, da det er det "target," der lyttes efter hvor langt man er scrollet i. Jeg har valgt at have 5 elementer i min horisontale sektion, og bruger derfor en størrelse på h-[500vw] - havde jeg f.eks. 3 eller 7 elementer i min horisontale sektion, ville jeg gå efter en størrelse på hhv. h-[300vw] h-[700vw] for at få en passende scroll-hastighed. Kort sagt: Højden skal matche den horisontale sektions bredde.
Min ul'er er sat til sticky top-[10vh] - det kan tilpasses efter behov
Hver enkelt li-element er sat til en bredde på 100vvw ved hjælp af w-[100vw]. Deruodver er der en række flex-classes til justering af indholdet. Hvis du vil have sektionerne til at fylde mindre, kan du sætte en anden/fast bredde - så skal du bare opdatere højden, jvf. punktet ovenfor, og en lille stump JS (kommer senere).
Transform med translateX er her sat til -500vw fordi der er 5 indholdselementer i listen. Har du f.eks. syv, sætter du den til -700vw, har du 3, sætter du den til -300vw mm.
Skal du have to eller flere horisontale scroll-sektioner, kan du bare kopiere kodestumpen, og ændre id'er på de efterfølgende horisontal scroll sektioner samt i JS-stumperne.
I html'en: Først har jeg lavet en container/article det hele. Dernæst to <div>'er: Den første <div> består af et grid på 5 kolonner. Inde i det grid er der en masse <div>'er, med hver sin class (mangeelementer1...10). <div>en er position: sticky. <div> nr. 2 fungerer bare som fyldstof:
Dernæst skal der lidt javascript til. Her har jeg brugt inView funktionen til at checke at elementet er i viewporten. Dernæst bliver hver enkelt element animeret med animate()-funktionen. Jeg animerer hver enkelt element, så de kan forskydes uafhængigt af hinanden. Efter animate-funktionerne er der en retur/callback-funktion, som egentlig bare gentager animationerne. Så vil animationen virke hver gang elementet kommer ind i viewporten.:
Læg mærke til toppen af sitet - der er en progress-bar/læseindikator, der viser hvor langt nede på siden brugeren er. Du kan lave en progress-bar ved hjælp af to stumper: En html-og-tailwind stump, der styrer udseendet, og en JS/Motion One stump, der styrer hvor meget af progress-baren, der vises.
Først og fremmest er progress-baren "designet" med Tailwind. Jeg har placeret den nederst i html'en, da den alligevel bare bliver positioneret "fixed" over alt andet indhold:
<!-- Progress-bar placeret i toppen af sitet --> <div class="progress-bar h-4 fixed w-full bg-gradient-to-r from-pink-500 to-yellow-300 left-0 origin-top-left top-0 right-0"></div>
Dernæst er der en JS/Motion One stump, der bruger Motion Ones scroll-funktion:
Her udfører scroll-funktionen en animate-funktion, der skalerer progress-baren op i størrelse fra 0 til 1 (fuld størrelse), alt afhængig af hvor langt brugeren er scrollet ned på siden.
En progress-bar behøver ikke at være fastgjort til toppen - den kan f.eks. også være i venstre eller højre side af skærmen - så skal html'en og JS/Motion One stumpen tilpasses lidt:
<!-- Progress-bar placeret i venstre side af sitet --> <div class="progress-bar h-4 fixed h-full bg-gradient-to-b from-pink-500 to-yellow-300 left-0 origin-top-left top-0 right-[99%]"></div>