使用 flexbox 的 Google Chrome 视口锚定扩展方向

Posted

技术标签:

【中文标题】使用 flexbox 的 Google Chrome 视口锚定扩展方向【英文标题】:Google Chrome viewport-anchored expand direction with flexbox 【发布时间】:2017-12-03 05:34:42 【问题描述】:

在 Google Chrome 中存在一个问题,当元素放置在具有 space-betweencenter 对齐内容的 相邻 flex 项目的 flexbox 容器中时,元素相对于视口在不同方向展开/折叠.

这在 Firefox、IE11、Edge 或 Safari 中不是问题,因为元素总是向下扩展。

我很好奇:

Chrome 的行为是否遵循某些规范?如果有,是哪一个? 如果不是,那为什么要在 Chrome 中完成呢? (恕我直言,点击触发器随机消失在屏幕外是可怕的用户体验。) 能否以某种方式修改或禁用 Chrome 的行为?例如。通过 CSS 或元标记?

更新 1:如果可能,我已提交 issue #739860 on chromium bug tracker 寻求 Chromium 开发人员的见解/解释。


以下是插入的两个示例。可以在这支笔中找到描述该问题的完整测试套件:https://codepen.io/jameswilson/full/xrpRPg/ 在此示例中我选择使用 slideToggle 以便展开/折叠运动具有动画效果并且肉眼可见。细节标签也会发生同样的行为,但还没有跨浏览器支持,而且展开/折叠太卡了。

示例 1:Chrome 对两端对齐的 flexbox 的展开/折叠行为

$('button').click(function() 
  $(this).next().slideToggle();
)
body 
  margin: 30px;
  font-family: sans-serif;

aside,
aside div,
summary,
main,
button,
details p,
button + p 
  background: rgba(0,0,0,.09);
  border: none;
  padding: 20px;
  margin: 0;


.flexcontainer 
  display: flex;

aside 
  flex: 1;
  position: relative;
  max-width: 25%;
  background: mintcream;

  display: flex;
  flex-direction: column;
  position: relative;

aside.space-between 
  justify-content: space-between;

aside.center 
  justify-content: center;


main 
  flex: 3;
  position: relative;
  max-width: 75%;
  background: aliceblue;
  vertical-align: top;
  height: 100%;

main > * + * 
  margin-top: 20px;


button + p 
  display: none;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<section class="flexcontainer">
  <aside class="space-between">
    <div>Top Sidebar</div>
    <div>Bottom Sidebar</div>
  </aside>
  <main>
    <div>
      <button>slideToggle</button>
      <p>Other browsers: always expands downward.<br>
        Chrome: Should always expand downward because Top Sidebar is always visible.</p>
    </div>

    <div>
      <button>slideToggle (usually expands down)</button>
      <p>Other browsers: always expands downward.<br>
        Chrome: Should expand downward while Bottom Sidebar and Top Sidebar are both visible. But will expand upward if you scroll down far enough so that Top Sidebar is off-screen.</p>
    </div>
    
    <div>
      <button>slideToggle (usually expands down)</button>
      <p>Other browsers: always expands downward.<br>
        Chrome: Should expand downward while Bottom Sidebar and Top Sidebar are both visible. But will expand upward if you scroll down far enough so that Top Sidebar is off-screen.</p>
    </div>
  </main>
</section>

示例 2:Chrome 的中心对齐 flexbox 的展开/折叠行为

$('button').click(function() 
  $(this).next().slideToggle();
)
body 
  margin: 30px;
  font-family: sans-serif;

aside,
aside div,
summary,
main,
button,
details p,
button + p 
  background: rgba(0,0,0,.09);
  border: none;
  padding: 20px;
  margin: 0;


.flexcontainer 
  display: flex;

aside 
  flex: 1;
  position: relative;
  max-width: 25%;
  background: mintcream;

  display: flex;
  flex-direction: column;
  position: relative;

aside.space-between 
  justify-content: space-between;

aside.center 
  justify-content: center;


main 
  flex: 3;
  position: relative;
  max-width: 75%;
  background: aliceblue;
  vertical-align: top;
  height: 100%;

main > * + * 
  margin-top: 20px;


button + p 
  display: none;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<section class="flexcontainer">
  <aside class="center">
    <div>Center Sidebar</div>
  </aside>
  <main>

    <div>
      <button>slideToggle (usually expands downwards)</button>
      <p>Other browsers: always expands downward.<br>
        Chrome: Usually expands downwards. Expands in both directions when the top-edge of the container scrolls out of the viewport.</p>
    </div>

    <div>
      <button>slideToggle</button>
      <p>Other browsers: always expands downward.<br>
        Chrome: Usually expands downwards. Expands in both directions when the top-edge of the container scrolls out of the viewport.</p>
    </div>

    <div>
      <button>slideToggle (usually expands downwards)</button>
      <p>Other browsers: always expands downward.<br>
        Chrome: Usually expands downwards. Expands in both directions when the top-edge of the container scrolls out of the viewport, but then resumes expanding downwards again when Center Sidebar scrolls out of view.</p>
    </div>
  </main>
</section>

【问题讨论】:

听起来像是最近实现的scroll anchoring 功能。如您所见,可以通过容器或文档正文上的overflow-anchor: none 选择退出。 @wOxxOm ++ 你完全正确。将overflow-anchor: none 添加到.flexcontainer 可以解决此问题。如果您将其转换为答案,我将奖励您积分。你也是通过 chromium tracker 上的 bug 来到这里的吗? 不,这么简单的事情不需要积分,是的,我确实来自错误跟踪器。 我明白并感谢它,但这是正确的答案,因此需要将其作为答案归档,以便将问题标记为已回答和接受。 ;) 如果不感兴趣,我可以做,我会等一下。 【参考方案1】:

将此代码添加到您的弹性容器中:

overflow-anchor: none

这将禁用 Chrome 中称为“滚动锚定”的功能,该功能会导致框向上扩展 (revised codepen)。


在 Chrome 中,展开框的向上/向下方向由视口中的滚动位置决定,而不是布局本身。

Chrome 对这种行为采取了一种独特的方法来改善用户体验。

基本上,它们将 DOM 元素绑定到当前滚动位置。屏幕上这个特定(“锚”)元素的移动将决定对滚动位置的调整(如果有的话)。

他们将这种方法称为“滚动锚定”。该算法在此页面上进行了说明: https://github.com/WICG/ScrollAnchoring/blob/master/explainer.md

这种行为目前是 Chrome 独有的,但 Google is pushing for standardization.

根据滚动锚定文档,将overflow-anchor: none 应用于适当的元素将禁用滚动锚定调整。

更多信息:

https://github.com/WICG/ScrollAnchoring/blob/master/explainer.md https://bugs.chromium.org/p/chromium/issues/detail?id=739860 https://hacks.mozilla.org/2019/03/scroll-anchoring-in-firefox-66/ Changing CSS flex order causes scrolling

【讨论】:

这似乎也会影响不是display: flex 的容器。任何线索何时开始在 Chrome 中发生?据说他们支持该功能有一段时间了,但最近才注意到它。

以上是关于使用 flexbox 的 Google Chrome 视口锚定扩展方向的主要内容,如果未能解决你的问题,请参考以下文章

Google发布flexbox-layout 能替代FlowLayout吗

CSS3 Flexbox:显示:box vs. flexbox vs. flex

CSS3 Flexbox:显示:box vs. flexbox vs. flex

CSS3 Flexbox:显示:box vs. flexbox vs. flex

Ubuntu下安装Google浏览器

chrom浏览器设置不了小于12px的文字大小的解决方法