假设您有一个非常简单的 CSS 网格布局,其中一列固定为 300px
,另一列占用剩余空间,为 1fr
。
.grid {
display: grid;
grid-template-columns: 1fr 300px;
}
这在某种程度上是稳健的。该 1fr
列将占用固定 300px
列留下的任何剩余空间。确实,auto
值也会这样做,但 auto
不太稳健,因为它的尺寸基于内部内容。因此,如果您内容太少,则您的列可能无法填充您想要的整个空间。但是,虽然 1fr
略微更稳健,但它并不能完全保护您免受内容过大的影响!
以下是网格在一些文本内容下正常工作的情况

现在,当我们在该列中放置一个巨大的图像时,观察右侧列如何被推到页面之外

这个问题很容易解决——而且您可能永远不会遇到它,因为此代码段在我们的样式表中非常常见
img {
max-width: 100%;
}

但是某些元素并不那么友好。以臭名昭著的 <pre>
标签为例。假设我们在我们的 1fr
列中放入其中一个标签,其中包含一个长字符串的文本。我们又回到了崩溃状态

这次,事情没有那么容易解决!即使尝试限制 <pre>
的宽度并隐藏溢出也不会起作用
pre {
max-width: 100%;
overflow: hidden;
}
真正的解决方法并不难——我们只需要理解发生了什么。我不能保证我的解释 100% 正确,但我理解的方式是,网格列的最小宽度为 auto
。(顺便说一句,弹性项目也是如此。)
并且由于 auto
完全基于内容,所以可以说它是“无限”大小的,其尺寸会伸缩。如果我们要在列上设置显式宽度,例如 50%
或 400px
,那么我们会说它是“确定”大小的。
要应用我们的修复,我们需要确保该列具有确定的最小宽度,而不是 auto
。
因此,我们可以像这样修复它
.grid {
/* auto minimum width, causing problem */
grid-template-columns: 1fr 300px;
/* fix: minimum width of 0 */
grid-template-columns: minmax(0, 1fr) 300px;
}
或者,我们在占据该网格列的元素上设置实际的 min-width
。在我们的简单演示中,<main>
元素会自动将其自身放置在第一列中,因为它是网格的第一个子元素。
这给了我们这个效果
main {
min-width: 0;
}
我认为在网格定义级别执行此操作更稳健一些。无论如何,它确实有效!看到 <pre>
标签现在如何尊重列的宽度并可以按预期溢出吗?

不错。
感谢您率先尝试,这样我们就不必尝试了
我喜欢这个,我也喜欢 CSS 网格,但是对于 IE 11 用户我们该怎么办?我知道……我知道,但只要微软继续支持它,我就必须也支持它。
您看过我们关于此主题的整个系列文章吗?
这里的解释是
fr
单位的最小尺寸为 auto。然后网格查看项目的min-content
尺寸。如果项目具有尺寸(您已为其设置宽度)或其中包含具有尺寸的内容(例如图像),则min-content
尺寸可能比您认为1fr
将提供的可用空间份额大得多。很容易将1fr
视为“网格容器中的一部分空间”,而实际上它是剩余空间的一部分。如果有空间增长,则轨道将从该
min-content
尺寸开始增长,并分配空间。如您所指出的,如果您希望强制执行等宽轨道,则使用
minmax
是最佳做法,因为这表示“我希望该轨道的min-content
尺寸为 0”,在这种情况下,您可能会遇到溢出,因为您失去了弹性。感谢您的努力并提出这个有趣的用例……
太棒了!感谢您为我们省去了麻烦;D
您将列从“300px 1fr”反转为“1fr 300px”。这有什么意义/区别?
感谢这个!
帮助我们修复了一个我们在 flexbox 中遇到的 bug,其中高度应该由
flex: 1
计算,但实际上却变成了被遮挡的滚动组件的整个高度。仅在 Firefox 中发生。