我刚开始使用网格布局,并注意到它在相同的视口(viewport)大小上呈现不同:
(1) 最大化窗口的初始显示,这里没什么特别的:
(2) 使用 调整浏览器窗口大小后按钮左侧边栏中的文本被换行:
(3) 在不改变大小的情况下刷新浏览器窗口后,去掉左侧边栏中的换行:
注意左侧边栏中的文本突然不再换行,而视口(viewport)大小仍然相同!
怎么可能? 我在 Windows 上使用 Chrome 89.0.4389.82(最新稳定版)。使用 Firefox 86 我也有奇怪的大小调整效果(在小窗口上换行,并且在最大化时换行不会被删除)。想知道两个主要浏览器在简单网格上会出现错误吗?我做错了什么/失踪了吗?
使用的 CSS/HTML:
<style type="text/css">
body {
height: 100vh;
margin: 0;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: auto minmax(0, 1fr);
}
header {
background-color: #add790;
text-align: center;
grid-column: span 2;
}
nav {
background-color: orange;
overflow: auto;
padding: 1em;
}
article {
overflow: auto;
padding: 1em;
}
</style>
<header>
<h1>Title</h1>
</header>
<nav>
<p>Navigation</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
</nav>
<article>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
</article>
更新 : 添加了nav > p { min-width: max-content; }
规则:调整窗口大小后:
点击刷新后:
请注意文本和滚动条之间的红色标记间隙。
更新 2:与
width: fit-content;
导航:刷新前:
刷新后:
所以导航栏保持完全相同的大小,但主要内容位置发生了变化。
最佳答案
没什么奇怪的,第一列设置为auto
( grid-template-columns: auto ...
) 如此描述 here它的行为如下:
auto
As a maximum represents the largest max-content size of the items in that track. As a minimum represents the largest minimum size of items in that track (specified by the min-width/min-height of the items). This is often, though not always, the min-content size. If used outside of minmax() notation, auto represents the range between the minimum and maxium described above. This behaves similarly to min-content(min-content,max-content) in most cases.
通过 CSS 规则
nav > p { min-width: max-content; }
可以轻松修复“怪癖”在深入了解细节之前,先说明一下环境:
OS: Ubuntu 20.04.2 LTS
Browser-1: Firefox 85.0.1 (64-bit)
Browser-2: Chromium Version 89.0.4389.72 (Official Build) snap (64-bit)
列出所有场景:
1a. initial maximized
window
1b. initial maximized
iframe
2a. initial minimized
window
2b. initial minimized
iframe
3a. maximize
window
3b. maximize
iframe
4a. minimize
window
4b. minimize
iframe
5 .
overflow: scroll
(in place ofoverflow: auto
, in all above scenarios)
max-content
与场景相关的行为:
Chromium
fixes wrapping in (
4b
)no effect in (
5
)Firefox
fixes wrapping in (
2a
,2b
,3a
,3b
,4a
,4b
)no effect in (
5
)
padding
nav
中的问题相关场景:
Chromium
no right padding in (
4b
)double right padding in (
3a
,3b
), i.e. CSS padding1em
+ scrollbar width~17px
no issues in (
5
)Firefox
no right padding in (
2a
,2b
,3a
,3b
,4a
,4b
)no issues in (
5
)
可以观察到在场景(
5
)中不存在问题,即滚动条始终可见时,尽管这种解决方案不是很吸引人。综上所述,
load
之间不同行为的解释对比 resize
可能如下:
On
load
, since the size of window is known and nothing is rendered yet, content (width+padding+scroll+border) is accommodated recursively as many times as needed till fits the geometry with minimal performance penalties.On
resize
, when content is already on screen, subsequent layout shifts are rendered in frames to accommodate the new geometry (note that application resize is a feature controlled by OS, not to be confused withwindow
resize
), so during resize, when browser engine detects an overflow, the containernav
may have no enough space to fit scrollbar, and although there is plenty of space in the adjacent container, to avoid a reflow avalanche (which require considerable processing resources and lack of these cause visual artifacts), the space for scrollbar is taken from that context.
这意味着单独使用 CSS 解决问题的可能性很小,因为它不提供任何控制,也不会很快在浏览器中修复此行为,因此我们唯一的解决方案是使用 javascript 处理此问题.
最明显的解决办法是听
resize
window
上的事件并进一步触发内容重排,对于这里的简单布局,切换 overflow: initial
代替overflow: auto
就足够了,更复杂的布局可能需要更激进的样式,例如 width: 0 !important
, 用于最终控制 resize observer
可用于特定目标,仅在该上下文中触发回流。将这些结论放在一起,接下来是解决上述所有场景(在我的环境中*)的解决方法:
- Add CSS rule
nav > p { min-width: max-content; }
- Add CSS rule
.reflowing * { overflow: initial; }
- Attach
resize
event listener on window which will toggle the class.reflowing
ondocument.body
for a period long enough to generate a content reflow, onerequestAnimationFrame
(~16ms) seems to be enough here.
实现:
const initReflow = el => requestAnimationFrame(() => {
el.classList.add('reflowing');
requestAnimationFrame(() => el.classList.remove('reflowing'));
});
addEventListener('resize', () => initReflow(document.body));
body {
background: white;
height: 100vh;
margin: 0;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: auto minmax(0, 1fr);
}
header {
background-color: #add790;
text-align: center;
grid-column: span 2;
}
nav {
background-color: orange;
overflow: auto;
padding: 1em;
}
article {
overflow: auto;
padding: 1em;
}
nav > p {
min-width: max-content;
}
.reflowing * {
overflow: initial;
}
<header>
<h1>Title</h1>
</header>
<nav>
<p>Navigation</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
<p>Some text.</p>
</nav>
<article>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
<p>Here too there should be a local scrollbar.</p>
</article>
资源:
Windowing system
Compositing window manager
Multiple buffering
How browsers work
CSS block formatting context
CSS overflow
免责声明:以上结论并非来自科学或专业 Material ,而是通用资源,也是个人经验,因此应持保留态度。
关于html - 刷新和调整浏览器窗口大小时网格布局呈现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66572128/