Single Element Loaders: Går i 3D! PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

Single Element Loaders: Går i 3D!

Til denne fjerde og sidste artikel i vores lille serie om enkelt-element læssere, skal vi udforske 3D-mønstre. Når du opretter et 3D-element, er det svært at forestille sig, at kun et HTML-element er nok til at simulere noget som alle seks flader af en terning. Men måske kan vi slippe afsted med noget mere terning-ligesom i stedet ved kun at vise de tre forreste sider af formen - det er fuldstændig muligt, og det er det, vi skal gøre sammen.

Den delte kube-loader

Her er en 3D-loader, hvor en terning er opdelt i to dele, men kun er lavet med kun et enkelt element:

CodePen Embed Fallback

Hver halvdel af terningen er lavet ved hjælp af et pseudo-element:

Single Element Loaders: Går i 3D! PlatoBlockchain Data Intelligence. Lodret søgning. Ai.
Single Element Loaders: Går i 3D!

Fedt, ikke sandt?! Vi kan bruge en konisk gradient med CSS clip-path på elementets ::before , ::after pseudos for at simulere de tre synlige flader af en 3D-terning. Negativ margin er det, der trækker de to pseudoer sammen for at overlappe og simulere en fuld terning. Resten af ​​vores arbejde er for det meste at animere de to halvdele for at få pæne læssere!

Lad os se en visualisering, der forklarer matematikken bag clip-path-punkterne, der bruges til at skabe dette terninglignende element:

Single Element Loaders: Går i 3D! PlatoBlockchain Data Intelligence. Lodret søgning. Ai.
Single Element Loaders: Går i 3D!

Vi har vores variabler og en ligning, så lad os sætte dem i gang. Først etablerer vi vores variabler og indstiller størrelsen for de vigtigste .loader element:

.loader { --s: 150px; /* control the size */ --_d: calc(0.353 * var(--s)); /* 0.353 = sin(45deg)/2 */ width: calc(var(--s) + var(--_d)); aspect-ratio: 1; display: flex;
}

Intet er for tosset indtil videre. Vi har en 150px kvadrat, der er sat op som en fleksibel beholder. Nu etablerer vi vores pseudos:

.loader::before,
.loader::after { content: ""; flex: 1;
}

Det er to halvdele i .loader beholder. Vi skal male dem ind, så det er der vores kegleformet gradient sparker ind:

.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}

Gradienten er der, men det ser mærkeligt ud. Vi er nødt til klip det til elementet:

.loader::before,
.loader::after { content: ""; flex: 1; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0); clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}

Lad os sørge for, at de to halvdele overlapper med a negativ margin:

.loader::before { margin-right: calc(var(--_d) / -2);
} .loader::after { margin-left: calc(var(--_d) / -2);
}

Lad os nu få dem til at bevæge sig!

.loader::before,
.loader::after { /* same as before */ animation: load 1.5s infinite cubic-bezier(0, .5, .5, 1.8) alternate;
} .loader::after { /* same as before */ animation-delay: -.75s
} @keyframes load{ 0%, 40% { transform: translateY(calc(var(--s) / -4)) } 60%, 100% { transform: translateY(calc(var(--s) / 4)) }
}

Her er den sidste demo igen:

CodePen Embed Fallback

Fremskridtskubeindlæseren

Lad os bruge den samme teknik til at skabe en 3D-fremskridtsindlæser. Ja, stadig kun ét element!

CodePen Embed Fallback

Vi ændrer ikke noget i forhold til at simulere kuben på samme måde, som vi gjorde før, andet end at ændre læsserens højde og billedformat. Animationen vi laver bygger på en overraskende nem teknik, hvor vi opdaterer bredden af ​​venstre side, mens højre side fylder det resterende rum, takket være flex-grow: 1.

Det første trin er at tilføje noget gennemsigtighed til højre side ved hjælp af opacity:

CodePen Embed Fallback

Dette simulerer effekten af, at den ene side af terningen er udfyldt, mens den anden er tom. Så opdaterer vi farven på venstre side. For at gøre det opdaterer vi enten de tre farver inde i den kegleformede gradient, eller vi gør det ved at tilføje en baggrundsfarve med en background-blend-mode:

.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply;
}

Dette trick tillader os kun at opdatere farven én gang. Den højre side af læsseren smelter sammen med de tre hvide nuancer fra den koniske gradient for at skabe tre nye nuancer af vores farve, selvom vi kun bruger én farveværdi. Farvetricks!

CodePen Embed Fallback

Lad os animere bredden af ​​læsserens venstre side:

CodePen Embed Fallback

Ups, animationen er lidt mærkelig i starten! Læg mærke til, hvordan det starter uden for kuben? Dette er fordi vi starter animationen på 0% bredde. Men pga clip-path og negativ margin, vi bruger, er det, vi skal gøre i stedet, at starte fra vores --_d variabel, som vi brugte til at definere clip-path point og den negative margen:

@keyframes load { 0%, 5% {width: var(--_d); } 95%, 100% {width: 100%; }
}

Det er lidt bedre:

CodePen Embed Fallback

Men vi kan gøre denne animation endnu mere jævn. Har du bemærket, at vi mangler lidt? Lad mig vise dig et skærmbillede for at sammenligne, hvordan den endelige demo skal se ud med den sidste demo:

Single Element Loaders: Går i 3D! PlatoBlockchain Data Intelligence. Lodret søgning. Ai.

Det er bunden af ​​kuben! Da det andet element er gennemsigtigt, skal vi se undersiden af ​​det rektangel, som du kan se i det venstre eksempel. Det er subtilt, men burde være der!

Vi kan tilføje en gradient til hovedelementet og klippe det, som vi gjorde med pseudoerne:

background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat;

Her er den fulde kode, når alt er trukket sammen:

.loader { --s: 100px; /* control the size */ --_d: calc(0.353*var(--s)); /* 0.353 = sin(45deg) / 2 */ height: var(--s); aspect-ratio: 3; display: flex; background: linear-gradient(#fff1 0 0) bottom / 100% var(--_d) no-repeat; clip-path: polygon(var(--_d) 0, 100% 0, 100% calc(100% - var(--_d)), calc(100% - var(--_d)) 100%, 0 100%, 0 var(--_d));
}
.loader::before,
.loader::after { content: ""; clip-path: inherit; background: conic-gradient(from -90deg at calc(100% - var(--_d)) var(--_d), #fff 135deg, #666 0 270deg, #aaa 0);
}
.loader::before { background-color: #CC333F; /* control the color here */ background-blend-mode: multiply; margin-right: calc(var(--_d) / -2); animation: load 2.5s infinite linear;
}
.loader:after { flex: 1; margin-left: calc(var(--_d) / -2); opacity: 0.4;
} @keyframes load { 0%, 5% { width: var(--_d); } 95%, 100% { width: 100%; }
}
CodePen Embed Fallback

Det er det! Vi har lige brugt en smart teknik, der bruger pseudo-elementer, kegleforløb, klipning, baggrundsblanding og negative margener for at få, ikke én, men to søde 3D-indlæsere med intet mere end et enkelt element i markeringen.

Mere 3D

Vi kan stadig gå længere og simulere et uendeligt antal 3D-kuber ved hjælp af ét element - ja, det er muligt! Her er et gitter af kuber:

CodePen Embed Fallback

Denne demo og de følgende demoer understøttes ikke i Safari i skrivende stund.

Skørt, ikke? Nu skaber vi et gentaget mønster af terninger lavet ved hjælp af et enkelt element... og heller ingen pseudos! Jeg vil ikke gå i detaljer om den matematik, vi bruger (der er meget specifikke tal derinde), men her er en figur for at visualisere, hvordan vi kom hertil:

Single Element Loaders: Går i 3D! PlatoBlockchain Data Intelligence. Lodret søgning. Ai.
Single Element Loaders: Går i 3D!

Vi bruger først en conic-gradient for at skabe det gentagne terningmønster. Gentagelsen af ​​mønsteret styres af tre variable:

  • --size: Tro mod sit navn styrer dette størrelsen af ​​hver terning.
  • --m: Dette repræsenterer antallet af kolonner.
  • --n: Dette er antallet af rækker.
  • --gap: dette er mellemrummet eller afstanden mellem kuberne
.cube { --size: 40px; --m: 4; --n: 5; --gap :10px; aspect-ratio: var(--m) / var(--n); width: calc(var(--m) * (1.353 * var(--size) + var(--gap))); background: conic-gradient(from -90deg at var(--size) calc(0.353 * var(--size)), #249FAB 135deg, #81C5A3 0 270deg, #26609D 0) /* update the colors here */ 0 0 / calc(100% / var(--m)) calc(100% / var(--n));
}

Derefter påfører vi et maskelag ved hjælp af et andet mønster med samme størrelse. Dette er den sværeste del af denne idé. Ved at bruge en kombination af en linear-gradient og en conic-gradient vi skærer nogle få dele af vores element for at holde kun terningformerne synlige.

.cube { /* etc. */ mask: linear-gradient(to bottom right, #0000 calc(0.25 * var(--size)), #000 0 calc(100% - calc(0.25 * var(--size)) - 1.414 * var(--gap)), #0000 0), conic-gradient(from -90deg at right var(--gap) bottom var(--gap), #000 90deg, #0000 0); mask-size: calc(100% / var(--m)) calc(100% / var(--n)); mask-composite: intersect;
}

Koden ser måske lidt kompleks ud, men takket være CSS-variabler skal vi kun opdatere nogle få værdier for at styre vores matrix af kuber. Har du brug for et 10⨉10 gitter? Opdater --m , --n variabler til 10. Har du brug for et større mellemrum mellem terninger? Opdater --gap værdi. Farveværdierne bruges kun én gang, så opdater dem for en ny farvepalet!

Nu hvor vi har en anden 3D-teknik, lad os bruge den til at bygge variationer af loaderen ved at lege med forskellige animationer. For eksempel, hvad med et gentaget mønster af terninger, der glider uendeligt fra venstre mod højre?

CodePen Embed Fallback

Denne loader definerer fire kuber i en enkelt række. Det betyder vores --n Værdien er 4 , --m er lig med 1 . Med andre ord har vi ikke længere brug for disse!

I stedet kan vi arbejde med --size , --gap variabler i en gitterbeholder:

.loader { --size: 70px; --gap: 15px; width: calc(3 * (1.353 * var(--size) + var(--gap))); display: grid; aspect-ratio: 3;
}

Dette er vores container. Vi har fire kuber, men vil kun vise tre i beholderen ad gangen, så vi altid har én, der glider ind, mens én glider ud. Derfor tager vi højde for bredden 3 og få billedformatet indstillet til 3 også.

Lad os sørge for, at vores terningmønster er sat op til bredden af ​​fire terninger. Vi vil gøre dette på containerens ::before pseudo-element:

.loader::before { content: ""; width: calc(4 * 100% / 3); /* Code to create four cubes */
}

Nu hvor vi har fire terninger i en beholder med tre terninger, kan vi retfærdiggøre terningmønsteret til enden af ​​gitterbeholderen for at flyde over det, og vise de sidste tre terninger:

.loader { /* same as before */ justify-content: end;
}

Her er, hvad vi har indtil videre, med en rød kontur for at vise grænserne for gitterbeholderen:

CodePen Embed Fallback

Nu skal vi bare flytte pseudo-elementet til højre ved at tilføje vores animation:

@keyframes load { to { transform: translate(calc(100% / 4)); }
}
CodePen Embed Fallback

Fik du tricket med animationen? Lad os afslutte dette ved at skjule det overfyldte terningmønster og ved at tilføje et strejf af maskering for at skabe den fading-effekt, som starten og slutningen:

.loader { --size: 70px; --gap: 15px; width: calc(3*(1.353*var(--s) + var(--g))); display: grid; justify-items: end; aspect-ratio: 3; overflow: hidden; mask: linear-gradient(90deg, #0000, #000 30px calc(100% - 30px), #0000);
}
CodePen Embed Fallback

Vi kan gøre dette meget mere fleksibelt ved at indføre en variabel, --n, for at indstille, hvor mange terninger der skal vises i beholderen på én gang. Og da det samlede antal terninger i mønsteret skal være en mere end --n, vi kan udtrykke det som calc(var(--n) + 1).

Her er det fulde:

CodePen Embed Fallback

OK, endnu en 3D-indlæser, der ligner, men hvor kuberne skifter farve efter hinanden i stedet for at glide:

CodePen Embed Fallback

Vi vil stole på en animeret baggrund med background-blend-mode til denne:

.loader { /* ... */ background: linear-gradient(#ff1818 0 0) 0% / calc(100% / 3) 100% no-repeat, /* ... */; background-blend-mode: multiply; /* ... */ animation: load steps(3) 1.5s infinite;
}
@keyframes load { to { background-position: 150%; }
}

Jeg har fjernet den overflødige kode, der blev brugt til at lave det samme layout som det sidste eksempel, men med tre kuber i stedet for fire. Det, jeg tilføjer her, er en gradient defineret med en specifik farve, der blander sig med den kegleformede gradient, ligesom vi gjorde tidligere for 3D-indlæseren for statuslinjen.

Derfra animerer den baggrundsgradientens background-position som en tre-trins animation for at få kuberne til at blinke en ad gangen.

Hvis du ikke er bekendt med de værdier, jeg bruger til background-position og baggrundssyntaksen, kan jeg varmt anbefale en af ​​mine tidligere artikler og en af mine Stack Overflow svar. Du finder en meget detaljeret forklaring der.

Kan vi opdatere antallet af kuber for at gøre det til variable?

Ja, jeg har en løsning på det, men jeg vil gerne have, at du tager et knæk på det i stedet for at indlejre det her. Tag det, vi har lært fra det foregående eksempel, og prøv at gøre det samme med dette - så del dit arbejde i kommentarerne!

Variationer i massevis!

Ligesom de andre tre artikler i denne serie, vil jeg gerne give dig lidt inspiration til at gå videre og skabe dine egne læssere. Her er en samling, der inkluderer de 3D-loadere, vi lavede sammen, plus et par andre til at sætte gang i din fantasi:

CodePen Embed Fallback

Det er en wrap

Jeg håber bestemt, at du har nydt at bruge tid på at lave enkeltelement-læssere med mig de sidste par uger. Det er skørt, at vi startede med tilsyneladende simpel spinner og så gradvist tilføjede nye stykker for at arbejde os selv helt op til 3D-teknikker, der stadig kun bruger et enkelt element i markeringen. Det er præcis, hvordan CSS ser ud, når vi udnytter dens kræfter: skalerbar, fleksibel og genbrugelig.

Tak igen fordi du læste denne lille serie! Jeg melder fra ved at minde dig om, at jeg har en samling af mere end 500 læssere hvis du leder efter flere ideer og inspiration.


Single Element Loaders: Går i 3D! oprindeligt udgivet den CSS-tricks. Du burde få nyhedsbrevet.

Tidsstempel:

Mere fra CSS-tricks