繁体   English   中英

网格布局在刷新和调整浏览器大小时呈现不同 window

[英]Grid layout rendered differently on refresh vs. resizing browser window

我刚开始使用网格布局,并注意到它在相同的视口大小上呈现不同:

(1) 初始显示在最大化的window,这里没什么特别的: 在此处输入图像描述

(2) 使用 window 调整浏览器大小后在此处输入图像描述 按钮左侧边栏中的文本被换行: 在此处输入图像描述

(3) 在不改变大小的情况下刷新浏览器 window 后,去掉左侧边栏中的换行: 在此处输入图像描述 请注意,左侧边栏中的文本突然不再换行,而视口大小仍然相同!

这个怎么可能? 我正在使用 Chrome 89.0.4389.82(最新稳定版)的 Windows。 使用 Firefox 86 我也有奇怪的调整大小效果(在小 windows 上换行,并且在最大化时不会删除换行)。 想知道两个主要浏览器在简单网格上可能有错误吗? 我做错了什么/失踪了吗?

使用的 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; } nav > p { min-width: max-content; }规则:

调整 window 的大小后: 在此处输入图像描述 点击刷新后: 在此处输入图像描述 请注意文本和滚动条之间的红色标记间隙。

更新 2: width: fit-content; 对于导航:刷新前: 在此处输入图像描述 刷新后: 在此处输入图像描述 所以导航栏保持完全相同的大小,但主要内容 position 被移动。

没什么奇怪的,第一列设置为autogrid-template-columns: auto... ),所以如此处所述,它的行为如下:

汽车

最大值表示该轨道中项目的最大最大内容大小。 作为最小值表示该轨道中项目的最大最小尺寸(由项目的最小宽度/最小高度指定)。 这通常是(但不总是)最小内容大小。 如果在 minmax() 表示法之外使用,则 auto 表示上述最小值和最大值之间的范围。 在大多数情况下,这与 min-content(min-content,max-content) 的行为相似。

css rule nav > p { min-width: max-content; } nav > p { min-width: max-content; }

在深入了解细节之前,先说明一下环境:

操作系统: Ubuntu 20.04.2 LTS

浏览器 1: Firefox 85.0.1(64 位)

Browser-2: Chromium 版本 89.0.4389.72(官方构建)快照(64 位)

列出所有场景:

1a。 初始最大化window

1b。 初始最大化iframe

2a. 初始最小化window

2b。 初始最小化iframe

3a。 最大化window

3b。 最大化iframe

4a。 最小化window

4b。 最小化iframe

5. overflow: scroll (代替overflow: auto ,在上述所有场景中)

与场景相关的max-content行为:

  1. 修复包裹( 4b

    ( 5 ) 中没有影响

  2. Firefox

    修复包裹在 ( 2a , 2b , 3a , 3b , 4a , 4b )

    ( 5 ) 中没有影响

nav中与场景相关的padding问题:

  1. ( 4b ) 中没有右填充

    3a3b )中的双右填充,即 CSS 填充1em + 滚动条宽度~17px

    ( 5 ) 中没有问题

  2. Firefox

    ( 2a , 2b , 3a , 3b , 4a , 4b ) 中没有右填充

    ( 5 ) 中没有问题

可以观察到场景( 5 )中不存在问题,即滚动条始终可见时,尽管这种解决方案不是很吸引人。 考虑到上述所有情况, loadresize之间的不同行为的解释可能如下:

  1. load时,由于 window 的大小是已知的并且还没有渲染任何内容,内容(宽度+填充+滚动+边框)会根据需要递归容纳多次,直到以最小的性能损失适应几何形状。

  2. resize时,当内容已经在屏幕上时,随后的布局变化会在框架中呈现以适应新的几何图形(请注意,应用程序调整大小是由操作系统控制的功能,不要与window resize混淆),所以在调整大小期间,当浏览器引擎检测到溢出,容器nav可能没有足够的空间来容纳滚动条,尽管相邻容器中有足够的空间,以避免回流雪崩(这需要大量的处理资源并且缺少这些会导致视觉伪影),但空间for 滚动条取自该上下文。

这意味着它不太可能单独解决 CSS 的问题,因为它不提供任何控制,也不会很快在浏览器中修复此行为,因此我们唯一的解决方案是使用 javascript 处理此问题. 最明显的解决方案是在window上监听resize事件并进一步触发内容重排,对于这里的简单布局,切换overflow: initial代替overflow: auto就足够了,更复杂的布局可能需要更积极的 styles,例如width: 0 !important ,对于最终控制,可以在特定目标上使用resize observer器,仅在该上下文中触发回流。

将这些结论放在一起,接下来是解决上述所有场景(在我的环境中*)的解决方法:

  1. 添加 CSS 规则nav > p { min-width: max-content; } nav > p { min-width: max-content; }
  2. 添加 CSS 规则.reflowing * { overflow: initial; } .reflowing * { overflow: initial; }
  3. 在 window 上附加resize事件侦听器,这将在document.body上切换 class .reflowing足够长的时间以生成内容回流,一个requestAnimationFrame (~16ms) 似乎就足够了。
  • 注意:这完全修复了 Chromium,Firefox 仍然存在需要更多 hack 的填充问题,因为它的滚动条似乎只是可滚动元素的覆盖。

实施:

 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>

资源:

视窗系统

合成 window 管理器

多重缓冲

浏览器的工作原理

CSS 块格式化上下文

CSS 溢出

免责声明:以上结论并非来自科学或专业材料,而是通用资源,也是个人经验,因此应持保留态度。

我观察到nav没有提到width ,因此它在调整大小和刷新时表现不同。

所以,我所做的是添加width: fit-content; nav

nav {
    background-color: orange;
    overflow: auto;
    padding: 1em;
    width: fit-content;
  }

这解决了这个问题。 您可以查看下面截断的完整 html:

 <html><head><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; width: fit-content; } article { overflow: auto; padding: 1em; } </style> </head><body><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></body></html>

问题是滚动条留下了一个宽度 这很奇怪。 我确定这是一个错误

如果您在nav中设置overflow: overlay而不是overflow: auto ,并使用 window 侧板执行该过程,那么您将看到问题(错误)是overflow: auto

我为你的问题做了一个解决方案。 我不能说这个解决方案是一个拐杖

该解决方案包括更新<nav>标记的内容,从而将该标记恢复为其默认宽度

只需将此代码粘贴到您的js文件或<script>标记内即可使用:

window.onresize = function () {
    let nav = document.querySelector("nav");
    let nav_content = nav.innerHTML;
    nav.innerHTML = nav_content;
};

抱歉,这是一个较长的描述。 即使 Chrome 和 Firefox 之间存在不同的行为,并且浏览器本身具有不同行为的不同浏览器事件,也很难描述“为什么”。

简短:原因

“奇怪”行为的原因是浏览器在网格或表格中使用auto自动计算列宽度的(不同)方式。 但是您看到的是(由浏览器编码人员)预期的浏览器行为。 是的:这会让某人发疯...... ;-)

更长:为什么/会发生什么?

一般基础:在您的示例中,导航列的auto width是根据最宽的元素计算的:“导航”一词。 自己检查一下:当您使用文本“一些文本更多单词”使第二个元素更长时,导航栏的宽度会发生变化。

Chrome 中的解释行为

在全屏上 window 足够高,因此导航不需要垂直滚动条。 使用 window 按钮使 window 的高度降低,因此导航栏中的内容有垂直溢出。 浏览器现在添加了垂直滚动条......滚动条发生在导航部分......但由于未知原因,Chrome 没有在该事件中添加自动宽度的重新计算。 滚动条只是添加到导航部分。 至于这个,现在内容包装的内容的位置更少了。 (注意:“导航”这个词不能换行,现在进入填充。所以它似乎有足够的地方,但事实并非如此。)

当您现在重新加载页面时,它是另一个浏览器事件。 您从开始加载页面,浏览器从开始计算自动宽度。 在这种情况下,他从一开始就检测到需要滚动条,并且 Chrome 中的自动宽度计算包括滚动条的宽度到导航部分的宽度。

在这种情况下重新加载时,您可以观察到:导航部分变得稍宽。

Firefox 中的解释行为(略有不同)

在 Firefox 中全屏显示与 Chrome 中相同。 足够的导航高度,因此没有垂直滚动条。 在 Firefox 中使用 window 按钮缩小 window 与 Chrome 中几乎相同:将现在需要的垂直滚动条添加到导航中,并且没有明显的自动宽度重新计算。 但似乎仍然存在重新计算,因为 Firefox 在识别到导航部分的内容比自动宽度空间更宽时额外添加了一个水平滚动条。

最大的不同是现在的重新加载事件。 与 Chrome 相同:Firefox ('re-') 计算自动宽度。 但是在 Firefox 中没有任何变化......那是因为 Firefox 总是在没有滚动条的情况下计算自动宽度,并且只将其添加到内部空间容器中......丑陋......但它就是这样。

调整 window 的高度时自己检查该行为

如果您使用另一个浏览器事件,您可以确认:只需使用鼠标跟踪 window 边缘来调整 window 高度。 在该事件中,两个浏览器都会重新计算自动宽度。 如果新高度使导航栏滚动 Chrome 会添加滚动条并使导航部分更宽。 Firefox 添加了滚动条,但将其放置在导航部分的内部,这意味着导航部分的宽度保持不变。

注意:如果您在导航部分删除一些内容行,更容易观察效果。

简短的可能解决方案:
仅 3 处更正

  1. 向导航部分添加 15 15px的额外填充,以便 Firefox 有足够的空间来放置滚动条。

  2. 将溢出更改为overflow-y: autooverflow-x: hidden以避免Firefox中可能出现的水平滚动条

  3. 避免不必要的导航元素换行。 在您的情况下,您有内联内容( p元素中的普通文本)。 只需添加nav > p { white-space: nowrap } 现在文本不能换行,自动宽度计算采用最宽的文本元素。 如果您现在向导航中的某个元素添加更多单词,则可以检查它,即<p>Some text with more words.</p>

:::
一个很长的解释,但...
只有三个更正...
就这样!!!

见例子。

 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; padding: 1em; padding-right: calc(1em + 15px); // added space scrollbar Firefox overflow-x: hidden; overflow-y: auto; } nav > p { white-space: nowrap; } article { overflow: auto; padding: 1em; }
 <header> <h1>Title</h1> </header> <nav> <p>Navigation</p> <p>Some text with more words.</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>


更新:解决方案描述中的修正。 更改了溢出-Y/-X 的错误值。 例如,他们是正确的。

更新代码
如评论中所述,更正了设置为导航部分(在代码中标记)的填充。

查看此代码是否符合您的喜好

<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;
  }
  nav::-webkit-scrollbar {
    display: none;
  }
  article::-webkit-scrollbar {
    display: none;
  }
</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>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM