我的立场:使用 flexbox 时粘性元素不粘性

Posted

技术标签:

【中文标题】我的立场:使用 flexbox 时粘性元素不粘性【英文标题】:My position: sticky element isn't sticky when using flexbox 【发布时间】:2017-11-10 19:33:50 【问题描述】:

我被这个问题困住了一段时间,并认为我会分享这个position: sticky + flexbox gotcha:

在我将视图切换到弹性盒容器之前,我的粘性 div 工作正常,但当它被包裹在弹性盒父级中时,它突然变得不粘性了。

.flexbox-wrapper 
  display: flex;
  height: 600px;

.regular 
  background-color: blue;

.sticky 
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  background-color: red;
<div class="flexbox-wrapper">
  <div class="regular">
    This is the regular box
  </div>
  <div class="sticky">
    This is the sticky box
  </div>
</div>

JSFiddle showing the problem

【问题讨论】:

这种行为是否会在所有支持 position: sticky 的浏览器中持续存在,或者仅支持一个/一些? @TylerH 我相信都是浏览器。它在 Chrome 和 Safari 中都是这样运行的。 谢谢。我可以确认问题和解决方案也出现在 Firefox 中。 【参考方案1】:

如果您在父元素中使用 flex,请使用 align-self: flex-start 作为您想要粘性的元素。

position: sticky;
align-self: flex-start;
top: 0;
overflow-y: auto;

【讨论】:

【参考方案2】:

根据我的经验的全球解决方案/规则:

不要将带有粘性元素的结构直接放在 display : flex 容器中。

相反(对于 flex 布局)将带有粘性元素的表格/div 放入 flex 子容器(例如,使用 flex: 1 1 auto ,但 没有 display : flex ),那么一切都应该按预期工作。

【讨论】:

你能举个例子吗?【参考方案3】:

对于我的情况,align-self: flex-start(或justify-self: flex-start)解决方案不起作用。我还需要保留overflow-x: hidden,因为有些容器会水平滑动。

我的解决方案需要嵌套 display: flexoverflow-y: auto 以获得所需的行为:

header可以动态调整高度,防止玩position: absoluteposition: fixed 内容垂直滚动,水平限制在视图宽度内 sticky 元素可以垂直放置在任何地方,粘在页眉的底部 其他元素可以水平滑动 看起来 SO sn-p 工具无法在子元素上渲染 width 以正确演示水平幻灯片,或者我的实际布局中可能还有其他设置可以使其正常工作... 请注意,为了让overflow-x: auto 在具有overflow-x: hidden 的父元素下的元素中正常工作,需要一个不执行任何其他操作的包装元素

body 
  height: 100vh;
  width: 100vw;
  display: flex;
  flex-direction: column;


body>header 
  background-color: red;
  color: white;
  padding: 1em;


.content 
  overflow-x: hidden;
  overflow-y: auto;
  display: flex;
  flex-direction: column;


article 
  position: relative;
  display: flex;
  flex-direction: column;
  overflow-y: auto;


.horizontal_slide 
  display: flex;
  overflow-x: auto;
  background-color: lightblue;
  padding: .5em;


.horizontal_slide>* 
  width: 1000px;


.toolbar 
  position: sticky;
  top: 0;
  z-index: 10;
  background-color: lightgray;
  padding: .5em;
  display: flex;
<header>Fancy header with height adjusting to variable content</header>
<div class="content">
  <article class="card">
    <h1>One of several cards that flips visibility</h1>
    <div class="overflow_x_wrapper">
      <div class="horizontal_slide">
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
        <div>Reason why `overflow-x: hidden` on the parent is required
        </div>
      </div>
      <div class="toolbar">Sticky toolbar part-way down the content</div>
      <p>Rest of vertically scrollable container with variable number of child containers and other elements</p>
      <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
        dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
  </article>
  </div>

【讨论】:

【参考方案4】:

我做了一个临时的 flexbox 表并遇到了这个问题。为了解决这个问题,我简单地将粘性标题行放在 flexbox 之外,就在它之前。

【讨论】:

【参考方案5】:

就我而言,其中一个父容器应用了overflow-x: hidden;,这将破坏position: sticky 的功能。您需要删除该规则。

任何父元素都不应应用上述 CSS 规则。此条件适用于直到(但不包括)“body”元素的所有父级。

【讨论】:

你也不能在 html 元素上使用overflow-x:hidden 非常感谢。我总是与位置粘滞作斗争,直到阅读您的回复,我才知道这种情况。 :) @SamuelLiew,是的,您可以在 HTML 元素上使用 overflow-x: hidden; @RaphaelAleixo 我很高兴能帮上忙 :) 天啊,这成功了!就我而言,隐藏的溢出来自粘性列向上三层的父级。我使用了 Bulma 的“部分”布局助手,它显然已经应用了溢出:隐藏。虽然,从我的情况来看,overflow-x 和overflow-y 都不应该被隐藏,而不仅仅是overflow-x。【参考方案6】:

由于弹性盒元素默认为stretch,所有元素的高度相同,不能滚动。

align-self: flex-start 添加到粘性元素将高度设置为自动,允许滚动,并修复它。

目前在所有主流浏览器中都是supported,但Safari 仍然在-webkit- 前缀后面,除Firefox 之外的其他浏览器在position: sticky 表方面存在一些问题。

.flexbox-wrapper 
  display: flex;
  overflow: auto;
  height: 200px;          /* Not necessary -- for example only */

.regular 
  background-color: blue; /* Not necessary -- for example only */
  height: 600px;          /* Not necessary -- for example only */

.sticky 
  position: -webkit-sticky; /* for Safari */
  position: sticky;
  top: 0;
  align-self: flex-start; /* <-- this is the fix */
  background-color: red;  /* Not necessary -- for example only */
<div class="flexbox-wrapper">
  <div class="regular">
    This is the regular box
  </div>
  <div class="sticky">
    This is the sticky box
  </div>
</div>

JSFiddle showing the solution

【讨论】:

这只在包含的 flex 元素中滚动时才有效——滚动整个窗口时它不会粘住(至少在 Firefox 中)——所以对于那些遇到矛盾行为的人来说,你更有可能'正在经历相互矛盾的期望(就像我一样) @aequalsb 你知道滚动整个页面时让它粘住的方法吗? @Douglas 这个问题具有误导性,因为它表明问题在于flexbox,但问题更多地与包含sticky 元素有关。看看这个小提琴:jsfiddle.net/9y87zL5c 第二个红色盒子按预期工作,但第一个红色盒子没有粘住——所以......这与 flexbox 无关(因此是矛盾的期望)......另外......我添加了一个一堆 jabberwocky 以更准确的方式查看结果。 我在 Firefox 87 中使用它没有问题。工作正常。【参考方案7】:

您也可以尝试将子 div 添加到包含内容的 flex 项目中,并将 position: sticky; top: 0; 分配给它。

这对我来说适用于两列布局,其中第一列的内容需要保持粘性,而第二列显示为可滚动。

【讨论】:

完全同意,这是我能找到的最简单、最可靠的选择。这样,您还可以通过控制容器的高度来控制何时停止粘贴。

以上是关于我的立场:使用 flexbox 时粘性元素不粘性的主要内容,如果未能解决你的问题,请参考以下文章

使用带有引导程序的 flexbox 粘性页脚

修复了 flexbox 项内的元素

css 使用Flexbox添加粘性页脚

使用粘性导航栏自动滚动 Flexbox 列

css 粘性页脚与flexbox和网格

css 粘性页脚片段(来源:treehouse flexbox课程)