Wie der Titel schon sagt, werden wir Bilder verzieren! Es gibt viele andere Artikel, die sich damit beschäftigen, aber das, was wir hier behandeln, ist etwas ganz anderes, weil es eher eine Herausforderung ist. Die Herausforderung? Ein Bild nur mit dem <img>-Tag und sonst nichts zu verzieren.
Das stimmt, keine zusätzliche Markierung, keine divs und keine Pseudo-Elemente. Nur dieser eine Tag.
Klingt schwierig, oder? Aber am Ende dieses Artikels – und der anderen, die zu dieser kleinen Serie gehören – werde ich beweisen, dass CSS mächtig genug ist, um uns großartige und beeindruckende Ergebnisse zu liefern, trotz der Einschränkung, mit nur einem Element zu arbeiten.
Fancy Image Decorations Serie
- Single Element Magic — Sie sind hier
- Masken und erweiterte Hover-Effekte
- Umrandungen und komplexe Animationen
Beginnen wir mit unserem ersten Beispiel
Bevor wir uns mit dem Code beschäftigen, listen wir die Möglichkeiten auf, ein <img> ohne zusätzliche Elemente oder Pseudo-Elemente zu stylen. Wir können border, box-shadow, outline und natürlich background verwenden. Es mag seltsam erscheinen, einem Bild einen Hintergrund hinzuzufügen, da wir ihn nicht sehen können, da er hinter dem Bild liegt – aber der Trick besteht darin, mit padding und/oder border Raum *um* das Bild zu schaffen und dann unseren Hintergrund in diesem Raum zu zeichnen.
Ich denke, Sie wissen, was als Nächstes kommt, da ich über background gesprochen habe, richtig? Ja, **Farbverläufe**! Alle Dekorationen, die wir machen werden, basieren auf vielen Farbverläufen. Wenn Sie mir schon länger folgen, überrascht Sie das wahrscheinlich gar nicht. 😁
Kommen wir zurück zu unserem ersten Beispiel
img {
--s: 10px; /* control the size */
padding: var(--s);
border: calc(2 * var(--s)) solid #0000;
outline: 1px solid #000;
outline-offset: calc(-1 * var(--s));
background: conic-gradient(from 90deg at 1px 1px, #0000 25%, #000 0);
}
Wir definieren padding und einen transparenten border mithilfe der Variable --s, um einen Raum um unser Bild zu schaffen, der dreimal so groß ist wie diese Variable.
Warum verwenden wir sowohl padding als auch border anstelle von einem oder dem anderen? Wir könnten mit nur einem von beiden auskommen, aber ich brauche diese Kombination für meinen Farbverlauf, denn standardmäßig ist der Anfangswert von background-clip border-box und background-origin ist gleich padding-box.
Hier ist eine Schritt-für-Schritt-Illustration, um die Logik zu verstehen
Anfänglich haben wir keine Rahmen am Bild, daher erzeugt unser Farbverlauf zwei Segmente mit einer Dicke von 1px. (Ich verwende in dieser speziellen Demo 3px, damit es leichter zu sehen ist.) Wir fügen einen farbigen Rahmen hinzu und der Farbverlauf liefert uns immer noch das gleiche Ergebnis im Padding-Bereich (wegen background-origin), aber er wiederholt sich hinter dem Rahmen. Wenn wir die Farbe des Rahmens transparent machen, können wir die Wiederholung nutzen und erhalten den gewünschten Rahmen.
Die outline in der Demo hat einen negativen Versatz. Das erzeugt eine quadratische Form oben im Farbverlauf. Das war's! Wir haben unserem Bild eine schöne Verzierung mit einem Farbverlauf und einer outline hinzugefügt. Wir hätten auch mehr Farbverläufe verwenden können! Aber ich versuche immer, meinen Code so einfach wie möglich zu halten, und ich habe festgestellt, dass das Hinzufügen einer outline auf diese Weise besser ist.
Hier ist eine reine Farbverlauf-Lösung, bei der ich nur padding verwende, um den Raum zu definieren. Immer noch das gleiche Ergebnis, aber mit einer komplexeren Syntax.
Lassen Sie uns eine andere Idee ausprobieren
Für diese habe ich das vorherige Beispiel genommen, die outline entfernt und ein clip-path angewendet, um den Farbverlauf an jeder Seite abzuschneiden. Der clip-path-Wert ist etwas ausführlich und verwirrend, aber hier ist eine Illustration, um seine Punkte besser zu sehen

Ich denke, Sie haben die Hauptidee verstanden. Wir werden Hintergründe, Umrandungen, Clipping und einige Masken kombinieren, um verschiedene Arten von Verzierungen zu erzielen. Wir werden auch einige coole Hover-Animationen als Bonus betrachten! Was wir bisher betrachtet haben, ist nur ein kleiner Überblick über das, was noch kommt!
Der nur-Ecken-Rahmen
Dieser verwendet vier Farbverläufe. Jeder Farbverlauf bedeckt eine Ecke und beim Hoveren dehnen wir sie aus, um einen vollständigen Rahmen um das Bild zu bilden. Lassen Sie uns den Code für einen der Farbverläufe aufschlüsseln
--b: 5px; /* border thickness */
background: conic-gradient(from 90deg at top var(--b) left var(--b), #0000 90deg, darkblue 0) 0 0;
background-size: 50px 50px;
background-repeat: no-repeat;
Wir werden einen Farbverlauf mit einer Größe von 50px 50px zeichnen und ihn in der oberen linken Ecke (0 0) platzieren. Für die Konfiguration des Farbverlaufs, hier ist eine Schritt-für-Schritt-Illustration, die zeigt, wie ich zu diesem Ergebnis gekommen bin.
Wir neigen dazu zu denken, dass Farbverläufe nur zum Übergang zwischen zwei Farben gut sind. Aber in Wirklichkeit können wir damit viel mehr machen! Sie sind besonders nützlich, wenn es darum geht, verschiedene Formen zu erstellen. Der Trick besteht darin, sicherzustellen, dass wir harte Stopps zwischen den Farben haben – wie im obigen Beispiel – anstatt sanfte Übergänge.
#0000 25%, darkblue 0
Dies bedeutet im Grunde: "Fülle den Farbverlauf mit einer transparenten Farbe bis zu 25% der Fläche, fülle dann den verbleibenden Bereich mit darkblue."
Sie kratzen sich vielleicht am Kopf über den 0-Wert. Das ist ein kleiner Hack, um die Syntax zu vereinfachen. Eigentlich sollten wir dies verwenden, um einen harten Stopp zwischen Farben zu erzeugen.
#0000 25%, darkblue 25%
Das ist logischer! Die transparente Farbe endet bei 25% und darkblue beginnt genau dort, wo die Transparenz endet, wodurch ein harter Stopp entsteht. Wenn wir die zweite durch 0 ersetzen, erledigt der Browser die Arbeit für uns, so dass es ein etwas effizienterer Weg ist.
Irgendwo in der Spezifikation steht:
wenn ein Farbpunkt oder ein Übergangshinweis eine Position hat, die kleiner ist als die angegebene Position jedes Farbpunktes oder Übergangshinweises vor ihm in der Liste, setze seine Position auf den größten angegebenen Wert jedes Farbpunktes oder Übergangshinweises vor ihm.
0 ist immer kleiner als jeder andere Wert, daher wandelt der Browser ihn immer in den größten Wert um, der in der Deklaration vor ihm steht. In unserem Fall ist diese Zahl 25%.
Nun wenden wir die gleiche Logik auf alle Ecken an und erhalten den folgenden Code
img {
--b: 5px; /* border thickness */
--c: #0000 90deg, darkblue 0; /* define the color here */
padding: 10px;
background:
conic-gradient(from 90deg at top var(--b) left var(--b), var(--c)) 0 0,
conic-gradient(from 180deg at top var(--b) right var(--b), var(--c)) 100% 0,
conic-gradient(from 0deg at bottom var(--b) left var(--b), var(--c)) 0 100%,
conic-gradient(from -90deg at bottom var(--b) right var(--b), var(--c)) 100% 100%;
background-size: 50px 50px; /* adjust border length here */
background-repeat: no-repeat;
}
Ich habe CSS-Variablen eingeführt, um Redundanzen zu vermeiden, da alle Farbverläufe die gleiche Farbkonfiguration verwenden.
Für den Hover-Effekt erhöhe ich lediglich die Größe der Farbverläufe, um den vollständigen Rahmen zu erzeugen
img:hover {
background-size: 51% 51%;
}
Ja, es sind 51% statt 50% – das erzeugt eine kleine Überlappung und vermeidet mögliche Lücken.
Lassen Sie uns eine weitere Idee mit der gleichen Technik ausprobieren
Diesmal verwenden wir nur zwei Farbverläufe, aber mit einer komplexeren Animation. Zuerst aktualisieren wir die Position jedes Farbverlaufs, dann erhöhen wir seine Größe, um den vollständigen Rahmen zu erzeugen. Ich habe auch mehr Variablen eingeführt, um eine bessere Kontrolle über Farbe, Größe, Dicke und sogar den Abstand zwischen dem Bild und dem Rahmen zu haben.
img {
--b: 8px; /* border thickness*/
--s: 60px; /* size of the corner*/
--g: 14px; /* the gap*/
--c: #EDC951;
padding: calc(var(--b) + var(--g));
background-image:
conic-gradient(from 90deg at top var(--b) left var(--b), #0000 25%, var(--c) 0),
conic-gradient(from -90deg at bottom var(--b) right var(--b), #0000 25%, var(--c) 0);
background-position:
var(--_p, 0%) var(--_p, 0%),
calc(100% - var(--_p, 0%)) calc(100% - var(--_p, 0%));
background-size: var(--s) var(--s);
background-repeat: no-repeat;
transition:
background-position .3s var(--_i,.3s),
background-size .3s calc(.3s - var(--_i, .3s));
}
img:hover {
background-size: calc(100% - var(--g)) calc(100% - var(--g));
--_p: calc(var(--g) / 2);
--_i: 0s;
}
Warum haben die Variablen --_i und --_p einen Unterstrich im Namen? Die Unterstriche sind Teil einer Namenskonvention, die ich verwende, um "interne" Variablen zu berücksichtigen, die zur Optimierung des Codes verwendet werden. Sie sind nichts Besonderes, aber ich möchte zwischen den Variablen, die wir zur Steuerung des Rahmens anpassen (wie --b, --c usw.), und denen, die ich verwende, um den Code kürzer zu machen, unterscheiden.
Der Code mag verwirrend und nicht leicht zu verstehen aussehen, aber ich habe eine dreiteilige Serie geschrieben, in der ich solche Techniken detailliert beschreibe. Ich empfehle dringend, zumindest den ersten Artikel zu lesen, um zu verstehen, wie ich zu dem obigen Code gekommen bin.
Hier ist eine Illustration, um die verschiedenen Werte besser zu verstehen

Die Rahmenanzeige
Versuchen wir eine andere Art von Animation, bei der wir den vollständigen Rahmen beim Hovern anzeigen
Cool, oder? Und wenn Sie genau hinschauen, werden Sie bemerken, dass die Linien beim Herausbewegen der Maus in die entgegengesetzte Richtung verschwinden, was den Effekt noch schöner macht! Ich habe einen ähnlichen Effekt in einem früheren Artikel verwendet.
Aber diesmal decke ich, anstatt das gesamte Element abzudecken, nur einen kleinen Teil ab, indem ich eine height definiere, um so etwas zu erhalten
Das ist die obere Kante unseres Rahmens. Wir wiederholen den gleichen Vorgang an jeder Seite des Bildes und haben unseren Hover-Effekt
img {
--b: 10px; /* the border thickness*/
--g: 5px; /* the gap on hover */
--c: #8A9B0F;
padding: calc(var(--g) + var(--b));
--_g: no-repeat linear-gradient(var(--c) 0 0);
background:
var(--_g) var(--_i, 0%) 0,
var(--_g) 100% var(--_i, 0%),
var(--_g) calc(100% - var(--_i, 0%)) 100%,
var(--_g) 0 calc(100% - var(--_i, 0%));
background-size: var(--_i, 0%) var(--b),var(--b) var(--_i, 0%);
transition: .4s, background-position 0s;
cursor: pointer;
}
img:hover {
--_i: 100%;
}
Wie Sie sehen können, wende ich viermal denselben Farbverlauf an und jeder hat eine andere Position, um nur eine Seite auf einmal abzudecken.
Noch einer? Los geht's!
Dieser sieht etwas knifflig aus und erfordert tatsächlich etwas Vorstellungskraft, um zu verstehen, wie zwei konische Farbverläufe diese Art von Magie vollbringen. Hier ist eine Demo, die einen der Farbverläufe veranschaulicht
Das Pseudo-Element simuliert den Farbverlauf. Es ist anfangs außer Sichtweite und beim Hovern ändern wir zuerst seine Position, um die obere Kante des Rahmens zu erhalten. Dann erhöhen wir die Höhe, um die rechte Kante zu erhalten. Die Form des Farbverlaufs ähnelt denen, die wir im letzten Abschnitt verwendet haben: zwei Segmente, um zwei Seiten abzudecken.
Aber warum habe ich die Breite des Farbverlaufs auf 200% gesetzt? Sie würden denken, 100% wäre genug, oder?
100% sollte ausreichen, aber ich werde den Farbverlauf nicht so bewegen können, wie ich möchte, wenn ich seine Breite auf 100% belasse. Das ist eine weitere kleine Eigenart in Bezug auf die Funktionsweise von background-position. Ich behandle dies in einem früheren Artikel. Ich habe auch eine Antwort auf Stack Overflow gepostet, die sich damit befasst. Ich weiß, das ist viel zu lesen, aber es ist wirklich Ihre Zeit wert.
Nachdem wir nun die Logik für einen Farbverlauf erklärt haben, ist der zweite einfach, da er genau das Gleiche tut, aber die linke und untere Kante abdeckt. Alles, was wir tun müssen, ist, einige Werte zu vertauschen und wir sind fertig
img {
--c: #8A9B0F; /* the border color */
--b: 10px; /* the border thickness*/
--g: 5px; /* the gap */
padding: calc(var(--g) + var(--b));
--_g: #0000 25%, var(--c) 0;
background:
conic-gradient(from 180deg at top var(--b) right var(--b), var(--_g))
var(--_i, 200%) 0 / 200% var(--_i, var(--b)) no-repeat,
conic-gradient( at bottom var(--b) left var(--b), var(--_g))
0 var(--_i, 200%) / var(--_i, var(--b)) 200% no-repeat;
transition: .3s, background-position .3s .3s;
cursor: pointer;
}
img:hover {
--_i: 100%;
transition: .3s, background-size .3s .3s;
}
Wie Sie sehen können, sind beide Farbverläufe fast identisch. Ich vertausche einfach die Werte für Größe und Position.
Die Rahmenrotation
Diesmal werden wir keinen Rahmen um unser Bild zeichnen, sondern das Aussehen eines bestehenden anpassen.
Sie fragen sich wahrscheinlich, wie zum Teufel ich in der Lage bin, eine gerade Linie in eine schräge Linie zu verwandeln. Nein, die Magie ist anders. Das ist nur die Illusion, die wir nach der Kombination einfacher Animationen für vier Farbverläufe erhalten.
Sehen wir uns an, wie die Animation für den oberen Farbverlauf gemacht wird
Ich aktualisiere nur die Position eines wiederholten Farbverlaufs. Noch nichts Besonderes! Machen wir dasselbe für die rechte Seite
Beginnen Sie, den Trick zu sehen? Beide Farbverläufe schneiden sich an der Ecke, um die Illusion zu erzeugen, dass die gerade Linie in eine schräge umgewandelt wird. Lassen Sie uns die Umrandung entfernen und den Überlauf ausblenden, um sie besser zu sehen
Jetzt fügen wir zwei weitere Farbverläufe hinzu, um die restlichen Kanten abzudecken, und wir sind fertig
img {
--g: 4px; /* the gap */
--b: 12px; /* border thickness*/
--c: #669706; /* the color */
padding: calc(var(--g) + var(--b));
--_c: #0000 0 25%, var(--c) 0 50%;
--_g1: repeating-linear-gradient(90deg ,var(--_c)) repeat-x;
--_g2: repeating-linear-gradient(180deg,var(--_c)) repeat-y;
background:
var(--_g1) var(--_p, 25%) 0,
var(--_g2) 0 var(--_p, 125%),
var(--_g1) var(--_p, 125%) 100%,
var(--_g2) 100% var(--_p, 25%);
background-size: 200% var(--b), var(--b) 200%;
transition: .3s;
}
img:hover {
--_p: 75%;
}
Wenn wir diesen Code nehmen und ihn leicht anpassen, können wir eine weitere coole Animation erhalten
Können Sie die Logik in diesem Beispiel erkennen? Das ist Ihre Hausaufgabe! Der Code mag beängstigend aussehen, aber er verwendet die gleiche Logik wie die vorherigen Beispiele, die wir uns angesehen haben. Versuchen Sie, jeden Farbverlauf zu isolieren und sich vorzustellen, wie er animiert.
Zusammenfassung
Das sind viele Farbverläufe in einem Artikel!
Das stimmt, und ich habe Sie gewarnt! Aber wenn die Herausforderung darin besteht, ein Bild ohne zusätzliche Elemente und Pseudo-Elemente zu verzieren, bleiben uns nur wenige Möglichkeiten, und Farbverläufe sind die mächtigste Option.
Machen Sie sich keine Sorgen, wenn Sie bei einigen Erklärungen etwas verloren sind. Ich empfehle immer einige meiner alten Artikel, in denen ich einige der Konzepte, die wir für diese Herausforderung wiederverwendet haben, detaillierter erkläre.
- Hintergrundmuster mit conic-gradient: Dieser Artikel macht Sie mit der
conic-gradient()-Syntax vertraut. - Hover-Effekte mit Hintergrund-Eigenschaften: Dieser Artikel behandelt verschiedene Hintergrund-Tricks zur Erstellung cooler Animationen mit effizientem Code. Dieser ist ein Muss, da er viel über CSS-Variablen und
calc()enthält, die wichtige Bestandteile dessen sind, was wir hier behandelt haben. - Alles, was Sie über background-position wissen müssen: Dieser Artikel teilt das Erfolgsgeheimnis hinter der Verwendung von
background-positionin den von uns betrachteten Beispielen.
Ich verabschiede mich mit einer letzten Demo, um Sie bis zum nächsten Artikel dieser Serie bei Laune zu halten. Diesmal verwende ich radial-gradient(), um einen weiteren lustigen Hover-Effekt zu erzeugen. Ich überlasse es Ihnen, den Code zu zerlegen, um zu verstehen, wie er funktioniert. Fragen Sie mich in den Kommentaren, wenn Sie nicht weiterkommen!
Fancy Image Decorations Serie
- Single Element Magic — Sie sind hier
- Masken und erweiterte Hover-Effekte
- Umrandungen und komplexe Animationen
Ein großartiger Artikel mit einigen großartigen CSS-Techniken.
Ja, das stimmt
Toller Artikel. Mir haben die Ideen wirklich gefallen und ich werde definitiv ähnliche Dinge in meinen Projekten ausprobieren.
Ich freue mich, dass es zwei weitere Teile gibt!