如何使图像保持在css网格容器的行内?

Ali*_*Ali 10 html css image css3 css-grid

下面的代码显示了我在Chrome 60和Firefox 55中调整窗口大小时的预期行为(但在iOS Safari 10.3中没有;这很可能是另一个问题,为什么它在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;
}
Run Code Online (Sandbox Code Playgroud)
 <!-- 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>
Run Code Online (Sandbox Code Playgroud)

重要的是图像的纵横比(2:1)

虚拟图像

保留下来.我原以为:

grid-template-rows: 1fr 1fr 1fr;
Run Code Online (Sandbox Code Playgroud)

要么:

grid-template-rows: auto auto auto;
Run Code Online (Sandbox Code Playgroud)

使图像适合网格的行,但它们都不适合.附:

grid-template-rows: repeat(3, calc((60vh - 12px)/3));
Run Code Online (Sandbox Code Playgroud)

我得到了理想的行为.我怎么能避免自己算数学呢?换句话说,我应该怎么做grid-template-rows: 1fr 1fr 1fr;(或类似的东西)?

已经很难在实际页面上计算出CSS中容器元素的高度.目标是用CSS网格布局解决它; 没有JavaScript,没有背景图片黑客.


更新:我最初排除背景图片黑客有两个原因.

  1. 我认为(由于一些误解)背景图片网址必须在CSS文件中,但事实并非如此:我可以使用内联样式并将其放在HTML中.

  2. 感到很骇人.在看到嵌套在一个网格容器中的嵌套Flex容器之后变得多么复杂和混乱之后,为了使它在Safari上工作,我只是采用了背景图像黑客,因为它非常清晰,适用于所有测试的浏览器(Chrome,Firefox,苹果浏览器).

最后,它不是有助于解决我的问题的公认答案.

kuk*_*kuz 6

您可以使用grid-template-rows: 1fr 1fr 1fr,更重要的是您必须重置网格项目的默认值min-width(与内容一样多)。min-heightauto

为了给网格项提供更合理的默认最小尺寸,本规范定义了 min-width/min-height 的自动值也将指定轴上的自动最小尺寸应用于溢出可见且跨越至少一个的网格项。最小轨道大小调整功能为自动的轨道。(效果类似于对弹性项目施加的自动最小尺寸。)

来源:W3C

这类似于flexboxes自动弹性项目规则。请参阅下面的演示,我将它们重置为零

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;
}
Run Code Online (Sandbox Code Playgroud)
<!-- 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>
Run Code Online (Sandbox Code Playgroud)


Mic*_*l_B 5

您已将图像设置为height: 100%. 但 100% 是什么?100% 的容器?100% 的视口?100% 的行?如果是这样,该行的高度是多少?

Chrome 和 Firefox 会对您的意图做出有根据的猜测。他们实施的算法旨在超越规范指导,以改善用户体验。他们称这些修改为“干预”

Safari 不这样做。Safari 严格遵守规范语言,该语言规定元素上的百分比高度必须在父元素上定义高度,否则将被忽略。

这些浏览器差异在这里有更详细的解释:

然后你必须考虑网格项默认不能小于其内容。如果您的行设置为1fr,但图像高于分配的空间,则行必须扩展。您可以使用min-height: 0/min-width: 0overflowvisible覆盖此行为。

此处更详细地解释了此行为:

不过,一旦您考虑了上面的指导,您就可以通过结合 grid 和 flex 属性让您的布局在 Safari 中工作:

* {
  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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)

jsFiddle