Sie müssen ein Element rechts oder links positionieren, sodass Text darum herum fließt? Das ist mit der float-Eigenschaft eine einfache Aufgabe. Aber was ist, wenn wir dieses Element (nennen wir es ein Bild) auch noch in eine der unteren Ecken schieben wollen? Klingt etwas knifflig, oder? Wir brauchen wahrscheinlich JavaScript?
Nein, ein paar Zeilen (kniffliger) CSS reichen aus! Hier ist die reine CSS-Lösung, die Ihr Bild in der unteren Ecke verankert, unabhängig von Größe und Inhalt.
Vergrößern Sie das Wrapper-Element und sehen Sie die Magie am Werk
Lassen Sie uns den Code analysieren.
Markup und Layout
Wir benötigen ein Wrapper-Element, um alles zu umschließen, und darauf werden wir Flexbox anwenden. Flexbox erlaubt uns, die standardmäßige stretch-Ausrichtung zu nutzen, um später height: 100% verwenden zu können.
<div class="wrapper">
<div class="box">
<div class="float"><img></div>
Lorem ipsum dolor ...
</div>
</div>
.wrapper {
display: flex;
}
.float {
float: right;
height: 100%;
display: flex;
align-items: flex-end;
shape-outside: inset(calc(100% - 100px) 0 0);
}
Das .box innerhalb des .wrapper ist unser Flex-Item. Wir benötigen keine besondere CSS für die Box. Sie definiert die Höhe des Wrappers und wird gleichzeitig auf die gleiche Höhe gestreckt. Dieses Verhalten liefert uns eine "Referenzhöhe", die von den Kindelementen verwendet werden kann.
Wenn das Flex-Item
align-self: stretchhat, wird das Layout seiner Inhalte neu berechnet, wobei diese verwendete Größe als seine definitive Quergröße behandelt wird, damit prozentual bemessene Kinder aufgelöst werden können.
Das Schlüsselwort ist definitiv, was uns erlaubt, eine prozentuale (%) Höhe sicher innerhalb des Box-Elements zu verwenden.
Nun zum schwebenden Element
Unser .float-Element nimmt dank der oben beschriebenen Höhenberechnung die volle Höhe neben dem Textinhalt ein. Innerhalb dieses Elements schieben wir das Bild mit Flexbox-Ausrichtung nach unten.

Nun zur eigentlichen Trickerei, der Verwendung der shape-outside-Eigenschaft. Hier ist, wie MDN sie definiert
Die CSS-Eigenschaft `shape-outside` definiert eine Form – die nicht rechteckig sein kann –, um die herum benachbarter Inline-Inhalt umbrechen soll. Standardmäßig bricht Inline-Inhalt um seine Margin-Box herum;
shape-outsidebietet eine Möglichkeit, diesen Umbruch anzupassen, sodass Text um komplexe Objekte statt um einfache Boxen fließen kann.
Mit anderen Worten, shape-outside legt fest, wie der Inhalt um die Bounding Box eines Elements fließt.
Sie akzeptiert eine Reihe von Werten. Einer davon ist die Funktion inset(), die, wieder laut MDN
Definiert ein Innenrechteck. Wenn alle vier ersten Argumente angegeben sind, stellen sie die oberen, rechten, unteren und linken Abstände vom Referenzrahmen nach innen dar, die die Positionen der Kanten des Innenrechtecks definieren.
Also, mit shape-outside: inset(calc(100% - X) 0 0) können wir ein Innenrechteck erstellen, das genau am oberen Rand des Bildes beginnt. Und der obere Rand ist gleich 100% - X, wobei X die Bildhöhe und 100% die Höhe des .float-Elements ist. Dies ermöglicht es dem Text, innerhalb des *freien* Raums oberhalb des Bildes zu fließen. Dies ist responsiv, und wir können einfach zwischen links und rechts wechseln (indem wir die float-Eigenschaft anpassen).
Das war's! Das einzige größere Manko ist, dass Sie die Bildhöhe kennen müssen.
Optimieren wir den Markup
Wir können unseren Code noch etwas optimieren und die zusätzliche Wrapper-Schicht um das Bild entfernen.
<div class="wrapper">
<div class="box">
<img class="float">
Lorem ipsum dolor ...
</div>
</div>
Dann würde unser CSS so aussehen:
.wrapper {
display: flex;
}
.float {
float: right;
height: 100%;
width: 100px;
shape-outside: inset(calc(100% - 100px /*height */) 0 0);
object-fit: contain;
object-position: bottom;
}
Da wir den zusätzlichen Wrapper entfernt haben, benötigen wir eine andere Technik, um das Bild in der unteren Ecke zu platzieren. Dazu verwenden wir object-fit und object-position, müssen aber die Breite des Bildes explizit angeben.
Mit dieser Methode müssen wir sowohl die Breite als auch die Höhe des Bildes kennen, im Gegensatz zum vorherigen Code, bei dem nur die Höhe benötigt wurde.
Möchten Sie mehr?
Wir können dieses Konzept noch etwas erweitern, um ausgefeiltere Situationen zu berücksichtigen. Zum Beispiel können wir das Bild nach rechts schwebend positionieren, aber mit justify-content: center in der Mitte der Box verankern: und auch unser Innenrechteck in die Mitte verschieben, indem wir shape-outside von inset(calc(100% - X) 0 0) zu inset(calc(50% - X/2) 0 0) ändern.
Wir können auch zwei Bilder in beiden unteren Ecken platzieren
Nichts Komplexes hier. Ich verwende einfach zweimal dasselbe schwebende Element, einmal rechts und wieder links. Und warum bei zwei Ecken aufhören, wenn wir Bilder in allen vier Ecken platzieren können?
Die gleiche grundlegende Idee steckt dahinter, aber wir verlassen uns bei den oberen Bildern auch auf die übliche Float-Funktion. Sie werden jedoch feststellen, dass das Konzept hier anfängt, ein wenig zu brechen, und wir unerwünschte Überläufe erhalten, je nach Größe der Container-Box. Wir können die Höhe des .float-Elements größer als 100 % machen und einigermaßen "magische Zahlen" anwenden, die die Dinge glätten, indem wir den `padding` und `margin` der Bilder anpassen.
Wussten Sie, dass shape-outside radial-gradient() als Wert akzeptiert? Wir können das verwenden, um abgerundete Bilder wie unten zu platzieren.
Der transparente Teil des Gradienten ist der freie Raum, in den der Text gelangen kann. Sie haben vielleicht bemerkt, dass wir auch border-radius auf das Bild angewendet haben. Die Eigenschaft shape-outside beeinflusst einfach das .float-Element, und wir müssen die Form des Bildes manuell anpassen, damit sie der von shape-outside definierten Form folgt.
Während wir dabei sind, kombinieren wir dies mit unserem früheren Beispiel, das das Bild in der vertikalen Mitte der Box verankert, indem wir justify-content: center verwenden.
Ein weiteres radial-gradient() und auch eine weitere border-radius-Konfiguration.
Wir hätten stattdessen einen linear-gradient() verwenden können, um eine dreieckige Form für den Umbruchbereich zu erzeugen.
Dies ist die gleiche Idee, die wir für radial-gradient() verwendet haben. Der große Unterschied ist, dass wir clip-path anstelle von border-radius verwenden, um unser Bild zuzuschneiden.
Und da wir es für die anderen gemacht haben, verwenden wir die Idee justify-content: center, um das Bild am vertikalen Mittelpunkt des rechten Rands der Box zu verankern.
Wir haben im obigen Demo ein conic-gradient() mit shape-outside verwendet, um die dreieckige Form zu definieren, und clip-path, um eine ähnliche Form auf dem Bild zu erhalten.
All diese Beispiele können noch weiter optimiert werden, indem weniger Code verwendet wird, falls das Bild dekorativ ist (wenn es aus SEO-Gründen nicht im HTML benötigt wird). Ersetzen wir das .float-Element durch ein Pseudo-Element und wenden das Bild stattdessen als Hintergrund an.
Wir verwenden mask, um nur den Teil des Bildes anzuzeigen, den wir benötigen, und raten Sie mal, es verwendet denselben Wert wie shape-outside! Also mussten wir nur einen Wert für die Form definieren.
Das ist alles!
Hier gibt es viele Möglichkeiten, nicht nur Rechtecke in Ecken, sondern jede Art von Form an jeder Position zu platzieren, indem im Wesentlichen die gleiche Code-Struktur verwendet wird. Wir müssen nur
- Die Eigenschaft
shape-outsideanpassen, um die Form zu definieren - Etwas Styling auf das Bild anwenden, um der zuvor definierten Form zu folgen, *oder* denselben Wert auf
maskanwenden, falls wir die Pseudo-Element-Version verwenden.
Dann hält alles an seinem Platz, sogar in responsiven Designs.
Wundervoller Artikel. Er gibt mir die Zuversicht, dass ich
floatnie wieder verwenden muss.Großartige Übung in Stil und Technik, in der Tat! Aber sind wir sicher, dass eine Sprache so kompliziert sein sollte, um das zu erreichen? Ich denke, sie sollte eine einfachere Möglichkeit dafür bieten, nicht diese Zauberei!
Das ist eigentlich eine sehr einfache Methode, um es zu erreichen :) es sind nur 6 Zeilen CSS-Code. Wenn Sie im Internet nach demselben Thema suchen, werden Sie komplexere Codes finden, die dies nur "annähern" (lassen wir die, die JS verwenden, mal beiseite).
Für einige ältere Leser könnte dieser Artikel
float-PTBS ausgelöst haben.Ich kann mich nicht erinnern, wann ich das letzte Mal die Höhe meiner Bilder garantieren konnte.
Irgendwelche Ideen, wie man mit einem responsiven Bild umgeht?
Ich denke, Ihre einzige Möglichkeit ist, die Höhe explizit anzugeben: https://jsfiddle.net/8aoryLju/ es bleibt responsiv, aber mit einer festen Höhe.
Also in den ersten paar Beispielen, bei denen die
float-Klasse eine Breite von 100 % hat...was verhindert, dass der Text über dem Bild – und unter dem Float – "überrannt" und unselektierbar wird? Ist es dasshape-outside-Attribut, das den Trick macht? Ich hatte gerade zwei Situationen, in denen der unsichtbare Teil eines Floats Formelemente überdeckte, die nicht mehr angeklickt werden konnten.Entschuldigung, ich meinte eine
heightvon 100 %.In der Tat, Sie haben Recht. Es geht um die letzten Beispiele, bei denen ich Maske verwende. In diesem Fall wird die Stapelreihenfolge dazu führen, dass das Float-Element über dem Text liegt und die Textauswahl (oder jede Interaktion) verhindert.
Ich habe nicht darauf geachtet, da es in den anderen Beispielen nicht vorkommt.
Um dies zu vermeiden, fügen Sie einfach
pointer-events:nonezum Float-Element hinzu.Danke für das tolle Beispiel! Das Einzige, was mir aufgefallen ist, ist, dass die `height:100%;` auf dem äußeren Element und auf den `.float`-Elementen auch die Höhe des Bildes einschließt. Wenn der Inhalt der Box kleiner ist als das Bild, führt dies dazu, dass das Element am unteren Rand etwas "Leerraum" hat. Sie können sehen, was ich meine, in diesem Fiddle, wo sich ein Abstand zwischen dem Button und dem Container-Rand befindet: https://jsfiddle.net/s8jqmb6v/
Wenn die `height:100%` die Bildhöhe nicht einschließen würde, würde das Bild etwas weiter nach oben geschoben werden, sodass auch die H3 umbrechen würde.
Hoffentlich verstehen Sie, was ich meine, und haben einige Hinweise/einen Workaround dafür?
Leider stoßen Sie hier auf eine Einschränkung dieser Technik. Wenn das Bild im Verhältnis zu Ihrem Inhalt groß genug ist, werden Sie auf ein solches Problem stoßen, da die Höhenberechnung etwas komplex ist.
Entschuldigung, aber ich kenne keinen guten Workaround für diesen Fall. Wahrscheinlich werde ich in Zukunft einen finden.
Danke! Ich habe stundenlang versucht, das zu erreichen, bis ich endlich diese Seite gefunden habe!!!
Damit konnte ich meine Seite innerhalb weniger Minuten umstrukturieren, um sie zum Laufen zu bringen. Großartig!
Es scheint jetzt möglich zu sein, dasselbe Ergebnis zu erzielen, ohne das Bild in `.box` einwickeln zu müssen, indem man `height: 100%; object-fit: cover; object-position: bottom;` direkt auf das `img` anwendet.
*object-fit: contain;
Toller Artikel! Ich habe ihn über Stackoverflow gefunden. Früher habe ich mit JavaScript herumgespielt, aber Sie zeigen, dass es auch ohne geht, wenn die Höhe des zu schwebenden Elements bekannt ist.
Was ist mit einer Situation, in der sie nicht bekannt ist? Z.B. ein `figure`-Element mit einer Bildunterschrift. Geht das auch ohne JS?
Tatsächlich gibt es eine reine CSS-Lösung, die auch mit Internet Explorer 10 und 11 funktioniert!
Und Sie können prozentuale Breiten für das Bild verwenden, wenn Sie die Seitenverhältnisse des Bildes kennen. Prozentuale Höhen funktionieren leider nicht.
Bewegen Sie einfach Ihre Maus nach links und rechts, um das Div zu vergrößern (getan, da IE die
resize:-Eigenschaft nicht unterstützt).Leider funktioniert es nicht zuverlässig. Bei bestimmten Breiten können einige Wörter abgeschnitten werden – das Wrapper-Element erhöht seine Höhe nicht wie benötigt. Das passiert in meinem Projekt ziemlich oft, aber ich konnte es auf einem Pen aus dem Artikel reproduzieren. Es kann sowohl in Firefox als auch in Chrome reproduziert werden, und ich denke, größere Bilder verursachen es wahrscheinlicher. Ändern Sie einfach langsam die Breite des Wrappers, bis das letzte Wort auf eine neue Zeile umgebrochen wird, und es gibt eine Zeilenumbruchbreite, aber der Wrapper ist immer noch auf seiner vorherigen Höhe.