【问题标题】:Scrollbar is disappearing/reappearing when element changes opacity in Chrome当元素在 Chrome 中更改不透明度时,滚动条消失/重新出现
【发布时间】:2021-10-13 17:46:17
【问题描述】:

我有一个名为img-with-overlaydiv,其中包含一个静态定位的图像和一个绝对定位的叠加层。当img-with-overlay 悬停在上面时,覆盖从0 不透明度变为1。一个意想不到的副作用是,在基于 Chrome 和 Chromium 的浏览器中,当覆盖层不透明时,垂直滚动条会消失。它不会出现在 Firefox 中。

你问为什么会有滚动条?你可以看到有一个container 有一个非常具体的widthheight。即使这些尺寸改变了半个像素,也不会发生意外的副作用。我正在使用这个容器来代表我网页的body,尽管我为了适应 sn-p 的目的而将它缩小了。虽然大多数屏幕尺寸不会出现问题,但我仍然想防止它过度发生。

$(document).ready(function () {
  $('.img-with-overlay').hover(function () {
    $('.overlay').css('opacity',1);
  }, function () {
    $('.overlay').css('opacity',0);
  })
});
.container {
  width: 600px;
  height: 248.5px;
  overflow: auto;
  overflow-x: hidden;
}

.img-with-overlay {
  position: relative;
  overflow: hidden;
  width: 100%;
}

img {
  display: block;
  width: 100%;
}

.overlay {
  position: absolute;
  top: 0;
  opacity: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="container">
  <div class="img-with-overlay">
    <img src="https://via.placeholder.com/468x200?text=Hover">
    <div class="overlay">This is an overlay</div>
  </div>
</div>

为什么当叠加层的不透明度发生变化时,滚动条会消失/重新出现?

我注意到的一些有趣的事情:

  • 如果将img 替换为相同尺寸的div,则不会出现滚动条。
  • 如果将叠加层不透明度设置为小于 1 的值,例如 0.7,则滚动条不会在悬停时消失。

【问题讨论】:

    标签: jquery google-chrome scrollbar chromium opacity


    【解决方案1】:

    发生的事情很简单,但并不那么明显。

    背景

    当您设置图像width: 100% 时,会自动计算图像高度以保持原始比例。容器比图像高一点,因为它有overflow-y: auto,所以会出现垂直滚动。但是现在神奇的事情发生了:垂直滚动条减小了容器的内部宽度,因此图像宽度相应地减小,并且它的高度这样做是为了保持比例。但是现在图像比容器高一点,所以不再需要垂直滚动条。但如果滚动条消失,图像会再次展开,开始无限循环,一切都在闪烁。为了防止这种竞争情况,浏览器选择始终显示滚动条,但由于图像适合容器,因此无需向下滚动,因此滚动条被禁用。

    这解释了为什么稍微改变尺寸可以解决问题:如果你让容器有点窄或高一点,图像总是适合而不需要滚动条;如果你让容器更宽或更短,图像永远不会适合并且总是显示滚动条。

    不透明度问题

    现在考虑以下内容。您的图像同时具有display: blockwidth: 100%。这两个属性影响相同的属性(宽度),但在布局工作流程中以不同的方式和不同的时间影响。这足以启动一个竞争条件,该行为未定义,浏览器尝试以自己的方式解决它。您可以通过打开检查器并切换 img 的 display 属性来验证它:一开始您有一个禁用的滚动条,然后当您关闭该属性时,滚动条将启用,然后当您完全启用该属性时滚动条消失。什么?!我们又回到了初始状态,结果却不一样了?! :我的天啊: 大多数情况下,这种竞争条件没有任何影响,但在这种情况下,由于上一节中描述的内容,它变得很清楚。

    现在让我们谈谈不透明度。不透明度小于 1 的元素必须按特定顺序(从后到前)渲染,并且在渲染后不透明元素之后。虽然我不知道这在 Chrome 与 Firefox 中是如何实现的,但这种行为表明在 Chrome 中,渲染顺序会以某种方式影响布局工作流程。这解释了为什么 opacity=1 的行为不同于 opacity=0.999。但这只是因为有一个条件没有定义的行为,如前所述。

    因此解决方案非常简单:删除导致未定义行为的条件。由于display: block 不会影响图像大小,而只会影响元素占用的空间,所以要做的事情很明显:删除display: block,在img 元素上只保留width: 100%.

    如果出于某种原因您不想删除display: block,您可以通过在容器上编码overflow-y: scroll 来强制滚动条始终可见(同时删除溢出属性)。这样您就不会删除导致未定义行为的条件,但会删除滚动条上的竞争条件。

    【讨论】:

      猜你喜欢
      • 2015-02-22
      • 1970-01-01
      • 1970-01-01
      • 2012-09-07
      • 2021-08-26
      • 2019-01-17
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      相关资源
      最近更新 更多