CSS 位置 当缩放应用于父级、粘性滚动和元素的不同速度时粘性奇怪的行为

ste*_*165 6 css positioning sticky

我不敢相信以前没有人注意到这一点,但我似乎找不到任何人注意到这种行为。首先我应该说这个 html 是很久以前写的(不是我写的),目前还不能真正修改。

所以问题是这样的:

我们的 html 结构布局如下

.rptDisplay {
  overflow: auto;
  position: relative;
  top: 0;
  left: 0;
  z-index: 0;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 200px;
  max-height: 100vh;
  font-size: 11px;
  text-align: left;
}

.rptPositioner {
  width: 33%;
  display: block;
  transform-origin: 0px 0px;
  transform: scale(3, 3);
}

.rptHeader {
  position: sticky !important;
  top: 0 !important;
  z-index: 1;
  background: #eee;
}

body {
  margin: 0;
  padding: 0;
}
Run Code Online (Sandbox Code Playgroud)
<div class="rptDisplay">
  <div class="rptPositioner">
    <div class="rptHeader">Header</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

问题是有一些非常奇怪的行为,当我滚动标题时,页面向下滚动的速度与页面本身向下滚动的速度不同。请记住,用户可以更改变换比例以进行缩放,最近添加了粘性位置。

我跟踪问题到缩放未应用于 rptDisplay,而是应用于显示的子项,但应用于粘性元素的父项。如果我将缩放应用于显示或标题,问题就会消失,但目前这不是一个选项。

我附上了一个 CodePen,它演示了我们所看到的问题。

https://codepen.io/steves165/pen/QWOLMwr

onk*_*kar 3

一种解决方案是top根据当前的变换比例值自行设置。

您提到过,“用户可以更改变换比例以进行缩放。” 这意味着正在使用 javascript。所以我们可以添加以下小代码来自top行设置:

let scale = zoom.value;
let disp = document.querySelector('.rptDisplay');
let psnr = document.querySelector('.rptPositioner');
let header = document.querySelector('.rptHeader');

disp.addEventListener('scroll', setTop);

function setTop() {
  let offset = disp.scrollTop - (disp.scrollTop / scale);
  header.style.top = `${-offset}px`;
}

// for the demo set custom zoom
function adjust(r) {
  scale = r.value;
  psnr.style.transform = `scale(${scale},${scale})`;
  setTop()
}
Run Code Online (Sandbox Code Playgroud)
.rptDisplay {
  overflow: auto;
  position: relative;
  top: 0;
  left: 0;
  z-index: 0;
  margin: 0;
  padding: 0;
  width: 100%;
  height: 155px;
  max-height: 100vh;
  font-size: 11px;
  text-align: left;
}

.rptPositioner {
  width: 33%;
  display: block;
  transform-origin: 0px 0px;
  transform: scale(3, 3);
}

.rptHeader {
  position: sticky !important;
  /* top: 0 !important;*/
  z-index: 1;
  background: rgb(215, 253, 199);
}

body {
  margin: 0;
  padding: 0;
}
Run Code Online (Sandbox Code Playgroud)
<label>Set Zoom(1-4):
    <input type="range" id="zoom" min="1" max="4" value="3" onchange="adjust(this)">
  </label><br>
<hr>
<div class="rptDisplay">
  <div class="rptPositioner">
    <div class="rptHeader">Header</div>
    <div class="row">Row first</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row</div>
    <div class="row">Row Last</div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • 这个例子非常简单且通用,但它有一个副作用。由于不断重新定位,滚动时会出现滞后抖动效应。这在滚动快速且平滑的移动设备上尤其明显。不幸的是,只有在滚动时避免重新计算才能避免这个问题,就像[在本例中](/sf/answers/4965418251/)所做的那样。 (3认同)