html - 刷新和调整浏览器窗口大小时网格布局呈现不同

标签 html css google-chrome firefox css-grid

我刚开始使用网格布局,并注意到它在相同的视口(viewport)大小上呈现不同:
(1) 最大化窗口的初始显示,这里没什么特别的:
enter image description here
(2) 使用 enter image description here 调整浏览器窗口大小后按钮左侧边栏中的文本被换行:
enter image description here
(3) 在不改变大小的情况下刷新浏览器窗口后,去掉左侧边栏中的换行:
enter image description here
注意左侧边栏中的文本突然不再换行,而视口(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; }规则:
调整窗口大小后:
enter image description here
点击刷新后:
enter image description here
请注意文本和滚动条之间的红色标记间隙。
更新 2:width: fit-content;导航:
刷新前:
enter image description here
刷新后:
enter image description here
所以导航栏保持完全相同的大小,但主要内容位置发生了变化。

最佳答案

没什么奇怪的,第一列设置为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 of overflow: auto, in all above scenarios)


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

    fixes wrapping in (4b)

    no effect in (5)

  2. Firefox

    fixes wrapping in (2a, 2b, 3a, 3b, 4a, 4b)

    no effect in (5)


padding nav 中的问题相关场景:
  1. Chromium

    no right padding in (4b)

    double right padding in (3a, 3b), i.e. CSS padding 1em + scrollbar width ~17px

    no issues in (5)

  2. Firefox

    no right padding in (2a, 2b, 3a, 3b, 4a, 4b)

    no issues in (5)


可以观察到在场景(5)中不存在问题,即滚动条始终可见时,尽管这种解决方案不是很吸引人。
综上所述,load 之间不同行为的解释对比 resize可能如下:
  1. 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.

  2. 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 with window resize), so during resize, when browser engine detects an overflow, the container nav 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可用于特定目标,仅在该上下文中触发回流。
将这些结论放在一起,接下来是解决上述所有场景(在我的环境中*)的解决方法:
  1. Add CSS rule nav > p { min-width: max-content; }
  2. Add CSS rule .reflowing * { overflow: initial; }
  3. Attach resize event listener on window which will toggle the class .reflowing on document.body for a period long enough to generate a content reflow, one requestAnimationFrame (~16ms) seems to be enough here.

  • 注:这完全修复了 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>

    资源:
    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/

    相关文章:

    javascript - 如何将 HTML POST 数据转换为 JSON?

    html - 使 Bootstrap 仪表板示例侧边栏在移动设备上可见/可用

    css - 悬停时 bootstrap .btn-default 的背景色是什么

    javascript - 如何用svg连接不同位置的点?

    google-chrome - 在 Chrome 开发者工具中禁用 CSS 更改的自动保存

    html - IE7 与 FF float 问题

    jquery - 如何使用 CSS 创建管理固定背景?

    javascript - Chrome 远程调试 - 获取页面通知

    javascript - 滑出和滑入菜单边栏 html, css

    javascript - 在 Google 移动设备上被 robots.txt 屏蔽的资源