我们之前已经介绍过 纵横比框。 它涉及使用填充的技巧,以便元素的宽度和高度按您的喜好成比例。 这并不是一个非常常见的需求,因为固定元素的高度会带来麻烦,但它确实会发生。
降低风险的一种方法是 伪元素策略,其中伪元素将父元素推到纵横比,但如果内部内容将父元素推高,它将变得更高,纵横比将被忽略。
您可以在 CSS 网格中使用这种技术,并应用于网格项目! 虽然有几种不同的应用方式值得思考。
请记住,网格区域和占据它们的元素不一定是相同的大小。
我们刚刚介绍了这一点。 这篇文章最初是本文的一部分,但感觉很重要,所以将其拆分成了一个单独的概念。
了解这一点后,就会引出这样的问题:您需要网格区域具有纵横比,而元素将在其中拉伸吗? 还是元素只需要具有纵横比,无论它位于哪个网格区域?
场景 1) 只有内部元素需要具有纵横比。
很酷。 这可以说是更容易的。 确保元素与网格区域一样宽,然后应用伪元素来处理高度拉伸的纵横比。
<div class="grid">
<div style="--aspect-ratio: 2/1;">2/1</div>
<div style="--aspect-ratio: 3/1;">3/1</div>
<div style="--aspect-ratio: 1/1;">1/1</div>
</div>
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
place-items: start;
}
.grid > * {
background: orange;
width: 100%;
}
.grid > [style^='--aspect-ratio']::before {
content: "";
display: inline-block;
width: 1px;
height: 0;
padding-bottom: calc(100% / (var(--aspect-ratio)));
}
这将导致 这种情况

请注意,您不需要通过自定义属性来应用纵横比。 您可以在 padding-bottom 执行重要操作的地方看到,该值可以是硬编码的,或者可以是其他任何值。
场景 2) 跨越多列以满足宽度需求
我敢打赌,您更有可能需要的是一种方法,可以让一个 2 比 1 的纵横比元素实际跨越两列,而不是被困在一列中。 执行此操作非常类似于我们上面所做的,但是需要添加一些规则来执行跨列操作。
[style="--aspect-ratio: 1/1;"] {
grid-column: span 1;
}
[style="--aspect-ratio: 2/1;"] {
grid-column: span 2;
}
[style="--aspect-ratio: 3/1;"] {
grid-column: span 3;
}
如果我们也添加 grid-auto-flow: dense;
,我们可以得到具有各种纵横比的元素 整齐地排列,以适合它们。

现在是时候提到一些会破坏精确纵横比的小方法了。 一些文本的 line-height
可能会使框比您想要的高度更高。 如果您想使用 grid-gap
,这可能会使纵横比失效。 如果您需要对纵横比进行超精确的控制,您可能更幸运地使用硬编码值。
如果您在一个没有固定行数的网格中执行跨列操作,也会变得很棘手。 也许您正在使用 repeat
/auto-fill
。 您最终可能会遇到列不均匀的情况,不利于纵横比。 也许我们可以在以后再深入探讨这个问题。
场景 3) 强制执行
网格具有二维布局功能,如果我们愿意,我们可以通过强制网格区域为我们想要的高度和宽度来获得纵横比。 例如,没有什么能阻止您将高度和宽度硬编码到列和行中。
.grid {
display: grid;
grid-template-columns: 200px 100px 100px;
grid-template-rows: 100px 200px 300px;
}
我们通常不会这样想,因为我们希望元素具有灵活性和流动性,因此上面使用了基于百分比的技术来实现纵横比。 但是,这是可以做到的。
查看 填充纵横比框,由 Chris Coyier (@chriscoyier) 在 CodePen 上创建。
此示例强制网格区域的大小,并使元素拉伸以填充,但您也可以固定元素的大小。
现实世界的例子
Ben Goshow 写信给我,试图实现这一点,这也是本文的灵感来源。

其中的一部分问题不仅是让框具有纵横比,还要让它们在内部具有对齐能力。 有几种方法可以解决这个问题,但我认为最简单的方法是嵌套网格。 使网格元素 display: grid;
并使用新内部网格的对齐功能。
查看 具有纵横比和内部对齐的 CSS 网格项目,由 Chris Coyier (@chriscoyier) 在 CodePen 上创建。
请注意,在此演示中,元素不是跨行,而是明确放置的(不是必需的,只是一个替代布局方法的示例)。
感谢您对此的见解,Chris。 对于我来说,关键的“顿悟”时刻是您的嵌套网格解决方案。 太棒了!!
TIL:
place-items
属性。看起来
place-items
(甚至不在 caniuse 上?!)与align-items
不同,align-items
在更多浏览器中有效。 我认为,如果演示只在一个(或几个)浏览器中测试,这就是问题所在 :(在演示中将“
place-items: start
”替换为“align-items: start
”,它在例如 Edge 16 中有效。https://mdn.org.cn/en-US/docs/Web/CSS/place-items
仅处于 WD 状态。