1-Element-CSS-Rainbow Gradient Infinity

0
28

Ich zum ersten mal die Idee auf CSS etwas von der Art, als ich sah, dieses Gefälle infinity logo von Infografik-Paradies:

Der ursprüngliche Verlauf in die Unendlichkeit.

Nach vier Stunden und zwanzig Minuten, von denen über vier Stunden Flossen in die Feinabstimmung der Positionierung, Kanten und highlights… endlich habe ich das Ergebnis unten an:

Meine version des Regenbogen-Farbverlauf Unendlichkeit.

Der Farbverlauf sieht nicht wie in der original-Abbildung, als ich wählte, die zum generieren der rainbow-logisch, anstatt die Dev-Tools picker oder so ähnlich, aber anders als das, denke ich, dass ich ziemlich nah dran—mal sehen, wie ich das geschafft habe!

Markup

Wie Sie wahrscheinlich schon erraten aus dem Titel, das HTML ist nur ein element:

<div class=’∞’></div>

Styling

Die Entscheidung über den Ansatz

Die erste Idee, dass vielleicht in den Sinn kommen, wenn man die oben wäre mit konischen Verläufe als Grenze Bildern. Leider, border-image und border-radius nicht gut zusammen spielen, wie dargestellt durch die interaktive Produkt-demo unter:

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Wann immer wir uns eine Grenze gesetzt-image, border-radius wird einfach ignoriert, so mit den beiden zusammen ist leider keine option.

Also der Ansatz, den wir hier nehmen, ist mit conic-gradient () – Hintergründe und dann loszuwerden, das Teil in der Mitte mit Hilfe einer Maske. Mal sehen, wie das funktioniert!

Erstellen der beiden ∞ Hälften

Wir zunächst entscheiden, auf einen äußeren Durchmesser.

$tun: 12.5 em;

Wir erstellen die beiden Hälften des infinity-symbol mit den ::before und ::after pseudo-Elemente unserer .∞ element. Um diese beiden pseudo-Elemente nebeneinander, wir verwenden Sie ein flex-layout auf Ihre Eltern (die infinity-element .∞). Jeder von Ihnen hat sowohl die Breite und die Höhe gleich dem äußeren Durchmesser $tun. Wir Runden Sie mit einem border-radius von 50%, und wir geben Ihnen eine dummy-hintergrund, so dass wir Sie sehen können.

.∞ {
display: flex;

&:before, &:after {
Breite: $machen; height: $machen;
border-radius: 50%;
background: #000;
Inhalt: “;
}
}

Wir haben auch der .∞ element in der Mitte des übergeordneten Elements (die Körper, in diesem Fall) sowohl vertikal als auch horizontal durch die Verwendung des flexbox-Ansatz.

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Wie konisch-gradient() funktioniert

Um die konisch-gradient() Hintergründe für die beiden haves, müssen wir zuerst verstehen, wie das Kegelschnitt-gradient () – Funktion funktioniert.

Wenn Sie innerhalb des Kegelschnitt-gradient () – Funktion haben wir eine Liste von Haltestellen ohne explizite Positionen, dann wird die erste genommen zu werden, bei 0% (oder 0deg, gleiche Sache), die last ist genommen zu werden bei 100% (oder 360deg), während alle diejenigen, die Links sind gleichmäßig verteilt in [0%, 100%] – Intervall.

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Wenn wir nur 2 Haltestellen, es ist einfach. Die erste ist bei 0%, die zweite (und Letzte) bei 100% und es gibt keine weiteren Stationen dazwischen.

Wenn wir haben 3 Stufen, die erste ist bei 0%, die Letzte (Dritte) bei 100%, während die zweite ist tot in der Mitte von [0%, 100%] – Intervall, bei 50%.

Wenn wir haben 4 Stationen, die erste ist bei 0%, die Letzte (vierte) bei 100%, während die zweite und Dritte split [0%, 100%] Intervall in 3 gleich große Intervalle, positioniert sich an der 33.(3)% und 66.(6)%.

Wenn wir 5 Stationen, die erste ist bei 0%, die Letzte (fünfte) bei 100%, während die zweiten, Dritten und vierten teilen Sie die [0%, 100%] Intervall, in 4 gleich große Intervalle wird positioniert bei 25%, 50% und 75%.

Wenn wir haben 6 Stationen, die erste ist bei 0%, die Letzte (sechste) bei 100%, während die zweite, Dritte, vierte und fünfte teilen Sie die [0%, 100%] Intervall in 5 gleich große Intervalle wird positioniert bei 20%, 40%, 60% und 80%.

Im Allgemeinen, wenn wir n Stationen, die erste ist bei 0%, die Letzte bei 100%, während diejenigen, die in zwischen split [0%, 100%] Intervall in n-1 eqial Abständen spanning 100%/(n-1). Wenn wir die Stationen 0-basierte Indizes, dann wird jeder von Ihnen ist an Position i*100%/(n-1).

Für die erste, i, ist 0, das gibt uns 0*100%/(n-1) = 0%.

Für die letzten (n-TEN), i n-1, die uns die (n-1)*100%/(n-1) = 100%.

Hier wählen wir mit 9 Stationen, was bedeutet, wir teilen Sie die [0%, 100%] Intervall, in 8 gleich große Intervalle.

Okay, aber wie bekommen wir die Stopp-Liste?

Die hsl() Stoppt

Gut, der Einfachheit halber wählen wir erzeugen eine Liste der HSL-Werte. Wir halten die Sättigung und Helligkeit fest, und wir variieren den Farbton. Der Farbton ist ein Winkel-Wert, der geht von 0 bis 360, wie wir hier sehen können:

Visuelle Darstellung der Farbton-Skala von 0 bis 360 (Sättigung und die Helligkeit wird konstant gehalten).

Mit diesem im Verstand, können wir eine Liste erstellen für hsl() Stoppt mit festen Sättigung und Helligkeit und unterschiedlichem Farbton, wenn wir wissen, dass der start Farbton $hue-start, der Farbton Palette $hue-Reihe (dies ist das Ende hue minus der start-Farbton) und die Anzahl der Stopps, $num-Haltestellen.

Sagen wir, wir halten die Sättigung und die Helligkeit fest auf 85% und 57% (willkürliche Werte, die können wahrscheinlich gezwickt werden, um bessere Ergebnisse zu erzielen) und, zum Beispiel, könnten wir gehen von einem start Farbton von 240 zu Ende, Farbton, 300 und verwenden Sie 4 Haltestellen.

Um zu generieren, diese Liste der Haltestellen, die wir verwenden, um eine get-Haltestellen () – Funktion, dass diese drei Dinge als Argumente:

@function get-Stationen($hue-start, $hue-Reihe, $num-Haltestellen) {}

Wir erstellen die Liste der Haltestellen $Liste, die ursprünglich leer ist (und die wir wieder zurückkehren werden am Ende, nachdem wir füllen es). Auch wir berechnen die Spannweite eines gleichen Abständen unsere Stationen aufgeteilt das vollständige start-und end-Intervall, in ($unit).

@function get-Stationen($hue-start, $hue-Reihe, $num-Haltestellen) {
$Liste: ();
$unit: $hue-Reihe/($num-Stoppt – 1);

/* Auffüllen der Liste der Haltestellen $Liste */

@return $Liste
}

Um zu füllen unsere $Liste, die wir Durchlaufen Sie die Stationen, die Berechnung der aktuellen Farbton, verwenden Sie den aktuellen Farbton zu erzeugen, die hsl () – Wert auf, dass zu stoppen und dann und fügen Sie es der Liste der Haltestellen:

@for $i von 0 bis $num-hält {
$hue-curr: $hue-Anfang + $i*$Einheit;
$Liste: $Liste, hsl($hue-curr, 85%, 57%);
}

Wir können nun die stop-Liste diese Funktion gibt für jede Art von Gefälle, wie es aus gesehen werden kann die Anwendungsbeispiele für diese Funktion gezeigt, in der interaktiven demo unten (navigation funktioniert sowohl mit den vorherigen/nächsten Tasten an den Seiten sowie die Pfeiltasten und der Bild-ab/ Bild-auf-Tasten):

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Beachten Sie, wie, wenn Sie unser Angebot an einem Ende des [0, 360] – Intervall, weiter geht es aus dem anderen Ende. Zum Beispiel, wenn die start-Farbton ist 30 und ist die range -210 (das vierte Beispiel), können wir nur runter gehen bis 0, dann haben wir weiterhin noch 360.

Die konischen Verläufe für die beiden Hälften

Okay, aber wie bestimmen wir die $hue-start und $hue-Reihe, insbesondere für unseren Fall?

In der original-Bild, dann ziehen wir eine Linie zwischen der zentralen Punkte der beiden Hälften der Schleife und, ausgehend von dieser Linie, weiter im Uhrzeigersinn in beiden Fällen sehen wir, wo wir beginnen und wo wir enden, in die [0, 360] – Intervall und Farbton, was von anderen Farben, die wir passieren.

Wir starten von der Verbindungslinie der zentralen Punkte der beiden Hälften, und wir gehen um Sie herum im Uhrzeigersinn.

Zur Vereinfachung der Dinge, die wir betrachten, das wir Durchlaufen die ganze [0, 360] Farbton-Skala geht es entlang unserer infinity-symbol. Dies bedeutet, dass die Reihe für jedes Semester wird 180 ° (die Hälfte von 360) im absoluten Wert.

Keywords Tonwerte Korrespondenz für Sättigung und Helligkeit fest bei 100% und 50%.

Auf der linken Hälfte, wir beginnen mit etwas, das aussieht wie es in zwischen eine Art von cyan-blau (Farbton 180) und eine Art Kalk (Farbton 120), so nehmen wir die start-Farbton zu der Durchschnittswert der Farbtöne dieser beiden (180 + 120)/2 = 150.

Der plan für die linke Hälfte.

Wir bekommen eine Art von rot, die 180 Weg von der start-Wert, also bei 330, ob wir subtrahieren oder hinzufügen von 180:

(150 – 180 + 360)%360 = (150 + 180 + 360)%360 = 330

So… gehen wir nach oben oder unten? Gut, fahren wir durch gelb, das sind rund 60 auf die Farbton-Ebene, so dass der Abstieg von 150, nicht. Going down bedeutet, dass unser Sortiment ist negativ (-180).

Der plan für die Rechte Hälfte.

Auf der rechten Hälfte, beginnen wir auch von den gleichen Farbton in der zwischen cyan-und lime (150) und wir auch am Ende auf die gleiche Art von rot (330), aber dieses mal fahren wir durch blues, das sind rund 240, D. H. wir gehen von unserem start Farbton von 150, so dass unser Angebot positiv ist in diesem Fall (180).

So weit wie die Anzahl der Haltestellen geht, 9 sollte ausreichen.

Aktualisieren Sie nun unseren code mit den Werten für die linke Hälfte als Standardwerte für unsere Funktion:

@function get-Stationen($hue-start: 150, $hue-Bereich: -180, $num-stops: 9) {
/* das gleiche wie vorher */
}

.∞ {
display: flex;

&:before, &:after {
/* das gleiche wie vorher */
hintergrund: Kegelschnitt-gradient(get-Haltestellen());
}

&:after {
hintergrund: Kegelschnitt-gradient(get-Stationen(150, 180));
}
}

Und nun unsere zwei Scheiben haben einen Kegelschnitt-gradient() Hintergründe:

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Jedoch wollen wir nicht diese konischen Verläufe beginnen von der Spitze.

Für die erste CD, die wir wollen, um aus der Recht—, dass die auf 90° von oben im Uhrzeigersinn (positive) Richtung. Für die zweite Scheibe, wir wollen es auf der Startseite von Links—das ist bei 90° von oben in die andere (negative) Richtung, das entspricht 270° von oben im Uhrzeigersinn (weil negative Winkel nicht zu funktionieren scheinen aus irgendeinem Grund).

Winkel-offsets von oben für unsere zwei Hälften.

Wir ändern unseren code um dies zu erreichen:

.∞ {
display: flex;

&:before, &:after {
/* das gleiche wie vorher */
hintergrund: Kegelschnitt-gradient(von 90deg, get-Haltestellen());
}

&:after {
hintergrund: Kegelschnitt-gradient(von 270deg, get-Stationen(150, 180));
}
}

So weit, So gut!

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Von 🥧 zu 🍩

Der nächste Schritt ist die Löcher, die aus unseren zwei Hälften. Wir tun dies mit einer Maske oder, genauer gesagt, mit einem radial-gradient (). Diese schneidet Edge-Unterstützung für jetzt, aber da ist etwas, das in Entwicklung ist, ist es wahrscheinlich eine cross-browser-Lösung, die irgendwann in der nicht allzu Fernen Zukunft.

Denken Sie daran, dass CSS-gradient-Masken, alpha Masken standardmäßig (und nur Firefox derzeit erlaubt das ändern dieser über Maske-Modus), was bedeutet, dass nur der alpha-Kanal ankommt. Die überlagerung der Maske über unsere element macht aus jedem pixel dieses element verwenden Sie den alpha-Kanal des entsprechenden pixels der Maske. Wenn die Maske pixel ist vollständig transparent (alpha-Wert ist 0), dann so wird das entsprechende pixel des Elements.

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Um um die Maske zu erstellen, berechnen wir den äußeren radius $ro (die Hälfte der äußere Durchmesser $tun) und der innere radius $ri (ein Bruchteil von dem äußeren radius $ro).

$ro: .5*$;
$ri: .52*$ro;
$m: radial-gradient(transparent $ri, rot 0);

Wir legen Sie dann die Maske auf die zwei Hälften:

.∞ {
/* das gleiche wie vorher */

&:before, &:after {
/* das gleiche wie vorher */
Maske: $m;
}
}

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Dies sieht perfekt aus in Firefox, aber die Kanten der radialen Verläufen mit abrupten übergänge von einer Haltestelle zu einer anderen hässlich Aussehen in Chrom und, folglich, so haben die inneren Kanten unserer Ringe.

Close-up von dem inneren Rand der rechten Hälfte in Chrom.

Das Update würde hier nicht um einen abrupten übergang zwischen den Haltestellen, sondern verteilen sich über einen kleinen Abstand, sagen wir, die Hälfte eines pixels:

$m: radial-gradient(transparent calc(#{$ri} – .5px), rot $ri);

Wir haben nun entfernen Sie die gezackten Kanten in Chrom:

Close-up von dem inneren Rand der rechten Hälfte in Chrome nach dem verstreichen der übergang zwischen den Haltestellen über ein halbes pixel.

Der folgende Schritt ist der Ausgleich der zwei Hälften, so dass Sie bilden tatsächlich ein infinity-symbol. Die sichtbaren kreisförmigen Streifen haben die gleiche Breite, die Differenz zwischen dem äußeren radius $ro und die inneren radius $ri. Das bedeutet, wir müssen jede Verschiebung seitlich um die Hälfte dieser Differenz $ri $ri.

.∞ {
/* das gleiche wie vorher */

&:before, &:after {
/* das gleiche wie vorher */
Marge: 0 (-.5*($ro – $ri));
}
}

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Schneidende Hälften

Wir sind näher, wir haben aber noch ein sehr großes problem hier. Wir wollen nicht den rechten Teil der Schleife werden komplett über die linke. Wir wollen stattdessen die Obere Hälfte des rechten Teils vorbei zu sein, der linke Teil und die untere Hälfte des linken Teils werden über den rechten Teil.

Also wie erreichen wir das?

Wir nehmen einen ähnlichen Ansatz, vorgestellt in einem älteren Artikel: mit 3D!

Um zu verstehen, wie dies funktioniert, betrachten Sie die zwei Karte-Beispiel unten. Wenn wir drehen Sie um die x-Achse, Sie sind nicht in der Ebene der Bildschirm nicht mehr. Eine positive Drehung bringt der Unterseite nach vorne und schiebt die Spitze zurück. Eine negative Drehung bringt die Spitze nach vorne und schiebt den Boden zurück.

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Beachten Sie, dass die demo oben funktioniert nicht in Edge.

Also, wenn wir geben der linken eine positive Drehung, und die Rechte eine negative Drehung, dann die Obere Hälfte des rechts wird vor der oberen Hälfte der linken und Umgekehrt für die unteren Hälften.

Addiing die Perspektive macht was näher an unseren Augen erscheint größer und was weiter entfernt ist, erscheint kleiner und wir verwenden viel kleiner Winkel. Ohne ihn haben wir die 3D-Ebene Kreuzung ohne die 3D-Darstellung.

Beachten Sie, dass unsere beiden Hälften müssen in der gleichen 3D-Kontext, etwas, das erzielt, indem man transform-style: preserve-3d auf der .∞ element.

.∞ {
/* das gleiche wie vorher */
transform-style: preserve-3d;

&:before, &:after {
/* das gleiche wie vorher */
transform: rotatex(1deg);
}

&:after {
/* das gleiche wie vorher */
transform: rotatex(-1deg);
}
}

Und jetzt sind wir fast da, aber nicht ganz:

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Fine-tuning

Wir haben eine kleine rötliche Streifen in der Mitte, da die Steigung endet und die Schnittlinie nicht ganz übereinstimmen:

Close-up der kleinen Ausgabe an der Kreuzung der beiden Hälften.

Eine ziemlich unschöne, aber effiziente Lösung ist das hinzufügen einer 1px übersetzung vor der Drehung auf den rechten Teil (dem ::after-pseudo-element):

.∞:nach { transform: translate(1px) rotatex(-1deg) }

Viel besser!

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Diese ist noch nicht perfekt aber. Da die inneren Kanten der unsere beiden Ringe sind ein bisschen unscharf, der übergang zwischen Ihnen und dem knackigen äußeren ein wenig seltsam aussieht, so können wir vielleicht besser dort:

Close-up-of-continuity-Problem (scharfe äußere Kanten treffen verschwommen inneren).

Eine schnelle Lösung wäre hier hinzufügen eines radial-gradient () – Abdeckung auf jeder der beiden Hälften. Diese Abdeckung ist transparent weiß für die meisten unmaskiert Teil die zwei Hälften und geht in die Feste, weiße Zeit beide Ihren inneren und äußeren Rändern, so dass wir eine nette Kontinuität:

$gc: radial-gradient(#fff $ri, rgba(#fff, 0) calc(#{$ri} + 1px),
rgba(#fff, 0) calc(#{$ro} – 1px), #fff calc(#{$ro -} – .5px));

.∞ {
/* das gleiche wie vorher */

&:before, &:after {
/* das gleiche wie vorher */
hintergrund: $gc, konisch-gradient(von 90deg, get-Haltestellen());
}

&:after {
/* das gleiche wie vorher */
hintergrund: $gc, konisch-gradient(von 270deg, get-Stationen(150, 180));
}
}

Der Vorteil wird umso deutlicher, sobald wir einen dunklen hintergrund, um den Körper:

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Jetzt sieht es besser aus, auch beim Zoomen in:

Nicht mehr scharfe Gegensatz zwischen inneren und äußeren Rändern.

Das endgültige Ergebnis

Schließlich, fügen wir einige prettifying berührt durch die Schichtung etwas subtiler radialen Farbverlauf highlights über die zwei Hälften. Dies war der Teil, der nahm, der mich am meisten da es sich um die geringste Menge an Logik und die Menge von Versuch und Irrtum. An diesem Punkt, ich habe gerade geschichtet ist das ursprüngliche Bild unter der .∞ element, die beiden Hälften, halb-transparente und begann, hinzufügen von Farbverläufen und optimieren Sie, bis Sie so ziemlich abgestimmt highlights. Und Sie können sehen, wenn ich krank, weil das ist, wenn die Positionswerte werden gröbere Approximationen mit weniger Dezimalstellen.

Ein weiterer cool-touch-würde sein Schatten auf die ganze Sache mit einem filter auf den Körper. Leider bricht die 3D-Kreuzung Effekt in Firefox, was bedeutet, dass wir nicht fügen Sie es dort auch.

@nicht unterstützt (-moz-transform: scale(2)) {
filter: drop-shadow – (.25em .25em .25em #000)
drop-shadow – (.25em .25em .5em #000);
}

Wir haben nun die endgültige statische Ergebnis!

Finden Sie den Stift, indem Sie thebabydino (@thebabydino) auf CodePen.

Würzen es mit animation!

Als ich das erste gemeinsame demo, ich habe gefragt, zu animieren. Anfänglich dachte ich, dies wäre kompliziert, aber dann traf es mich, dass Dank Houdini, es muss nicht sein!

Wie bereits in meinem vorherigen Artikel, können wir Sie animieren, sich in zwischen den Haltestellen, sagen wir, eine rot, eine blau. In unserem Fall, die Sättigung und Helligkeit Komponenten des hsl () – Werte verwendet, um generieren die Regenbogen-Farbverlauf bleiben konstant, alle diese änderungen wird der Farbton.

Für jede und jeden zu stoppen, der Farbton geht von seinem Anfangswert auf seinen ursprünglichen Wert plus 360, also die übergabe durch den gesamten Farbton-Skala in den Prozess. Dies ist äquivalent zur Erhaltung des ursprünglichen Farbtons konstant und Variation von einem offset. Dieser offset –off ist die benutzerdefinierte Eigenschaft, die wir animieren.

Leider, dies bedeutet, dass die Unterstützung beschränkt sich auf Blink-Browser mit der Experimental-Web-Platform-features – flag aktiviert.

Die Experimental-Web-Platform-features flag in Chrom.

Noch, mal sehen, wie wir es alle in code!

Für den Anfang ändern wir die get-Haltestellen () – Funktion, so dass die aktuellen Farbton zu jeder Zeit ist der ursprüngliche Farbton des aktuellen stop $hue-curr plus unsere offset – –aus:

$Liste: $Liste, hsl(calc(#{$hue-curr} + var(–off, 0)), 85%, 57%);

Als Nächstes registrieren wir diese benutzerdefinierte Eigenschaft:

CSS.registerProperty({
name: ‘–off’,
syntax: ‘<Anzahl>’,
initialValue: 0;
})

Und schließlich, wir animieren, es an 360:

.∞ {
/* das gleiche wie vorher */

&:before, &:after {
/* das gleiche wie vorher */
animation: Verschiebung 2s linear infinite;
}
}

@keyframes-shift – {{ –off: 360 } }

Das gibt uns unsere animierten Farbverlauf Unendlichkeit!

Animierte ∞ – logo (live-demo, Blink nur mit dem flag aktiviert).

Das ist es! Ich hoffe, Sie habe es genossen, dieses eintauchen in das, was getan werden kann, mit CSS in diesen Tagen!

Das Jetpack WordPress-plugin läuft auf dieser Website, indem Sie nicht nur die verwandten Beiträge unten, aber die Sicherheit und backups, Markdown-support, site-Suche, Kommentar-Formularen, social-network-verbindungen und vieles mehr!