Seltsamer Gradientenrand-Effekt

72

Wenn linear-gradientich einen transparenten Rand auf ein Element mit einem als Hintergrund anwende, erhalte ich einen seltsamen Effekt.

Geben Sie hier die Bildbeschreibung ein

Beachten Sie, dass die linke und rechte Seite des Elements nicht die richtigen Farben haben (sie sind irgendwie vertauscht) und seltsam flach sind .

HTML

<div class="colors">
</div>

CSS

.colors {
    width: 100px;
    border: 10px solid rgba(0,0,0,0.2);
    height: 50px;
    background: linear-gradient(to right, 
        #78C5D6,
        #459BA8,
        #79C267,
        #C5D647,
        #F5D63D,
        #F08B33,
        #E868A2,
        #BE61A5);
}

Warum zeigt dies einen seltsamen Effekt auf der linken und rechten Seite des Elements und was kann ich dagegen tun?

Hier ist die Geige: http://jsfiddle.net/fzndodgx/3/

Afonso Matos
quelle
Liegt das nicht nur daran, dass die Ränder vom Inhaltsfeld getrennt sind? dh der Hintergrund.
gebissen
Eine Lösung wäre, eine zweite Div mit :: after zu haben: jsfiddle.net/a1h2yh11
Denys Séguret
Warum das Downvote? Erwägen Sie auch, einen Kommentar zu veröffentlichen. Sowieso ..
Afonso Matos

Antworten:

52

Das liegt daran, dass sich die Start- und Endpunkte von gradientan den Rändern von befinden padding-boxund borderaußerhalb von gerendert werden padding-box. So sehen die Ränder lustig aus, weil das backgroundauf jeder Seite außerhalb der wiederholt wird padding-box, um das abzudecken border-box.

Das box-shadow:insetwird im padding-box(genau wie im Hintergrund) gerendert und hat visuell den gleichen Effekt wie a border, sodass Sie versuchen können, dies anstelle von border:

box-shadow: inset 0 0 0 10px rgba(0,0,0,0.2);
padding: 10px;

Da a box-shadowkeinen Platz beansprucht, müssen Sie Ihre Polsterung entsprechend erhöhen.

Illustration von padding-boxund border-box: Geben Sie hier die Bildbeschreibung ein

Demo http://jsfiddle.net/ilpo/fzndodgx/5/

Okku
quelle
9
Die Hintergründe wiederholen sich - sie erstrecken sich also über die Grenzen der Polsterbox hinaus und beginnen dann erneut - daher die offensichtliche Umkehrung.
Geoff Atkins
6
Ich denke nicht, dass es von Ihrer Seite gut war, das, was bereits in einer anderen Antwort behandelt wurde, lange nach der Veröffentlichung der anderen in Ihre eigene aufzunehmen. Zumindest hätten Sie die andere Antwort in Ihrer Bearbeitung erwähnen können.
Harry
3
downvoted .. wegen Kopie Einfügen Antwort von anderen Beitrag. Versuchen Sie nicht, die Arbeit anderer anzuerkennen.
Mr_Green
4
Uh, es eine Copy-Paste - Aufruf ist ein bisschen weit hergeholt, und es ist nicht wie dieser Benutzer ersetzt seine ursprüngliche Antwort mit dem neuen. Auf jeden Fall bietet Harrys Antwort immer noch eine Erklärung seiner Lösung, so dass sie dieser überlegen bleibt.
BoltClock
2
Entschuldigung, ich hatte mir nicht die Mühe gemacht, seine lange Antwort zu lesen, bevor ich eine Bearbeitung vorgenommen hatte, und wusste nicht, dass die Lösung bereits vorgeschlagen wurde. Ich kann mein bearbeitetes Bit jedoch entfernen, wenn dies einen Unterschied macht.
Okku
46

Lösung

Der einfachste Weg, um dieses Problem zu beheben, besteht darin, den Wert für die background-originEigenschaft als festzulegen border-box.

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-origin: border-box;
}
<div class="colors"></div>


Grund für das fragliche Verhalten

Die folgenden relevanten backgroundEigenschaften bestimmen, wie der Hintergrundverlauf für diesen Fall angezeigt wird:

  • background-origin- Der Standardwert ist padding-box. Dies bedeutet, dass der Hintergrund tatsächlich in Bezug auf die Polsterbox positioniert ist und daher nach dem beginnt border.
  • background-repeat- Der Standardwert hierfür ist repeat. Dies bedeutet, dass das Bild so oft wie nötig wiederholt werden sollte, um den gesamten Hintergrundmalbereich abzudecken.
  • background-clip- Der Standardwert hierfür ist border-box. Dies bedeutet, dass das Bild auch unter dem Bereich vorhanden sein sollte, der von den Rändern der Box eingenommen wird.

Wenn wir nun alle drei kombinieren, können wir sehen, dass der Rand so oft wie möglich wiederholt werden muss, damit er auch unter den Rändern vorhanden ist, und dass seine Startposition hinter dem Rand der Box liegt. Dies bedeutet, dass der Hintergrund zyklisch wiederholt werden muss, um den Bereich unter dem Rand auf der linken Seite auszufüllen. Aus diesem Grund hat der linke Rand die Farbe als rechtes Ende des Verlaufs und umgekehrt.

Durch Ändern in border-boxwird der Hintergrund in Bezug auf das Rahmenfeld positioniert. Diese Einstellung wirkt sich auch auf die Größe des Hintergrundbilds aus, und der Grund dafür wird nachstehend ausführlich beschrieben.


Warum funktioniert das box-sizing: border-boxnicht?

Die Einstellung box-sizingals border-boxbewirkt keine Änderung, da diese Eigenschaft nur die Größe der Box beeinflusst. Es hat absolut keine Auswirkungen auf Folgendes:

  • Die Größe des Gradientenbildes (die tatsächliche Berechnungslogik wird unten beschrieben)
  • Der Startpunkt (oder die Position) des Verlaufsbildes
  • Die Wiederholung des Hintergrundbildes

Wie berechnet sich die Größe des Gradienten?

Gemäß der W3C-Spezifikation werden im Folgenden die Abmessungen des Bildes berechnet, wenn keine explizite Größe angegeben ist (Standardwert ist auto).

Wenn das Bild weder eine Eigenbreite noch eine Eigenhöhe hat, wird seine Größe wie für "Enthalten" bestimmt.

Beachten Sie, wie es um die Größe des Bildes und nicht um die der Box geht. Unabhängig von der Größe des Felds würde die Größe des Hintergrundbilds im Wesentlichen basierend auf der Definition für das Schlüsselwort berechnet, containwenn das Bild selbst keine intrinsische Höhe hat ( die CSS-Verläufe im Gegensatz zu Bildern nicht haben ).

Die Definition fürcontain lautet wie folgt:

Skalieren Sie das Bild unter Beibehaltung seines intrinsischen Seitenverhältnisses (falls vorhanden) auf die größte Größe, sodass sowohl seine Breite als auch seine Höhe in den Hintergrundpositionierungsbereich passen .

Der Hintergrundpositionierungsbereich ist wie folgt definiert (unter background-originEigenschaftsdefinition):

Gibt für Elemente, die als einzelnes Feld gerendert werden, den Hintergrundpositionierungsbereich an

Wenn das Bild keine intrinsische Höhe hat (und in diesem Fall auch keine background-size), wäre die Größe des Bildes gleich der des background-originWertes von (was in unserem Fall der Fall ist padding-box).

Aus diesem Grund hat auch das Einstellen des box-sizingas border-boxkeine Auswirkung.

Hinweis: Die Betonung in den zitierten Texten liegt ausschließlich bei mir


Wenn Sie explizit background-sizedie Größe des Felds festlegen , werden Sie feststellen, wie das Problem auf der rechten Seite, jedoch nicht auf der linken Seite behoben wird. Dies liegt daran, dass das Bild jetzt groß genug ist, um nicht unter dem rechten Rand wiederholt zu werden, aber sein Startpunkt immer noch hinter dem linken Rand liegt.

Harry
quelle
1
Gute Erklärung für mögliche unterschiedliche Problemumgehungen.
Afonso Matos
1
@afonsomatos: Der in dieser Antwort behandelte Ansatz ist keine Problemumgehung. Es ist eigentlich die richtige Lösung für Ihr Problem :)
Harry
13

Der Hintergrund wiederholt sich unter der Grenze. Der Hintergrund läuft nur im "Körper" des Elements, unter dem Rand befindet sich eine Erweiterung und es kommt zu Wiederholungen.

Siehe dieses Beispiel mit no-repeatan der Grenze.

AKTUALISIEREN

Das Spielen mit dem Hintergrund position& sizekann helfen, indem Sie den Hintergrund erweitern und dann seine Position anpassen.

Überprüfen Sie diese Geige aus.

Oder siehe Ausschnitt:

.colors {
  padding: 10px;
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-size: 117%;
  background-position-x: 130px;
}
<div class="colors"></div>

JNF
quelle
@ DenysSéguret, fester Link zur Geige
JNF
4

Der Verlauf beginnt innerhalb des Auffüllfelds gemäß dem Standardverhalten des CSS-Feldmodells. Daher ist es sinnvoll, dass die Start- und Endfarben bis unendlich auf beiden Seiten des Verlaufs angezeigt werden, wo sich der Rand befinden würde.

Gleiches gilt für diesen Gradienten (NSFW):

Ein Gott schreckliches Auge wund

Es setzt sich unendlich im Startwert (violett) links und unendlich im Endwert (orange) rechts fort. Mit diesem Gradienten kann es unendlich weiter nach oben gehen, und das tut es auch.

So verstehe ich, warum dies so erscheint. Eine Lösung wäre die Verwendung eines anderen Box-Modells.

gebissen
quelle
12
... warum haben Sie den Farbverlauf als nicht arbeitssicher markiert?
Woodrow Barlow
4
weil es super hässlich ist>.>
gebissen am
13
Mein Chef hat mich beim Betrachten dieses Gefälles erwischt und jetzt muss ich mich mit der Personalabteilung treffen. Vielen Dank Aaron.
Sterling Archer
1
@WoodrowBarlow Stackoverflow sieht geschäftlich und seriös aus, um gelegentlich zu surfen (es sei denn, Sie haben die tagbasierte Thread-Hervorhebung aktiviert). Wenn Sie direkt gefragt werden, können Sie immer sagen: "Ich bin hier, um die Lösung für Problem X zu finden." Große, farbenfrohe Bilder ruinieren diesen Eindruck.
Traubenfuchs
1
@SterlingArcher Ich bin sicher, Malory war wütend.
Purag
4

Der Standardwert der background-originEigenschaft ist padding-box, dass der Hintergrund relativ zum Auffüllfeld positioniert und dimensioniert wird.

Der Hintergrund erstreckt sich auch unterhalb der Grenze, da die background-clipEigenschaft standardmäßig lautet border-box. es wiederholt sich einfach unterhalb der Grenze. Aus diesem Grund sehen Sie die rechte Seite des Hintergrunds unter dem linken Rand und umgekehrt.

Ändern Sie einfach den Ursprung:

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-origin: border-box;
}
<div class="colors"></div>

Alternativ können Sie mit Hintergrundgröße und -position spielen: Fügen Sie der Hintergrundgröße 20 Pixel hinzu und positionieren Sie sie bei -10 Pixel -10 Pixel:

.colors {
  width: 100px;
  border: 10px solid rgba(0, 0, 0, 0.2);
  height: 50px;
  background: linear-gradient(to right, #78C5D6, #459BA8, #79C267, #C5D647, #F5D63D, #F08B33, #E868A2, #BE61A5);
  background-position: -10px -10px;
  background-size: calc(100% + 20px) calc(100% + 20px);
}
<div class="colors"></div>

Salman A.
quelle
4

Andere Antworten haben bereits gezeigt, wie das Problem behoben werden kann, aber ich dachte, ich sollte nur darauf hinweisen, border-widthdass sich der Hintergrund tatsächlich wiederholt , wenn Sie den Wert erhöhen .

.colors {
    width: 100px;
    border: 100px solid rgba(0,0,0,0.2);
    height: 50px;
    background: linear-gradient(to right, 
        #78C5D6,
        #459BA8,
        #79C267,
        #C5D647,
        #F5D63D,
        #F08B33,
        #E868A2,
        #BE61A5);
}

wird herstellen

Geben Sie hier die Bildbeschreibung ein

mflodin
quelle
@mflodin + 1 es wird offensichtlicher
Afonso Matos
3

Wenn Sie nicht verwenden möchten box-shadow, können Sie border-imagedie Farben des Verlaufs verwenden und anpassen: http://jsfiddle.net/9pcuj8bw/5/

.colors {
    width:100px;
    height: 50px;
    background: linear-gradient(to right, 
        #78C5D6,
        #459BA8,
        #79C267,
        #C5D647,
        #F5D63D,
        #F08B33,
        #E868A2,
        #BE61A5) no-repeat;
    border: 10px solid;
    border-image: linear-gradient(to right, 
        #0bc3b8,
        #068e8c,
        #f8c617,
        #ea5f24,
        #b2492c) 1;
}
<div class="colors"></div>

Vorsicht, dies funktioniert nicht unter IE10 oder niedriger: http://caniuse.com/#feat=border-image

Wellenmeister
quelle
Sie meinen, "das funktioniert nicht mit IE10 -" - es funktioniert mit allen anderen Browsern (Firefox, Chrome usw.).
Kobi
1
Dies ist nicht die beste Lösung und erzielt nicht den gewünschten Effekt.
Afonso Matos