Warum gibt es überhaupt `repeating-linear-gradient`?

Avatar of Ana Tudor
Ana Tudor am

DigitalOcean bietet Cloud-Produkte für jede Phase Ihrer Reise. Starten Sie mit 200 $ kostenlosem Guthaben!

Alles begann mit dieser Frage, die Keith Clark kürzlich auf Twitter gestellt hat.

CSS repeating-linear-gradients, brauchen wir das? Kann man nicht dasselbe mit einem linear-gradient und background-size erreichen?

Das ist eine gute Frage.

Ihre Cousins, repeating radial gradients, sind definitiv nützlich. Sie haben mich davon bewahrt, Dutzende von Stops in einem normalen radial-gradient schreiben zu müssen, wenn ich das Aussehen einer Vinyl-Schallplatte mit CSS reproduzieren wollte.

Vinyl-Schallplatte mit repeating-radial-gradient

Aber repeating-linear-gradient?

Bis zu diesem Jahr war ich auch davon überzeugt, dass sie nutzlos sind. Aber Anfang Februar, während ich an einer Canvas-Demo arbeitete, bin ich der Falle aufgesessen, das Bedienfeld für diese Demo zu gestalten und habe dabei über 100 Slider-Designs reproduziert, die ich online gefunden habe, wobei ich (selbst auferlegt) die Einschränkung hatte, nur einen Range-Input pro Slider zu verwenden.

Slider-Beispiele

Warnung: Obwohl ich dabei viel gelernt habe, bin ich nie zurückgegangen, um das Gelernte auf die bereits codierten Slider anzuwenden, daher würde ich sie, mit Ausnahme der letzten paar, nicht wirklich als gute Ressource empfehlen. Außerdem: Wenn ich nie wieder einen Range-Input gestalten muss, ist es mir schon zu viel.

Einige dieser gestalteten Range-Inputs hatten gestreifte Füllungen oder Lineale, sodass sie ziemlich oft Farbverläufe, insbesondere wiederholende lineare Farbverläufe, erforderten. Ich habe wiederholende lineare Farbverläufe genau deshalb verwendet, weil sich herausstellte, dass normale lineare Farbverläufe nicht ausreichten. Lassen Sie uns sehen, warum!

Wir beginnen damit, das folgende Muster nachzubilden

Einfaches Streifenmuster

Es hat schwarze und blaue Streifen, wobei die blauen Streifen doppelt so breit sind wie die schwarzen. Wenn die schwarzen Streifen eine Breite von .25em haben, lautet der Code, um diesen Effekt mit repeating-linear-gradient zu erzielen:

background: repeating-linear-gradient(135deg, 
  #000, #000 .25em /* black stripe */, 
  #0092b7 0, #0092b7 .75em /* blue stripe */
);

Der Farbverlauf beginnt in der oberen linken Ecke mit einem Winkel von 135°. Wenn Sie eine Auffrischung dazu benötigen, wie lineare Farbverläufe und ihre Winkel funktionieren, lesen Sie diese Erklärung (ignorieren Sie den Teil über die alte Syntax, diese haben wir nun hinter uns gelassen). Es gibt einen schwarzen Streifen von 0 bis .25em entlang der Farbverlauflinie, dann einen blauen Streifen von .25em bis .75em (.75em - .25em = .5em = die Breite des blauen Streifens = 2*.25em = doppelt so breit wie der schwarze Streifen). Wir können ihn in diesem Pen sehen

Siehe den Pen einfaches repeating-linear-gradient Muster von Ana Tudor (@thebabydino) auf CodePen.

Versuchen wir nun, dasselbe mit einfachem linear-gradient und background-size zu erreichen. Wir machen den Hintergrund zu einem kleinen Quadrat mit einer Diagonale, die sich zur Breite eines schwarzen Streifens (.25em) und der Breite eines blauen Streifens (.5em) addiert. Die Diagonale eines Quadrats ist die Kante des Quadrats mal √2, und wenn wir wissen, dass die Diagonale .25em + .5em = .75em beträgt, dann ist die Kante des background-size-Quadrats .75em/sqrt(2). Dies führt uns zum folgenden Code

background: linear-gradient(135deg, #000 .25em, #0092b7 0);
background-size: .75em/sqrt(2) .75em/sqrt(2);

Hmm, das sieht nicht so aus, wie wir es erreichen wollten...

Siehe den Pen einfaches linear-gradient Muster – Schritt 1 von Ana Tudor (@thebabydino) auf CodePen.

Was, wenn wir den .25em breiten schwarzen Streifen in die Mitte setzen? Versuchen wir es!

background: linear-gradient(135deg, 
  #0092b7 calc(50% - .125em) /* blue corner */, 
  #000 0, #000 calc(50% + .125em) /* black stripe */, 
  #0092b7 0 /* blue corner */
);
background-size: .75em/sqrt(2) .75em/sqrt(2);

Es ist jetzt schon etwas näher dran, aber es sieht immer noch nicht gut aus.

Siehe den Pen einfaches linear-gradient Muster – Schritt 2 von Ana Tudor (@thebabydino) auf CodePen.

Wenn wir hineinzoomen, wird deutlicher, was das Problem ist und was wir dagegen tun müssen. Wir müssen diese Ecken mit Schwarz ausfüllen.

Problem an den Ecken beim Hineinzoomen

Das bedeutet, dass am Anfang und am Ende der Farbverlauflinie ein kleiner schwarzer Streifen hinzugefügt werden muss. Jeder davon wird halb so breit sein wie der ursprüngliche schwarze Streifen in der Mitte (also die Hälfte von .25em, was .125em entspricht).

background: linear-gradient(135deg, 
  #000 .125em /* black corner */, 
  #0092b7 0, #0092b7 calc(50% - .125em) /* blue stripe */, 
  #000 0, #000 calc(50% + .125em) /* black stripe */, 
  #0092b7 0, #0092b7 calc(100% - .125em) /* blue stripe */, 
  #000 0 /* black corner */
);
background-size: .75em/sqrt(2) .75em/sqrt(2);

Es sieht... etwas besser aus?

Siehe den Pen einfaches linear-gradient Muster – Schritt 3 von Ana Tudor (@thebabydino) auf CodePen.

Es ist immer noch nicht das, was wir wollen, denn jetzt sind die blauen Streifen zu schmal. Das liegt daran, dass die Diagonalberechnungen nicht mehr stimmen. Wenn wir von der oberen linken Ecke zur unteren rechten Ecke gehen, haben wir jetzt einen halben schwarzen Streifen (.125em), einen blauen Streifen (.5em), einen schwarzen Streifen (.25em), einen weiteren blauen Streifen (.5em) und noch einen halben schwarzen Streifen (.125em). Das ergibt eine Diagonale von 1.5em, was bedeutet, dass wir die background-size auf 1.5em/sqrt(2) 1.5em/sqrt(2) ändern müssen.

Siehe den Pen einfaches linear-gradient Muster – Schritt 4 von Ana Tudor (@thebabydino) auf CodePen.

Perfekt! Es ist visuell dasselbe Ergebnis wie in der repeating-linear-gradient-Version. Aber in diesem Fall ist es zu viel Arbeit, zu viele Berechnungen, zu viel Code, zu viel Risiko für Rundungsfehler (die obige Demo *wird brechen*, wenn wir die font-size auf einen seltsamen Wert wie 1.734em setzen, der keine ganze Pixelzahl ergibt).

Und falls Sie noch nicht überzeugt sind, dass repeating-linear-gradient in diesem Fall die bessere Lösung ist, stellen wir uns vor, der Winkel des Farbverlaufs ist nicht 135°, sondern etwas anderes... sagen wir 120°.

Einfaches Streifenmuster (120°)

Mit repeating-linear-gradient ist der Code fast derselbe wie zuvor, wir müssen nur 135deg durch 120deg ersetzen.

Siehe den Pen einfaches repeating-linear-gradient Muster v2 von Ana Tudor (@thebabydino) auf CodePen.

In Firefox und Edge/IE scheint alles in Ordnung zu sein, aber der Übergang von Blau zu Schwarz sieht in Chrome nicht gut aus. Wir können das beheben, indem wir den Übergang nicht scharf machen und einen Abstand von 1px dazwischen lassen.

background: repeating-linear-gradient(120deg, 
  #0092b7 0, 
  #000 1px /* transition from previous blue stripe */, #000 .25em, 
  #0092b7 calc(.25em + 1px) /* from black to blue */, #0092b7 .75em
);

Wir verwenden diesen Pen, um zu testen, ob dies das Chrome-Problem behebt

Siehe den Pen einfaches repeating-linear-gradient Muster v2 (Chrome-Fix) von Ana Tudor (@thebabydino) auf CodePen.

Mit dem herkömmlichen linear-gradient müssen wir auch den Winkel von 135deg auf 120deg ändern. Aber das reicht dieses Mal nicht aus.

Siehe den Pen einfaches linear-gradient Muster v2 – Schritt 1 von Ana Tudor (@thebabydino) auf CodePen.

Wir müssen auch die Abmessungen von background-size ändern, da dies kein Quadrat mehr ist. Die x-Dimension wird 1.5em*abs(cos(120deg)) sein, während die y-Dimension 1.5em*abs(sin(120deg)) sein wird.

Siehe den Pen einfaches linear-gradient Muster v2 – Schritt 2 von Ana Tudor (@thebabydino) auf CodePen.

Auch hier sehen die Kanten in Chrome nicht gut aus, daher müssen wir den 1px-Abstand-Trick anwenden.

Siehe den Pen einfaches linear-gradient Muster v2 (Chrome-Fix) von Ana Tudor (@thebabydino) auf CodePen.

Die linear-gradient-Alternative ist nicht schön, aber sie existiert.

Gibt es etwas, das repeating-linear-gradient tun kann, was ein einfacher linear-gradient und die richtige background-size *überhaupt nicht* können?

Nun... **ja!**

Wenn Sie auf die eingangs gezeigten Slider-Beispiele geachtet haben, wird der oben reproduzierte gestreifte Farbverlauf verwendet, um die Schiene des Sliders vor dem Zeiger (links vom Zeiger) zu füllen.

IE und Firefox haben dafür spezielle Pseudo-Elemente (-ms-fill-lower bzw. -moz-progress) und wir müssen nur den zuvor erstellten Hintergrund auf diese Pseudos legen.

Aber für WebKit-Browser ist die einzige Möglichkeit, diese gestreifte Füllung zu erhalten, einen weiteren Hintergrund über den regulären für die Slider-Schiene zu legen und dann anzupassen, wie viel von der Schiene er abdeckt, während sich der Zeiger des Sliders bewegt. Dies schafft ein großes Problem mit dem einfachen linear-gradient. Wir können nicht steuern, wie viel von der Schiene er abdeckt, indem wir background-size verwenden, da *wir background-size bereits zur Erstellung des gestreiften Looks verwenden*. Darüber hinaus *wiederholen sich Farbverläufe entweder unendlich oder gar nicht.*

Es wäre wahrscheinlich cool, wenn wir für background-repeat numerische Werte angeben könnten, so wie wir es für animation-iteration-count können. Etwas wie background-repeat: .5 1.5 würde dazu führen, dass die Hälfte des Hintergrunds horizontal angezeigt wird und anderthalb Kacheln vertikal angezeigt werden. Aber das können wir nicht. Vielleicht gibt es eine andere Möglichkeit, einen linear-gradient nur innerhalb bestimmter Grenzen wiederholen zu lassen?

Nun, die einzige Möglichkeit, mit einem einfachen alten linear-gradient und background-size etwas zu erstellen, das dem gewünschten nahekommt, ist, identische Farbverläufe zu stapeln und sie nacheinander zu positionieren, während sie sich in mindestens einer Richtung nicht wiederholen dürfen.

Zum Beispiel, wenn sie nur einen Teil des Elements horizontal abdecken sollen, müssten wir background-repeat: repeat-y setzen. Der erste Hintergrund-Farbverlauf würde horizontal bei 0*$size-x beginnen, der zweite bei 1*$size-x und so weiter... wobei $size-x die x-Komponente von background-size ist. Das folgende Bild veranschaulicht, wie das funktionieren würde

Hintergründe nacheinander in einer Reihe positioniert

Aber das funktioniert nur, um zu ändern, wie viel von der Schiene der gestreifte Teil abdeckt *in Schritten von $size-x*. Es ist nutzlos, wenn wir eine feinere Kontrolle wünschen. Außerdem ist es wirklich hässlich, vielleicht 20 identische Farbverläufe zu stapeln.

background-image: 
  linear-gradient(135deg, 
      #000 0.125em, 
      #0092b7 0, #0092b7 calc(50% - .125em), 
      #000 0, #000 calc(50% + .125em), 
      #0092b7 0, #0092b7 calc(100% - .125em), #000 0
  ), 
  linear-gradient(135deg, 
      #000 0.125em, 
      #0092b7 0, #0092b7 calc(50% - .125em), 
      #000 0, #000 calc(50% + .125em), 
      #0092b7 0, #0092b7 calc(100% - .125em), #000 0
  ) /* repeat as many times as needed */;
;
background-position: 
  0*1.5em/sqrt(2) 0, 1*1.5em/sqrt(2) /* repeat for 2, 3, 4 and so on... */;
background-repeat: repeat-y;

Ugh. Den exakt gleichen Farbverlauf 20 Mal zu wiederholen ist schrecklich. Wir könnten Sass besser machen, aber der generierte CSS wird trotzdem hässlich aussehen.

$grad: linear-gradient(135deg, 
      #000 0.125em, 
      #0092b7 0, #0092b7 calc(50% - .125em), 
      #000 0, #000 calc(50% + .125em), 
      #0092b7 0, #0092b7 calc(100% - .125em), #000 0
  );

background-image: $grad, $grad /* repeat as many times as needed */;
background-position: 
  0*1.5em/sqrt(2) 0, 1*1.5em/sqrt(2) /* repeat for 2, 3, 4 and so on... */;
background-repeat: repeat-y;

Der folgende Pen zeigt diese Methode in Aktion

Siehe den Pen begrenzen Sie einen linear-gradient innerhalb bestimmter Grenzen von Ana Tudor (@thebabydino) auf CodePen.

Kurz gesagt, mein Rat ist: Tun Sie das nicht! Der Code ist furchtbar und fehleranfällig, wir könnten leicht Lücken zwischen den Farbverläufen bei bestimmten Hintergrundgrößen oder beim Zoomen haben.

Wir haben eine viel bessere Methode zur Verfügung. Wir können begrenzen, wie viel des Elements ein repeating-linear-gradient abdeckt (unabhängig von den Abmessungen des sich wiederholenden Teils), indem wir background-size verwenden und background-repeat auf no-repeat setzen.

Siehe den Pen begrenzen Sie einen repeating-linear-gradient innerhalb bestimmter Grenzen von Ana Tudor (@thebabydino) auf CodePen.

So konnte ich steuern, wie viel von der Schiene des Sliders mit dem gestreiften Farbverlauf gefüllt wurde, jedes Mal wenn sich der Wert des Zeigers des Sliders änderte – indem ich die x-Komponente von background-size änderte.

Die gleiche Idee hilft, zu begrenzen, wie weit die Lineale reichen, wenn wir nicht wollen, dass sie die gesamte Länge des Sliders abdecken. Nehmen wir an, wir wollen sie auch horizontal in der Mitte haben, was die x-Komponente von background-position zu 50% macht. So würde ein sehr einfaches Lineal erstellt werden.

width: 19em;
background: 
  repeating-linear-gradient(90deg, 
      #c8c8c8, #c8c8c8 0.125em /* lines */, 
      transparent 0.125em, transparent 1.25em /* space between */
  ) 50% no-repeat;
background-size: 12.625em /* = 10*1.25em + .125em */ .5em;

Und wir können das Ergebnis in diesem Pen sehen

Siehe den Pen einfaches Lineal, das das gesamte Element nicht abdeckt von Ana Tudor (@thebabydino) auf CodePen.

Um sowohl Haupt- als auch Nebenlinien zu haben, müssen wir einen zweiten wiederholenden Farbverlauf hinzufügen, der sich im doppelten Intervall des ersten wiederholt und doppelt so hoch ist.

background: 
  repeating-linear-gradient(90deg, /* major */
      #c8c8c8, #c8c8c8 .125em /* lines */, 
      transparent , transparent 2.5em /* space between */
  ) 50% no-repeat, 
  repeating-linear-gradient(90deg, /* minor */
      #c8c8c8, #c8c8c8 .125em /* lines */, 
      transparent , transparent 1.25em /* space between */
  ) 50% no-repeat;
background-size: 12.625em 1em, 12.625em .5em;

Das Ergebnis ist in diesem Pen zu sehen

Siehe den Pen Lineal, das das gesamte Element nicht abdeckt #2 von Ana Tudor (@thebabydino) auf CodePen.

Wir könnten auch die y-Komponente von background-position anpassen, damit sie oben oder unten ausgerichtet sind. Zum Beispiel könnten wir so etwas tun

background-position: right 50% bottom 2.25em;

Genau diese Art von Lineal wurde in einem der Beispiele eingangs verwendet.

Siehe den Pen Lineal, das das gesamte Element nicht abdeckt #3 von Ana Tudor (@thebabydino) auf CodePen.

Die Zeigergriffe im folgenden Beispiel wurden auf genau die gleiche Weise erstellt.

Zeigergriffe

Es gibt zwei identische wiederholende lineare Farbverläufe, beide horizontal auf das Doppelte der Größe des wiederholenden Teils plus die Breite des nicht-transparenten Teils begrenzt. Horizontal ist der erste bei 25% und der zweite bei 75% positioniert.

background: 
  repeating-linear-gradient(90deg,
    #6b4c1e, #6b4c1e 1px, 
    #e1ba75 0, #e1ba75 2px, 
    transparent 0, transparent 4px
  ) 25% 50% /* left */, 
  repeating-linear-gradient(90deg,
    #6b4c1e, #6b4c1e 1px, 
    #e1ba75 0, #e1ba75 2px, 
    transparent 0, transparent 4px
  ) 75% 50% /* right */
  orange;
background-repeat: no-repeat;
background-size: 10px 10px;

Aber das ist eine sehr WET (Repetitive) Art, Code zu schreiben. Wir könnten es mit Sass wartungsfreundlicher gestalten.

$grip: repeating-linear-gradient(90deg,
  #6b4c1e, #6b4c1e 1px, 
  #e1ba75 0, #e1ba75 2px, 
  transparent 0, transparent 4px); /* we use this twice */

background: 
  $grip 25% 50% /* left */, 
  $grip 75% 50% /* right */
  orange;
background-repeat: no-repeat;
background-size: 10px 10px;

Dies ergibt das folgende Ergebnis.

Siehe den Pen Zeigergriffe von Ana Tudor (@thebabydino) auf CodePen.

Wiederholende Farbverläufe waren früher ein echtes Kopfzerbrechen und wir können immer noch Probleme mit dünnen Farbverlauflinien bekommen, besonders wenn sie größere Bereiche abdecken. Sie haben nicht immer die gleiche Breite in WebKit-Browsern und Firefox unter OS X ist nicht sehr präzise bei der Darstellung (obwohl Firefox unter Windows hier selten versagt).

Probleme mit dünnen diagonalen Linien

Aber die Dinge haben sich stark verbessert, und ich glaube, sie werden sich weiter verbessern. Schon als ich Anfang dieses Jahres diese Slider erstellte, konnte ich ziemlich große Unterschiede zwischen den damals stabilen (41) und den Canary-Versionen (43) von Chrome feststellen.

Wiederholende Farbverläufe in Chrome 41 vs. Chrome 43

Wiederholende Farbverläufe sind jetzt viel sicherer zu verwenden, und ich denke, sie verdienen ein bisschen mehr Aufmerksamkeit, weil sie unser Leben erheblich erleichtern können und das macht sie in meinen Augen ziemlich cool.