Laders met één element: 3D! PlatoBlockchain-gegevensintelligentie. Verticaal zoeken. Ai.

Laders met één element: 3D!

Voor dit vierde en laatste artikel van onze kleine serie over laders met één element, gaan we 3D-patronen verkennen. Bij het maken van een 3D-element is het moeilijk voor te stellen dat slechts één HTML-element voldoende is om zoiets als alle zes vlakken van een kubus te simuleren. Maar misschien kunnen we wegkomen met iets meer kubus-als in plaats daarvan door alleen de drie voorkanten van de vorm te laten zien - het is heel goed mogelijk en dat is wat we samen gaan doen.

Artikel serie

De gesplitste kubuslader

Hier is een 3D-lader waarbij een kubus in twee delen wordt gesplitst, maar slechts met één enkel element wordt gemaakt:

CodePen Embed-terugval

Elke helft van de kubus is gemaakt met behulp van een pseudo-element:

Laders met één element: 3D! PlatoBlockchain-gegevensintelligentie. Verticaal zoeken. Ai.
Laders met één element: 3D!

Cool toch?! We kunnen een kegelvormig verloop gebruiken met CSS clip-path op het element ::before en ::after pseudos om de drie zichtbare vlakken van een 3D-kubus te simuleren. Negatieve marge is wat de twee pseudos samentrekt om te overlappen en een volledige kubus te simuleren. De rest van ons werk bestaat voornamelijk uit het animeren van die twee helften om nette laders te krijgen!

Laten we eens kijken naar een visual die de wiskunde uitlegt achter de clippad-punten die zijn gebruikt om dit kubusachtige element te maken:

Laders met één element: 3D! PlatoBlockchain-gegevensintelligentie. Verticaal zoeken. Ai.
Laders met één element: 3D!

We hebben onze variabelen en een vergelijking, dus laten we die aan het werk zetten. Eerst stellen we onze variabelen vast en stellen we de grootte in voor de main .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;
}

Tot nu toe niets te gek. We hebben een 150px vierkant dat is opgezet als een flexibele container. Nu stellen we onze pseudos vast:

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

Dat zijn twee helften in de .loader container. We moeten ze erin schilderen, dus dat is waar onze conische gradiënt begint te werken:

.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);
}

Het verloop is er, maar het ziet er raar uit. We moeten clip het aan het element:

.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));
}

Laten we ervoor zorgen dat de twee helften elkaar overlappen met a negatieve marge:

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

Laten we ze nu laten bewegen!

.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)) }
}

Hier is nog een keer de laatste demo:

CodePen Embed-terugval

De voortgangskubuslader

Laten we dezelfde techniek gebruiken om een ​​3D-voortgangslader te maken. Ja, nog steeds maar één element!

CodePen Embed-terugval

We veranderen niets wat betreft het simuleren van de kubus op dezelfde manier als voorheen, behalve het veranderen van de hoogte en aspectverhouding van de lader. De animatie die we maken is gebaseerd op een verrassend eenvoudige techniek waarbij we de breedte van de linkerkant bijwerken terwijl de rechterkant de resterende ruimte vult, dankzij flex-grow: 1.

De eerste stap is om wat transparantie aan de rechterkant toe te voegen met behulp van opacity:

CodePen Embed-terugval

Dit simuleert het effect dat de ene kant van de kubus gevuld is en de andere leeg. Dan werken we de kleur van de linkerkant bij. Om dat te doen, werken we ofwel de drie kleuren in het kegelvormige verloop bij of we doen het door een achtergrondkleur toe te voegen met a background-blend-mode:

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

Met deze truc kunnen we de kleur slechts één keer bijwerken. De rechterkant van de lader past in de drie tinten wit van het kegelvormige verloop om drie nieuwe tinten van onze kleur te creëren, ook al gebruiken we maar één kleurwaarde. Kleur bedrog!

CodePen Embed-terugval

Laten we de breedte van de linkerkant van de lader animeren:

CodePen Embed-terugval

Oeps, de animatie is in het begin een beetje vreemd! Merk je op hoe het begint buiten de kubus? Dit komt omdat we de animatie starten op de 0% breedte. Maar door de clip-path en negatieve marge die we gebruiken, moeten we in plaats daarvan beginnen met onze --_d variabele, die we gebruikten om de . te definiëren clip-path punten en de negatieve marge:

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

Dat is iets beter:

CodePen Embed-terugval

Maar we kunnen deze animatie nog vloeiender maken. Is het je opgevallen dat we iets missen? Laat me je een screenshot laten zien om te vergelijken hoe de uiteindelijke demo eruit zou moeten zien met die laatste demo:

Laders met één element: 3D! PlatoBlockchain-gegevensintelligentie. Verticaal zoeken. Ai.

Het is de onderkant van de kubus! Omdat het tweede element transparant is, moeten we de onderkant van die rechthoek zien, zoals je in het linkervoorbeeld kunt zien. Het is subtiel, maar zou er moeten zijn!

We kunnen een verloop toevoegen aan het hoofdelement en het knippen zoals we deden met de pseudos:

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

Hier is de volledige code als alles eenmaal is samengevoegd:

.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-terugval

Dat is het! We hebben zojuist een slimme techniek gebruikt die pseudo-elementen, kegelvormige gradiënten, clipping, achtergrondvermenging en negatieve marges gebruikt om niet één, maar twee lieflijk uitziende 3D-laders met niets meer dan een enkel element in de opmaak.

Meer 3D

We kunnen nog verder gaan en een oneindig aantal 3D-kubussen simuleren met één element - ja, het is mogelijk! Hier is een raster van kubussen:

CodePen Embed-terugval

Deze demo en de volgende demo's worden op het moment van schrijven niet ondersteund in Safari.

Gek, toch? Nu maken we een herhaald patroon van kubussen gemaakt met een enkel element... en ook geen pseudos! Ik zal niet in detail treden over de wiskunde die we gebruiken (er staan ​​heel specifieke getallen in), maar hier is een figuur om te visualiseren hoe we hier zijn gekomen:

Laders met één element: 3D! PlatoBlockchain-gegevensintelligentie. Verticaal zoeken. Ai.
Laders met één element: 3D!

We gebruiken eerst a conic-gradient om het herhalende kubuspatroon te maken. De herhaling van het patroon wordt bepaald door drie variabelen:

  • --size: Trouw aan zijn naam, dit bepaalt de grootte van elke kubus.
  • --m: Dit staat voor het aantal kolommen.
  • --n: Dit is het aantal rijen.
  • --gap: dit is de opening of afstand tussen de kubussen
.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));
}

Vervolgens passen we een maskerlaag toe met een ander patroon van dezelfde grootte. Dit is het lastigste deel van dit idee. Een combinatie van a . gebruiken linear-gradient en conic-gradient we zullen een paar delen van ons element knippen om alleen de kubusvormen zichtbaar te houden.

.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;
}

De code ziet er misschien een beetje ingewikkeld uit, maar dankzij CSS-variabelen hoeven we alleen maar een paar waarden bij te werken om onze matrix van kubussen te besturen. Een 10⨉10 raster nodig? Update de --m en --n variabelen om 10. Een grotere opening tussen kubussen nodig? Update de --gap waarde. De kleurwaarden worden maar één keer gebruikt, dus update die voor een nieuw kleurenpalet!

Nu we een andere 3D-techniek hebben, gaan we die gebruiken om variaties van de loader te bouwen door met verschillende animaties te spelen. Wat dacht je bijvoorbeeld van een herhalend patroon van kubussen die oneindig van links naar rechts schuiven?

CodePen Embed-terugval

Deze lader definieert vier kubussen in een enkele rij. Dat betekent onze --n Waarde is 4 en --m is gelijk aan 1 . Deze hebben we met andere woorden niet meer nodig!

In plaats daarvan kunnen we werken met de --size en --gap variabelen in een rastercontainer:

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

Dit is onze container. We hebben vier kubussen, maar we willen er slechts drie tegelijk in de container laten zien, zodat we er altijd één hebben die naar binnen schuift terwijl er één naar buiten schuift. Daarom houden we rekening met de breedte met 3 en stel de beeldverhouding in op 3 .

Laten we ervoor zorgen dat ons kubuspatroon is ingesteld voor de breedte van vier kubussen. Dit gaan we doen op de container ::before pseudo-element:

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

Nu we vier kubussen in een container met drie kubussen hebben, kunnen we het kubuspatroon uitvullen naar het einde van de rastercontainer om het te laten overlopen, met de laatste drie kubussen:

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

Dit is wat we tot nu toe hebben, met een rode omtrek om de grenzen van de rastercontainer te tonen:

CodePen Embed-terugval

Nu hoeven we alleen nog het pseudo-element naar rechts te verplaatsen door onze animatie toe te voegen:

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

Snap je de truc van de animatie? Laten we dit afmaken door het overlopende kubuspatroon te verbergen en een vleugje maskering toe te voegen om dat vervagende effect te creëren dat het begin en het einde is:

.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-terugval

We kunnen dit een stuk flexibeler maken door een variabele in te voeren, --n, om in te stellen hoeveel kubussen er tegelijk in de container worden weergegeven. En aangezien het totale aantal kubussen in het patroon één meer moet zijn dan --n, kunnen we dat uitdrukken als calc(var(--n) + 1).

Hier is het volledige ding:

CodePen Embed-terugval

OK, nog een 3D-lader die vergelijkbaar is, maar waarbij de kubussen achter elkaar van kleur veranderen in plaats van te schuiven:

CodePen Embed-terugval

We gaan vertrouwen op een geanimeerde achtergrond met background-blend-mode voor deze:

.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%; }
}

Ik heb de overbodige code verwijderd die werd gebruikt om dezelfde lay-out te maken als het laatste voorbeeld, maar met drie kubussen in plaats van vier. Wat ik hier toevoeg, is een verloop dat is gedefinieerd met een specifieke kleur die past bij het kegelvormige verloop, net zoals we eerder deden voor de 3D-lader van de voortgangsbalk.

Van daaruit animeert het de achtergrondverloop background-position als een animatie in drie stappen om de kubussen één voor één kleuren te laten knipperen.

Als u niet bekend bent met de waarden waarvoor ik gebruik: background-position en de achtergrondsyntaxis, raad ik ten zeerste aan een van mijn vorige artikelen en een mijn Stack Overflow-antwoorden. U vindt daar een zeer gedetailleerde uitleg.

Kunnen we het aantal kubussen bijwerken om er variabelen van te maken?

Ja, ik heb een oplossing daarvoor, maar ik zou graag willen dat je het onder de knie hebt in plaats van het hier in te bedden. Neem wat we van het vorige voorbeeld hebben geleerd en probeer hetzelfde te doen met dit voorbeeld - deel uw werk vervolgens in de opmerkingen!

Variaties in overvloed!

Net als de andere drie artikelen in deze serie, wil ik je graag wat inspiratie geven om aan de slag te gaan en je eigen laders te maken. Hier is een verzameling met de 3D-laders die we samen hebben gemaakt, plus een paar andere om je fantasie de vrije loop te laten:

CodePen Embed-terugval

Het zit er op

Ik hoop echt dat je het leuk vond om de afgelopen weken tijd door te brengen met het maken van laders met één element. Het is gek dat we zijn begonnen met een ogenschijnlijk eenvoudige spinner en vervolgens geleidelijk nieuwe stukken hebben toegevoegd om onszelf helemaal op te werken tot 3D-technieken die nog steeds maar een enkel element in de opmaak gebruiken. Dit is precies hoe CSS eruitziet als we zijn krachten benutten: schaalbaar, flexibel en herbruikbaar.

Nogmaals bedankt voor het lezen van deze kleine serie! Ik meld me af door je eraan te herinneren dat ik een verzameling van meer dan 500 laders als je op zoek bent naar meer ideeën en inspiratie.

Artikel serie


Laders met één element: 3D! oorspronkelijk gepubliceerd op CSS-trucs. Je zou moeten ontvang de nieuwsbrief.

Tijdstempel:

Meer van CSS-trucs