Sådan opbygges en Reddit-inspireret loading spinner med kun HTML og CSS

Reddits mobilapp har en temmelig slående lastespinner, der minder om kredsløb, der cirkler omkring en planet eller stjerne. De fleste udviklere vil nå JavaScript eller SVG'er til en opgave som denne, men takket væreanimation-iteration-count: infinite;og et par andre hacks og tricks, det er ikke engang nødvendigt. I dag skal jeg vise dig, hvordan du koder en Reddit-inspireret spinner udelukkende i HTML og CSS!

Her er det endelige resultat:

Grundlæggende opsætning

Lad os starte med at skrive nogle HTML DOM-elementer, som vi kan fastgøre midtercirklen og hver af de roterende orbitaler på.

 ... ... 

Den inner-spinog outer-spinelementer vil være forældrenes knudepunkter i alt, hvad der er nødvendigt at animeret, og til sidst vil vi anvende CSS keyframes transformationer til disse forældre noder.

I kodeeksemplet ovenfor står ellipserne ( ) for buerne og kredser om "måner". Både de indre og de ydre ringe indeholder hver to buer og to måner, men af ​​grunde, der vil blive tydelige lidt senere, er hver bue faktisk sammensat af to CSS-former, så vi har brug for i alt otte buer og fire måner. HTML'en fuldt ud ser sådan ud:

CSS-figurer

Det er muligt at tegne cirkler og buer i CSS ved blot at oprette en firkant og indstille border-radiustil 50%.

Hver side af grænsen kan have en anden farve eller kan indstilles til transparent. Den background-coloregenskab sætter formen fyld, hvis nogen.

Det er let at tegne buer i 90, 180 og 270 grader ved blot at indstille en eller flere sider af grænsen til at være gennemsigtig. Men hvis du ser nøje på spinderen øverst på siden, vil du bemærke, at "halen" på hver orbital efterlader et mellemrum mellem sig selv og månen bag sig. Det betyder, at selvom buelængderne er tæt på 180 grader, er de lidt genert af 180.

At tegne cirkelsegmenter med uregelmæssige længder i CSS kræver lidt hack. For at gøre dette er vi nødt til at tegne to tilstødende 90 graders buesegmenter og dreje en let, så de overlapper hinanden, hvilket efterlader et tilsyneladende buesegment på ca. 160 grader.

Når vi ser tilbage på HTML nu, kan du muligvis gætte, hvorfor vi har indstillet to noder til hver bue (an arc_startog arc_end). Disse vil blive brugt til at repræsentere hver del af en enkelt overlappende lysbue, der repræsenterer halen på hver orbital.

Opsætning af CSS

Til at begynde med indstiller vi en CSS-variabel, der repræsenterer farven på spinneren, og en anden variabel, der repræsenterer en -50%, -50% oversættelse, som vi bruger i hele CSS til at centrere former omkring deres centrum (som apposed til deres øverste venstre hjørne, hvilket er standard).

html { --spinner: #1EAAF0; --center: translate(-50%, -50%); }

Nu kan vi også tegne den centrale cirkel.

.center { position: absolute; width: 30px; height: 30px; background: var(--spinner); border-radius: 50%; top: 50%; left: 50%; transform: var(--center); }

Barneknudepunkterne for hver orbital er lukket inde i forældreknuderne kaldet inner-spinog outer-spin. For nu bruger vi dem bare til at centrere spinderen inden i vinduet.

.outer-spin, .inner-spin { position: absolute; top: 50%; left: 50%; }

Tegning af orbitalerne

Lastespinderen er dybest set en række koncentriske cirkler, så lad os først fokusere på at tegne kun en bue.

Da hver bue består af to overlappende sektioner, kan vi bare begynde at tegne to buer ved siden af ​​hinanden.

.inner-arc { width: 62px; height: 62px; } .inner-arc_start-a { border-color: transparent transparent transparent green; /* NOTE: the order here very much matters! */ transform: var(--center) rotate(0deg); } .inner-arc_end-a { border-color: red transparent transparent transparent; transform: var(--center) rotate(0deg); }

Den første transformation centrerer i vinduet. Rotation er sat til nul grader for at vise standardtilstanden for buerne.

Bemærk, at buerne ikke stemmer overens med x-krydsningerne på enhedens cirkel. For at rette op på dette og for at gøre buerne lettere at arbejde med roterer vi buerne 45 grader. Derefter drejer vi lidt over en af ​​buerne for at skabe en samlet buelængde på ca. 160 grader.

.inner-arc_start-a { border-color: transparent transparent transparent green; transform: var(--center) rotate(65deg); } .inner-arc_end-a { border-color: red transparent transparent transparent; transform: var(--center) rotate(45deg); }

Dernæst kan vi placere en af ​​orbitale måner ved at bevæge den langs x-aksen. Desværre, i modsætning til vektorgrafik som SVG'er, er CSS-grænser ikke breddeløse vektorer, der accepterer en stregstil. Det betyder, at afstande ikke automatisk måles til midtpunktet på linjen. Vi skal tage højde for bredden af ​​grænsen, når objekter placeres.

Dette resulterer i et par "magiske tal", som vi sandsynligvis kunne minimere, hvis vi ville indstille flere CSS-variabler og bruge calc()funktionen. Det virker dog lidt involveret, så jeg placerer bare cirklen efter pixelværdi for nu.

.inner-moon-a { position: absolute; top:50%; left:50%; width: 12px; height: 12px; background: red; border-radius: 50%; transform: var(--center) translate(33px, 0); }

Dernæst tegner vi to buer mere, men denne gang bruger vi scale(-1, -1)transformationen. Dette vender buerne på tværs af både x- og y-aksen, hvilket i det væsentlige spejler kontrailen.

.inner-arc_start-b { border-color: transparent transparent transparent var(--spinner); transform: var(--center) rotate(65deg) scale(-1, -1); } .inner-arc_end-b { border-color: var(--spinner) transparent transparent transparent; transform: var(--center) rotate(45deg) scale(-1, -1);

Endelig gentager vi blot den ydre bane CSS fra den indre bane, men indstiller en større højde og bredde! (Forestil dig, hvor kort denne CSS kan være med SASS-mixins!)

.outer-arc { width: 100px; height: 100px; }

Tilføjelse af animationen

Det sidste trin er at tilføje animation. Først skal vi tilføje et enkelt keyframes-element, der indstiller typen af ​​animationsadfærd og CSS-elementet, der er påvirket af animation, i dette tilfælde rotation gennem en transformegenskab.

@keyframes spin { 100% {transform: rotate(360deg); } }

Identifikatoren " spin" forbinder nøglerammerne tilbage til animationsattributter, som vi vil tilføje inden for hvert overordnet element. Animationsegenskaben indstiller den tidsmæssige information for animationen, hvilket betyder, at hver kredsløb kredser med forskellig hastighed.

.outer-spin { animation: spin 4s linear infinite; } .inner-spin { animation: spin 3s linear infinite; }

Det er det!

Koden til denne vejledning kan findes på CodePen.io. Du bedes kommentere - eller Tweet på mig @PleathrStarfish - hvis du har et forslag, en observation eller en cool fork af min kode!