How to make images within css grid container lines?

The code below shows the intended mode when I resize the window in Chrome 60 and in Firefox 55 (but not in iOS Safari 10.3, this is most likely another question why it works poorly in Safari).

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="/img/acf5ea011898a35d901f674bc9d1b5b7.png" alt="." /> </div> <div class="tile"> <img src="/img/acf5ea011898a35d901f674bc9d1b5b7.png" alt="." /> </div> <div class="tile"> <img src="/img/acf5ea011898a35d901f674bc9d1b5b7.png" alt="." /> </div> <div class="tile"> <img src="/img/acf5ea011898a35d901f674bc9d1b5b7.png" alt="." /> </div> <div class="tile"> <img src="/img/acf5ea011898a35d901f674bc9d1b5b7.png" alt="." /> </div> <div class="tile"> <img src="/img/acf5ea011898a35d901f674bc9d1b5b7.png" alt="." /> </div> </div> 

It is important that the aspect ratio of the images (2: 1)

dummy image

saved. I would also expect:

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

or

 grid-template-rows: auto auto auto; 

makes images placed on grid lines, but none of them does. FROM:

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

I get the desired behavior. How can I avoid the very development of mathematics? In other words, what should I do to work grid-template-rows: 1fr 1fr 1fr; (or something similar)?

It is already difficult to determine the height of a container element in CSS on a real page. The goal is to solve this problem using CSS mesh diagrams; no javascript and no background images.


Update: I initially ruled out hacking for two reasons.

  • I thought (due to some misunderstandings) that the url background image should be in the CSS file, but this is not the case: I can use inline styles and have it in HTML.

  • He felt like a hacker. Seeing how difficult and random it is with nested flexible containers nested inside the grid container to make it work on Safari, I just resorted to hacking the background image, since it is much cleaner and works in all tested browsers (Chrome, Firefox, Safari).

In the end, this is not an accepted answer that helped solve my problem.

+8
html css image css3 css-grid
source share
3 answers

You have installed images height: 100% . But 100% of what? 100% container? 100% view? 100% row? If so, what is the height of the line?

Chrome and Firefox give you a fair idea of โ€‹โ€‹your intentions. They introduced algorithms designed to go beyond specific instructions to improve user experience. They call these changes "interventions ."

Safari does not. Safari strictly adheres to the specification language, which states that the percentage height of an element must have a certain height for the parent, otherwise it is ignored.

These browser differences are explained in more detail here:

  • CSS safari height error in CSS grid
  • Chrome / Safari does not fill 100% of the height of the flexible parent

Then you should keep in mind that the default grid elements cannot be smaller than their contents. If your lines are set to 1fr , but the images are higher than the allocated space, the lines should expand. You can override this behavior with min-height: 0 / min-width: 0 or overflow with any value other than visible .

This is explained in more detail here:

  • Prevent stretching grid elements in CSS grid layout
  • Why is the flex element not compressed to the size of the content?

However, once you define the above guide, you can probably get your layout to work in Safari with a combination of grid properties and flexibility:

 * { 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
source share

You can use grid-template-rows: 1fr 1fr 1fr and, more importantly, you should reset the min-width and min-height values โ€‹โ€‹of the grid elements, which are auto by default (as much as the content).

To provide a more reasonable default minimum size for grid elements, this specification defines that the automatic min-width / min-height value also applies the automatic minimum size in the specified axis to grid elements whose overflow is visible and that spans at least one track whose minimum Track tracking function - auto. (The effect is similar to the automatic minimum size superimposed on flexible elements.)

Source: W3C

This is similar to the automatic flex rule with flexboxes. See the demo below, where I reset them to zero:

 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
source share

I don't know how convenient it is for the images to fit, but you could use minmax() . minmax() allows you to set the minimum and maximum value for the grid size. Setting auto for min and 33% for max will allow them to get as little content as possible and up to 33% of the height of the mesh container, but no more. This will save all the grid elements at a maximum height of 99% of 60vh, which is occupied by the grid container.

This is not a completely automatic way that you were hoping to get ... you are still declaring the size, even if it is relative. It avoids the awkward looking calc((60vh - 12px) / 3) , although there is nothing wrong with using this method if there are no other restrictions in your post.

However, kukkuz's answer and resetting min-height is the best solution, and this is what I was missing.

 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
source share

All Articles