缩放元素中的视频和z-index:一些div消失

iaf*_*wik 18 javascript css google-chrome z-index scaletransform

我在Chrome和Safari中有一些奇怪的行为.我有一个scaled(transform: scale())容器,里面有视频和其他元素.在一些缩放中,具有高z指数的绝对定位元素消失并且不再返回.

我怎样才能解决这个问题?请注意,我不能给视频元素一个负z-index,我需要使用overflow: hidden;.

我做了一个例子,可以向上和向下扩展最外面的容器.在特定比例值处,具有类.on-top(和文本"I should always be on top.")的元素消失.当再次缩小时,它会突然出现.

链接到exmaple:https://jsfiddle.net/iafiawik/Lcox1ecc/

在此输入图像描述

结论

  • 看起来元素的大小很重要.我做得越大,它消失之前的比例值就越大.
  • 我还测试了transform: scale(1.4)直接在元素上设置CSS,行为是一样的.

如果我这个问题不存在:

  • 用div替换视频标签
  • position: absolute;从兄弟姐妹中删除.on-top(即.below)
  • overflow: hidden;从中移除.content
  • 如果我移动.on-top,则将其放在文档流程中的视频标记之后

(但是当然,由于项目的具体原因,这些变通办法在现实中都不适用于我.我也不能给视频元素一个负面的z-index,我需要使用overflow: hidden;.)

来自社区的建议解决方法(谢谢!)

  • 为视频标记提供负z-index(不能这样做,因为我有时会在视频后面放置元素)
  • 删除overflow: hidden;(我无法删除overflow: hidden;)

浏览器

我在Chrome(Mac)和Safari(Mac)中看到了这个问题.


更新1

似乎这个错误报告几乎涵盖了我的问题.但是,它没有为它提供修复.

更新2

我通过提供解决这个问题的方法回答了我自己的问题.

更新3

有许多答案可以修改z-index视频添加translateZ.on-top元素.演示已经表明这两种方法都可以解决这个问题.但是,由于我的HTML结构是可视化HTML编辑器的输出(长篇故事......),我不知道它们将是什么元素,或者它们应该位于视频的前面,下面还是旁边.因此,我正在寻找一种解决方案,不需要更改缩放元素内的单个元素.

Sal*_*n A 8

它看起来像Chrome中的一个错误.请注意,缩放图像时,元素检查器会一直告诉您大小#scaled为1024x768:

Chrome Scale

在Firefox中的位置:

Firefox Scale

现在,显然,Chrome使用错误的大小来得出结论.on-top完全在外面.content并且由于隐藏溢出而隐藏它(它不应该这样做但显然它试图优化掉在视频上方显示的任何元素).例子:

Scale: 1.225
Parent width: 1254.40
Child left: 1254.40 - (100 + 90) * 1.225 = 1021.65
Result: less than 1024 (partially inside)

Scale: 1.230
Parent width: 1259.52
Child left: 1259.52 - (100 + 90) * 1.230 = 1025.82
Result: greater than 1024 (completely outside)
Run Code Online (Sandbox Code Playgroud)

不幸的是我找不到一个优雅的解决方案.理想情况下,您应该修改HTML标记和CSS,或者将顶部元素与左边缘对齐.作为最后的手段,您可以使用透明边框将元素向左移动:

var goalScale = 140;
var startScale = 100;
var currentScale = 100;
var shouldScaleUp = true;
var container = document.getElementById("scaled");
var scaleInfo = document.getElementById("scale-info");

function step() {
  container.style.transform = "scale(" + (currentScale / 100) + ")";
  scaleInfo.innerText = "Scale: " + (currentScale / 100);
  if (currentScale === goalScale) {
    shouldScaleUp = false;
  }
  if (currentScale === startScale) {
    shouldScaleUp = true;
  }
  if (shouldScaleUp) {
    currentScale += 0.5;
  } else {
    currentScale -= 0.5;
  }
  window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);
Run Code Online (Sandbox Code Playgroud)
.scale-info {
  position: fixed;
  left: 0;
  top: 0;
}

#scaled {
  background: #cccccc;
  width: 1024px;
  height: 768px;
  position: fixed;
  left: 200px;
  top: 200px;
}

.content {
  height: 100%;
  overflow: hidden;
  position: relative;
  margin-left: auto;
  margin-right: auto;
  background: rgba(34, 34, 56, 0.2);
}

.below {
  position: absolute;
  width: 300px;
  height: 300px;
  right: 0px;
  top: 100px;
  background: purple;
  z-index: 1;
  opacity: 0.8;
}

.below-2 {
  z-index: 3;
  right: 100px;
}

.below-3 {
  z-index: 4;
  right: 400px;
}

.on-top {
  position: absolute;
  width: 50px;
  right: 100px;
  top: 150px;
  background: pink;
  z-index: 5;
  padding: 20px;
  /* a 200px border moves the element towards left */
  border-left: 200px solid transparent;
  background-clip: padding-box;
}

.on-top h1 {
  font-size: 20px;
}

#video {
  position: absolute;
  z-index: 4;
  width: 1024px;
  height: 768px;
  background: rgba(0, 0, 0, 0.4);
}
Run Code Online (Sandbox Code Playgroud)
<div id="scale-info"></div>

<div id="scaled">
  <div class="content">
    <h2 class="below below-1"> I have z-index 1</h2>
    <div class="on-top">
      <h1> I should always be on top.<br> I have z-index 5</h1>
    </div>
    <h2 class="below below-2"> I have z-index 3</h2> <video id="video" src="https://www.w3schools.com/html/mov_bbb.mp4"></video>
    <h2 class="below below-3"> I have z-index 4</h2>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)

  • @iafiawik看到修改后的答案. (2认同)

jmc*_*riz 5

在这里您可以前往:https : //jsfiddle.net/Lcox1ecc/423/

您只需要添加-webkit-transform: translateZ(0);.on-top类中即可。

编码愉快!


iaf*_*wik 4

在花了很多时间研究这个问题并尝试了很多不同的方法之后,我得出的结论是没有解决方案可以解决我的问题。如果您能够控制消失元素的 z 索引,则有一些解决方案可以解决该问题,但我无法这样做,因为 HTML 的结构未知(它是 HTML 编辑器的输出) )。我一直在寻找一种不需要将单个子项更改为缩放父项的解决方案,但到目前为止我还没有找到任何解决方案。

该错误报告几乎涵盖了我的问题,但没有提供解决方案。

我可以确认发生这种情况是因为该元素位于缩放容器的原始宽度和高度之外:

该元素在以下位置可见scale(1.227)(红色边框表示 的原始大小#scaled):

在此输入图像描述

...但不是在scale(1.228)

在此输入图像描述

因此,我的解决方案是在未缩放的缩放元素外部添加另一个包装元素,但根据其第一个子缩放值更新其width和属性。height该元素具有overflow: hidden;并防止元素可见。

在此输入图像描述

这不是一个完美的解决方案,因为人们可能会遇到缩放元素和最外层包裹元素之间的小间隙(舍入问题),但这是我在这种情况下能做的最好的解决方案。

var goalScale = 140;
var startScale = 100;
var currentScale = 100;
var shouldScaleUp = true;
var container = document.getElementById("scaled");
var scaledContainer = document.getElementById("resized-container");
var scaleInfo = document.getElementById("scale-info");

function step() {
  var contentWidth = 1024;
  var contentHeight = 768;
  container.style.transform = "scale(" + (currentScale / 100) + ")";

  scaledContainer.style.width = contentWidth * ((currentScale / 100)) + "px";
  scaledContainer.style.height = contentHeight * ((currentScale / 100)) + "px";

  scaleInfo.innerText = "Scale: " + (currentScale / 100);

  if (currentScale === goalScale) {
    shouldScaleUp = false;
  }
  if (currentScale === startScale) {
    shouldScaleUp = true;
  }

  if (shouldScaleUp) {
    currentScale += 0.5;
  } else {
    currentScale -= 0.5;
  }

  window.requestAnimationFrame(step);
}

window.requestAnimationFrame(step);
Run Code Online (Sandbox Code Playgroud)
#resized-container {
  position: fixed;
  width: 1024px;
  height: 768px;
  overflow: hidden;
  border: 10px solid red;
  top: 200px;
  left: 200px;
}

#scaled {
  background: #cccccc;
  width: 1024px;
  height: 768px;
  position: absolute;
  transform-origin: left top;
}

.content {
  height: 100%;
  position: relative;
  margin-left: auto;
  margin-right: auto;
  background: rgba(34, 34, 56, 0.2);
}

.below {
  position: absolute;
  width: 300px;
  height: 300px;
  right: 0px;
  top: 100px;
  background: purple;
  z-index: 1;
  opacity: 0.8;
}

.below-2 {
  z-index: 3;
  right: 100px;
}

.below-3 {
  z-index: 4;
  right: 400px;
}

.on-top {
  position: absolute;
  width: 50px;
  right: -30px;
  top: 150px;
  background: pink;
  z-index: 5;
  padding: 20px;
}

.on-top h1 {
  font-size: 20px;
}

#video {
  position: absolute;
  z-index: 4;
  width: 1024px;
  height: 768px;
  background: rgba(0, 0, 0, 0.4);
}
Run Code Online (Sandbox Code Playgroud)
<div id="resized-container">
  <div id="scaled">
    <div id="scale-info">

    </div>
    <div class="content">
      <h2 class="below below-1">
        I have z-index 1
      </h2>

      <div class="on-top">
        <h1>
          I should always be on top.<br /> I have z-index 5
        </h1>
      </div>

      <h2 class="below below-2">
        I have z-index 3
      </h2>
      <video id="video" src="https://www.w3schools.com/html/mov_bbb.mp4"></video>
      <h2 class="below below-3">
        I have z-index 4
      </h2>
    </div>
  </div>
</div>
Run Code Online (Sandbox Code Playgroud)