webentwicklung-frage-antwort-db.com.de

Wie lassen sich Bilder in den Zeilen eines CSS-Grid-Containers belassen?

Der folgende Code zeigt das beabsichtigte Verhalten beim Ändern der Fenstergröße in Chrome 60 und Firefox 55 (jedoch nicht in iOS Safari 10.3; dies ist höchstwahrscheinlich eine weitere Frage, warum sich das Fenster in Safari nicht richtig verhält).

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  background-color: lightgrey;
}

.container {
  box-sizing: border-box;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(3, calc((60vh - 12px)/3));
  /*grid-template-rows: 1fr 1fr 1fr;*/
  /*grid-template-rows: auto auto auto;*/
  height: 60vh;
  border: 3px solid yellow;
  padding: 3px;
  /*grid-gap: 20px;*/ /* <-- would also mess things up */
}

.tile {
}

img {
  box-sizing: border-box;
  display: block;
  object-fit: contain;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  padding: 3px;
}
 <!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
 <div class="container">
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
 </div>

Es ist wichtig, dass das Seitenverhältnis der Bilder (2: 1)

 dummy image

ist erhalten. Ich hätte entweder erwartet:

grid-template-rows: 1fr 1fr 1fr;

oder:

grid-template-rows: auto auto auto;

passt die Bilder in die Zeilen des Rasters, aber keines von beiden. Mit:

grid-template-rows: repeat(3, calc((60vh - 12px)/3));

Ich bekomme das gewünschte Verhalten. Wie kann ich es vermeiden, selbst zu rechnen? Mit anderen Worten, was soll ich tun, damit grid-template-rows: 1fr 1fr 1fr; (oder etwas ähnliches) funktioniert?

Es ist bereits schwierig, die Höhe des Containerelements in CSS auf der realen Seite zu berechnen. Das Ziel ist es, es mit CSS-Grid-Layout zu lösen; Kein JavaScript und keine Hintergrundbild-Hacks.


Update: Ich habe den Hintergrundbild-Hack ursprünglich aus zwei Gründen ausgeschlossen.

  1. Ich dachte (aufgrund einiger Missverständnisse), dass die Hintergrundbild-URL in der CSS-Datei sein muss, aber das ist nicht der Fall: Ich kann Inline-Stile verwenden und sie im HTML-Code haben.

  2. Es fühlte sich hackisch an. Nachdem ich gesehen hatte, wie kompliziert und unübersichtlich es mit verschachtelten Flex-Containern ist, die in einem Grid-Container verschachtelt sind, um es auf Safari funktionieren zu lassen, habe ich einfach auf das Hintergrundbild-Hack zurückgegriffen, da es significant sauberer ist und in allen getesteten Browsern funktioniert ( Chrome, Firefox, Safari).

Letztendlich war es nicht die akzeptierte Antwort, die zur Lösung meines Problems beigetragen hat.

8
Ali

Sie haben die Bilder auf height: 100% eingestellt. Aber zu 100% von was? 100% des Behälters? 100% des Darstellungsbereichs 100% der Reihe? Wenn ja, wie hoch ist die Reihe?

Chrome und Firefox machen eine fundierte Vermutung über Ihre Absichten. Sie haben Algorithmen implementiert, die über die Spezifikation der Spezifikationen hinausgehen, um die Benutzererfahrung zu verbessern. Sie nennen diese Modifikationen "Interventionen" .

Safari macht das nicht. Safari hält sich strikt an die Spezifikationssprache, die besagt, dass eine prozentuale Höhe eines Elements eine definierte Höhe für das übergeordnete Element haben muss, andernfalls wird sie ignoriert.

Diese Browser-Unterschiede werden hier näher erläutert: 

Dann müssen Sie berücksichtigen, dass Rasterelemente standardmäßig nicht kleiner sein dürfen als ihr Inhalt. Wenn Ihre Zeilen auf 1fr eingestellt sind, die Bilder jedoch größer sind als der zugewiesene Speicherplatz, müssen die Zeilen erweitert werden. Sie können dieses Verhalten mit min-height: 0/min-width: 0 oder overflow mit einem anderen Wert als visible überschreiben.

Dieses Verhalten wird hier näher erläutert:

Wenn Sie jedoch die obigen Hinweise in Betracht gezogen haben, können Sie Ihr Layout wahrscheinlich mit einer Kombination aus Raster- und Flex-Eigenschaften in Safari verwenden:

* {
  box-sizing: border-box;
}

body {
  display: flex;
  flex-direction: column;
  height: 100vh;
  margin: 0;
  background-color: lightgrey;
}

header,
footer {
  flex: 0 0 100px;
  background-color: tomato;
  display: flex;
  align-items: center;
  justify-content: center;
}

.container {
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: auto;
  padding: 3px;
}

.tile {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 0;
}

img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  padding: 3px;
}
<header>HEADER</header>
<!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
<div class="container">
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
  <div class="tile">
    <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
  </div>
</div>
<footer>FOOTER</footer>

jsFiddle

2
Michael_B

Sie können grid-template-rows: 1fr 1fr 1fr verwenden und, noch wichtiger, Sie müssen die min-width- und min-height-Werte der grid-Elemente zurücksetzen, die standardmäßig auto (so viel wie der Inhalt) ist.

Um eine vernünftigere Standard-Mindestgröße für Gitterelemente bereitzustellen, definiert diese - Spezifikation, dass der Auto-Wert von min-width/min-height auch Eine automatische Mindestgröße in der angegebenen Achse für Gitterelemente verwendet , dessen Überlauf sichtbar ist und die mindestens eine Spur umfassen, deren min. Spurgrößenkorrekturfunktion auto ist. (Der Effekt ist analog zur automatischen Mindestgröße Für Flex-Artikel.)

Quelle: W3C

Dies ist vergleichbar mit der Regel auto flex mit flexboxes . Siehe Demo unten, wo ich sie auf zero setze:

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  background-color: lightgrey;
}

.container {
  box-sizing: border-box;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  height: 60vh;
  border: 3px solid yellow;
  padding: 3px;
  /*grid-gap: 20px;*/ /* <-- would also mess things up */
}

.tile {
  min-width: 0;
  min-height: 0;
}

img {
  box-sizing: border-box;
  display: block;
  object-fit: contain;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  padding: 3px;
}
<!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
 <div class="container">
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
 </div>

3
kukkuz

Ich weiß nicht, wie genau die Bilder passen sollen, aber Sie könnten minmax() verwenden. Mit minmax() können Sie einen Mindest- und Höchstwert für die Rasterzeilengröße festlegen. Wenn Sie auto für min und 33% für max festlegen, werden sie so klein, wie der Inhalt es benötigt, und bis zu 33% der Höhe des Gittercontainers. aber nicht größer . Dadurch werden alle Ihre Gitterelemente zusammen auf einer maximalen Höhe von 99% der 60vh gehalten, die der Gittercontainer aufnimmt. 

Dies ist nicht genau die Art Automatisch , auf die Sie gehofft hatten ... Sie geben immer noch eine Größe an, auch wenn sie relativ ist. Das klobig aussehende calc((60vh - 12px) / 3) wird zwar vermieden, obwohl mit dieser Methode nichts falsch ist, es sei denn, es gibt andere Einschränkungen in Ihrem Beitrag.

Die Antwort von kukkuz und das Zurücksetzen des min-height ist jedoch eine bessere Lösung und ist das, was mir gefehlt hat.

html, body {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 0;
  background-color: lightgrey;
}
.container {
  box-sizing: border-box;
  width: 100%;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: repeat(3, minmax(auto, 33%));
  height: 60vh;
  border: 3px solid yellow;
  padding: 3px;
}
.tile {
    display: grid;
}
img {
  box-sizing: border-box;
  display: block;
  object-fit: contain;
  width: 100%;
  height: 100%;
  margin: 0;
  border: 0;
  padding: 3px;
}
 <!-- The image is 200 x 100 px: a green and a blue square next to each other. -->
 <div class="container">
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
   <div class="tile">
     <img src="https://i.stack.imgur.com/qbpIG.png" alt="." />
   </div>
 </div>

1
TylerH