如何使图像保留在CSS网格容器的行内? [英] How to make images stay within the rows of a css grid container?
问题描述
下面的代码显示了当我在
Chrome 60和Firefox 55中调整窗口大小时(但不是在iOS Safari 10.3中;这很可能是Safari中出现异常的另一个问题)。
html,body {width:100%;身高:100%;填充:0;保证金:0; border:0; background-color:lightgrey;}。container {box-sizing:border-box;宽度:100%;显示:网格; 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;边框:3px纯黄色;填充:3px; / * grid-gap:20px; * / / *< - 也会把事情弄糟* /}。显示:块; object-fit:包含;宽度:100%;身高:100%;保证金:0; border:0; padding:3px;}
<! - 图像是200 x 100 px:彼此相邻的绿色和蓝色正方形。 - > < div class =container> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < / div>
图像(2:1)
保留了
。我希望可以这样做:
grid-template-rows:1fr 1fr 1fr;
或:
grid-template-rows:auto auto auto;
使图像适合网格的行,但它们都不是。
With:
grid-template-rows:repeat(3,calc((60vh - 12px)/ 3) );
我得到所需的行为。 我该如何避免自己计算数学呢换句话说,我该怎么做才能让 grid-template-rows:1fr 1fr 1fr;
(或类似的东西)有效吗?
现在已经很难计算真实页面中CSS容器元素的高度了。目标是用CSS网格布局解决它;没有JavaScript,也没有背景图像。
更新:我原本排除背景图片黑客有两个原因。
-
我认为(由于一些误解)背景图片
url必须位于CSS文件中,但情况并非如此:我可以使用
内联样式,并将其放在HTML中。 -
它感觉很骇人。在看到了多么复杂和混乱之后,为了使它在Safari上运行,嵌套在柔性容器中的嵌套柔性容器获得了
,我只是简单地使用背景图像hack,因为它显着 清洁并且适用于所有测试过的浏览器(Chrome,Firefox,Safari)。
最后,答案有助于解决我的问题。 / code>。但是100%是什么? 100%的容器? 100%的视口?行的100%?如果是这样,该行的高度是多少?
Chrome和Firefox会对您的意图进行有根据的猜测。他们已经实施了旨在超越规范指导的算法,以改善用户体验。他们称这些修改为 干预措施 。
Safari不会这样做。 Safari严格遵守spec语言,它规定元素上的百分比高度必须在父级上具有定义的高度,否则将被忽略。
这些浏览器差异被解释这里有更详细的介绍:
然后,您必须考虑网格项目默认情况下不能小于其内容。如果您的行设置为 1fr
,但图像比分配的空间高,则行必须展开。您可以使用 min-height:0
/ min-width:0
或溢出
,其值不是可见
。
这种行为会有更详细的解释这里:
- 防止网格物品伸展CSS网格布局
- 为什么flex项目收缩过去的内容大小?<然而,一旦你将上面的指导考虑在内,你或许可以让你的布局在Safari中工作,结合使用它们的组合grid和flex属性:
* {box-sizing:border-box; } body {display:flex; flex-direction:列;身高:100vh;保证金:0; background-color:lightgrey;} header,footer {flex:0 0 100px;背景颜色:番茄;显示:flex; align-items:center; justify-content:center;}。container {flex:1;最小高度:0;显示:网格; grid-template-columns:1fr 1fr;网格自动行:自动; padding:3px;}。tile {display:flex; flex-direction:列; justify-content:center; min-height:0;} img {max-width:100%;最大高度:100%; object-fit:包含; padding:3px;}
< header> HEADER< /头><! - 图像为200 x 100像素:彼此相邻的绿色和蓝色正方形。 - >< div class =container> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / DIV> < div class =tile> < img src =https://i.stack.imgur.com/qbpIG.pngalt =。 /> < / div>< / div>< footer> FOOTER< / footer>
b $ b
jsFiddle
The code below shows the intended behavior when I resize the window in Chrome 60, and in Firefox 55 (but not in iOS Safari 10.3; that is most likely another question why it misbehaves 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="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>
It is important that the aspect ratio of the images (2:1)
is preserved. I would have expected either:
grid-template-rows: 1fr 1fr 1fr;
or:
grid-template-rows: auto auto auto;
makes the images fit within the rows of the grid, but neither of them does. With:
grid-template-rows: repeat(3, calc((60vh - 12px)/3));
I get the desired behavior. How can I avoid working out the math myself? In other words, what should I do so that
grid-template-rows: 1fr 1fr 1fr;
(or something similar) works?It is already difficult to work out the height of the container element in CSS on the real page. The goal is to solve it with CSS grid layout; no JavaScript, and no background image hacks.
Update: I originally excluded the background image hack for two reasons.
I thought (due to some misunderstandings) that the background image url must be in the CSS file, but this is not the case: I can use inline styles and have it in the HTML.
It felt hackish. After having seen how complicated and messy it gets with nested flex containers nested inside a grid container just to make it work on Safari, I simply resorted to the background image hack as it is significantly cleaner and works in all browsers tested (Chrome, Firefox, Safari).
In the end, it is not the accepted answer that helped to solve my problem.
解决方案You have the images set to
height: 100%
. But 100% of what? 100% of the container? 100% of the viewport? 100% of the row? If so, what's the height of the row?Chrome and Firefox make an educated guess about your intentions. They have implemented algorithms designed to go beyond spec guidance in order to improve user experience. They call these modifications "interventions".
Safari doesn't do this. Safari adheres strictly to spec language, which states that a percentage height on an element must have a defined height on the parent, otherwise it is ignored.
These browser differences are explained in more detail here:
Then you have to consider that grid items, by default, cannot be smaller than their content. If your rows are set to
1fr
, but the images are taller than the space allotted, the rows must expand. You can override this behavior withmin-height: 0
/min-width: 0
oroverflow
with any value other thanvisible
.This behavior is explained in more detail here:
- Prevent grid items from stretching in CSS Grid Layout
- Why doesn't flex item shrink past content size?
Still, once you factor in the guidance above, you can probably get your layout to work in Safari with a combination of grid and flex properties:
* { 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
这篇关于如何使图像保留在CSS网格容器的行内?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文