Behalten Sie das Bildseitenverhältnis bei, wenn Sie die Höhe ändern

114

Wie kann ich mit dem CSS-Flexbox-Modell ein Bild zwingen, sein Seitenverhältnis beizubehalten?

JS Fiddle: http://jsfiddle.net/xLc2Le0k/2/

Beachten Sie, dass sich die Bilder dehnen oder verkleinern, um die Breite des Containers auszufüllen. Das ist in Ordnung, aber können wir es auch dehnen oder verkleinern lassen, um die Bildproportionen beizubehalten?

HTML

<div class="slider">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
    <img src="http://www.placebacon.net/400/300" alt="Bacn">
</div>

CSS

.slider {
    display: flex;
}
.slider img {
    margin: 0 5px;
}
coderMe
quelle
1
Soweit ich weiß, ist die beste Lösung, eine <div>mit dem CSSbackground-image: url(...);background-size:contain; background-repeat:no-repeat
Blazemonger
1
Hier gibt es einige interessante Hinweise, aber was ist, wenn die Bilder nicht bereits das gleiche Verhältnis haben? Hinzufügen und 'extra' div, ist das Letzte, worüber wir uns Sorgen machen müssen. Warum nicht einen Testfall wie diese statt: jsfiddle.net/sheriffderek/999Lg9qv
sheriffderek

Antworten:

67

Wenn Sie für IMG-Tags eine Seite definieren, wird die Größe der anderen Seite geändert, um das Seitenverhältnis beizubehalten, und standardmäßig werden Bilder auf ihre ursprüngliche Größe erweitert.

Wenn Sie diese Tatsache verwenden, wenn Sie jedes img-Tag in ein div-Tag einwickeln und seine Breite auf 100% des übergeordneten div einstellen, entspricht die Höhe dem gewünschten Seitenverhältnis.

http://jsfiddle.net/0o5tpbxg/

* {
    margin: 0;
    padding: 0;
}
.slider {
    display: flex;
}
.slider .slide img {
    width: 100%;
}
Muhammad Umer
quelle
2
Ich weiß, dass es zwei Antworten gibt, die die Verwendung von divs vorschlagen, aber ich markiere diese Antwort als richtig, weil sie erklärt, warum die Bildhöhen anders sind als ich erwartet hatte. In der Tat ist dies ein normales und korrektes Verhalten und es ist unwahrscheinlich, dass es "behoben" wird, da es kein Fehler ist.
CoderMe
18
Diese Antwort spricht jedoch nichts über Flexbox, da sich Bilder im Flexbox-Container anders verhalten. Wenn Sie eine Seite einstellen, wird die Größe der anderen Seite nicht proportional geändert. Das Einwickeln in einen Nicht-Flexbox-Container hilft, führt jedoch zu unnötigem Markup, wodurch die Semantik verloren geht.
Robert Koritnik
3
Es sieht nicht so aus, als ob Sie ein Wrapping-Div benötigen, damit dies funktioniert: jsfiddle.net/xLc2Le0k/120
Rick Strahl
4
Aber was ist damit? jsfiddle.net/xLc2Le0k/15 Ich denke, dass diese Lösung ein Zufall ist, der nur funktioniert, weil die Bilder alle das gleiche Verhältnis haben. Randnotiz: Es geht keine 'Semantik' verloren, wenn ein Bild zur Positionierung in einem Div platziert wird, insbesondere wenn es sich um reaktionsschnelle Bilder handelt.
Sheriffderek
1
Ernsthaft die sauberste Lösung und es funktioniert mit Bild!
Shaneonabike
64

Um zu verhindern, dass sich Bilder in einem flexiblen Elternteil in einer der Achsen dehnen, habe ich einige Lösungen gefunden.

Sie können versuchen, die Objektanpassung für das Bild zu verwenden, z

object-fit: contain;

http://jsfiddle.net/ykw3sfjd/

Oder Sie können flexspezifische Regeln hinzufügen, die in einigen Fällen besser funktionieren.

align-self: center;
flex: 0 0 auto;
Matty Bileam
quelle
4
Objektanpassung könnte eine gute Lösung sein, wenn die Unterstützung in IE und Edge auch bis Edge 14 nicht fehlt
Daniels
1
Schauen Sie sich diesen objektangepassten Fallback für Edge an IE an .
Andrei Telteu
Ich habe diesen Fallback selbst verwendet, funktioniert sehr gut.
Matty Bileam
1
@daniels Edge hat jetzt Objektanpassung in der Entwicklung: developer.microsoft.com/en-us/microsoft-edge/platform/status/…
AMDG
1
object-fit: contain;tat den Trick für mich, als ich nur das Problem in Chrom hatte, ff war in Ordnung.
Benjamin Peter
53

Es ist nicht erforderlich, ein enthaltendes div hinzuzufügen.

Die Standardeinstellung für die CSS-Eigenschaft "Align-Items" ist "Stretch". Dadurch werden Ihre Bilder auf ihre volle ursprüngliche Höhe gedehnt. Wenn Sie die CSS-Eigenschaft "align-items" auf "flex-start" setzen, wird Ihr Problem behoben.

.slider {
    display: flex;
    align-items: flex-start;  /* ADD THIS! */
}
Marvin Herbold
quelle
3
Ahh ... danke, dass du die Dinge tatsächlich auf die unterstützte Weise gemacht hast. Ich las die Antworten bis dahin und konnte nicht glauben, dass wir nur schmutzige Hacks hatten.
Félix Gagnon-Grenier
35

Die meisten Bilder mit intrinsischen Abmessungen , dh einer natürlichen Größe, wie ein jpegBild. Wenn die angegebene Größe sowohl die Breite als auch die Höhe definiert, wird der fehlende Wert anhand des Eigenverhältnisses ermittelt ... - siehe MDN .

Dies funktioniert jedoch nicht wie erwartet, wenn die Bilder, soweit ich weiß , mit dem aktuellen Flexible Box Layout Module Level 1 als direkte Flex-Elemente festgelegt werden .

Sehen Sie sich diese Diskussionen an und Fehlerberichte könnten verwandt sein:


Um dieses Problem zu umgehen, können Sie jedes <img>mit einem <div>oder einem <span>oder so umschließen.

jsFiddle

.slider {
  display: flex;
}

.slider>div {
  min-width: 0; /* why? see below. */
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

4.5 Implizite Mindestgröße von Flex-Elementen

Um eine angemessene Standardmindestgröße für bieten flex Produkte , stellt diese Spezifikation einen neuen Autowert als Anfangswert der min-width und min-height Eigenschaften definiert in CSS 2.1.


Alternativ können Sie tablestattdessen das CSS- Layout verwenden, mit dem Sie ähnliche Ergebnisse flexboxerzielen, da es auch für IE8 in mehr Browsern funktioniert.

jsFiddle

.slider {
  display: table;
  width: 100%;
  table-layout: fixed;
  border-collapse: collapse;
}

.slider>div {
  display: table-cell;
  vertical-align: top;
}

.slider>div>img {
  max-width: 100%;
  height: auto;
}
<div class="slider">
  <div><img src="https://picsum.photos/400/300?image=0" /></div>
  <div><img src="https://picsum.photos/400/300?image=1" /></div>
  <div><img src="https://picsum.photos/400/300?image=2" /></div>
  <div><img src="https://picsum.photos/400/300?image=3" /></div>
</div>

Aufkleber
quelle
Das erste Snippet benötigt .slider > div{min-width:0}neue Browser, die dies unterstützen min-width: auto.
Oriol
3
In der Flexbox-Spezifikation wurde ein neuer autoWert als Standardwert für min-widthund min-height(zuvor 0) eingeführt. Chrome implementiert es noch nicht, sodass Ihr erstes Snippet funktioniert. Neue Browser benötigen es jedoch, damit die Flex-Elemente kleiner als die Standardbreite der Bilder werden.
Oriol
2
+1 Dies sollte als Antwort akzeptiert werden, da es sich um Bilder im Flexbox-Modell handelt, was in diesem Fall das Hauptproblem darstellt ...
Robert Koritnik
Die Tabelle ist großartig, wenn sich Ihr Layout an verschiedenen Haltepunkten nicht ändert, aber das ist heutzutage unwahrscheinlich.
Sheriffderek
1
Was ist, wenn die Bilder nicht alle das gleiche Verhältnis haben? jsfiddle.net/sheriffderek/5u7y21we
sheriffderek
6

Ich habe in letzter Zeit mit Flexbox herumgespielt und bin durch Experimente und die folgenden Überlegungen zu einer Lösung gekommen. In Wirklichkeit bin ich mir jedoch nicht sicher, ob genau das passiert.

Wenn die tatsächliche Breite durch das Flex-System beeinflusst wird. Nachdem die Breite der Elemente die maximale Breite des übergeordneten Elements erreicht hat, wird die in CSS festgelegte zusätzliche Breite ignoriert. Dann ist es sicher, die Breite auf 100% einzustellen.

Da die Höhe des img-Tags vom Bild selbst abgeleitet wird, kann das Setzen der Höhe auf 0% etwas bewirken. (Hier ist mir unklar, was ... aber es machte für mich Sinn, dass es das Problem beheben sollte)

DEMO

(Denken Sie daran, es hier zuerst gesehen zu haben!)

.slider {
    display: flex;
}
.slider img {
    height: 0%;
    width: 100%;
    margin: 0 5px;
}

Funktioniert noch nur in Chrom

Muhammad Umer
quelle
Interessant, aber es scheint ein Fehler zu sein. Gemäß der Spezifikation "wird der Prozentsatz in Bezug auf die Höhe des enthaltenden Blocks der generierten Box berechnet. Wenn die Höhe des enthaltenden Blocks nicht explizit angegeben wird (dh von der Höhe des Inhalts abhängt) und dieses Element nicht absolut positioniert ist berechnet der Wertauto ". Genau das passiert in Firefox.
Oriol
jsfiddle.net/xLc2Le0k/8 erklärt den Unterschied zwischen ff und Chrome. dafür
Muhammad Umer
Breite scheint in ff zu tun, was Höhe in Chrom tut.
Muhammad Umer
Es ist interessant, aber ich befürchte, dass Nur-X-Browser-Lösungen keine wirklichen Lösungen sind. Ihre kommentierte Geige hier: jsfiddle.net/xLc2Le0k/8 ist jedoch in FF absolut faszinierend . Dies scheint zu zeigen, dass FF die Bildhöhe "proportional" zur Bildhöhe macht, wenn sie wirklich 100% wäre. Mit anderen Worten, das Bild "weiß" nichts über die Anzeige des Containers: flex. Dies erklärt, warum in FF das Bild größer ist, wenn Sie die Breite des Bilds auf 100% einstellen, als wenn Sie die Breite auf Auto einstellen.
coderMe
Dies ist ein bisschen schließen ... aber funktioniert nur in Chrome: jsfiddle.net/sheriffderek/xLc2Le0k/270
sheriffderek
2

Dieses Verhalten wird erwartet. Der Flex-Container streckt standardmäßig alle seine untergeordneten Elemente. Bild haben keine Ausnahme. (dh Eltern haben align-items: stretchEigentum)

Um das Seitenverhältnis beizubehalten, haben wir zwei Lösungen:

  1. Ersetzen Sie entweder die Standardeigenschaft align-items: stretchdurch align-items: flex-startoder align-self: centerusw., http://jsfiddle.net/e394Lqnt/3/

oder

  1. Set align Eigenschaft ausschließlich für das Kind selbst: wie, align-self: centeroder align-self: flex-startusw. http://jsfiddle.net/e394Lqnt/2/
Asim KT
quelle
-1

Eigentlich habe ich herausgefunden, dass der Container des Bild-Tags eine Höhe haben muss, um das Verhältnis des Bildes beizubehalten. zum Beispiel>

.container{display:flex; height:100%;} img{width:100%;height:auto;}

dann wird Ihr Container in Ihrem HTML das Tag-Bild umschließen

<div class="container"><img src="image.jpg" alt="image" /></div>

Dies funktioniert für IE und andere Browser

kengreg
quelle
-1

Ich hatte gerade das gleiche Problem. Verwenden Sie die Flex-Ausrichtung, um Ihre Elemente zu zentrieren. Sie müssen align-items: centeranstelle von verwenden align-content: center. Dadurch wird das Seitenverhältnis beibehalten, während bei der Ausrichtung des Inhalts das Seitenverhältnis nicht beibehalten wird.

Clinton Green
quelle