我在Chrome和Safari中有一些奇怪的行为。我有一个缩放的(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)
,行为是一样的。如果我:
,则问题不存在position: absolute;
移至.on-top
(即.below
)overflow: hidden;
.content
.on-top
,那么它会放在文档流程中的视频标记之后(但当然,由于项目的具体原因,这些变通方法在现实中都不适合我。我也不能给视频元素一个负z-index而我需要来使用{{1} }。)
来自社区的建议解决方法(谢谢!)
overflow: hidden;
(我无法移除overflow: hidden;
)浏览器
我在Chrome(Mac)和Safari(Mac)中看到了这个问题。
更新1
似乎this bug report似乎涵盖了我的问题。但是,它没有为它提供修复。
更新2
我通过提供解决此问题的方法回答了我自己的问题。
更新3
有很多答案可以修改视频的overflow: hidden;
或将z-index
添加到translateZ
元素。演示已经表明这两种方法都可以解决这个问题。
但是,由于我的HTML结构是可视化HTML编辑器的输出(长篇故事......),我不知道它们将是什么元素,或者它们应该位于视频的前面,下面还是旁边。因此,我正在寻找一种解决方案,不需要更改缩放元素内的单个元素。
答案 0 :(得分:8)
它看起来像是Chrome中的一个错误。请注意,缩放图像时,元素检查器会一直告诉您#scaled
的大小为1024x768:
在Firefox中的位置:
现在,显然,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)
不幸的是我找不到一个优雅的解决方案。理想情况下,您应该修改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);
.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);
}
<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>
答案 1 :(得分:4)
答案 2 :(得分:3)
花了很多时间研究这个问题并尝试了很多不同的方法后,我得出结论,没有解决方案可以解决我的问题。如果你能够控制消失的元素的z索引,有一些解决方案可以解决这个问题,但我不能这样做,因为HTML的结构是未知的(它是HTML编辑器的输出) )。我一直在寻找一个解决方案,不需要将个别孩子改为比例父母,但到目前为止我还没有找到。
This bug report几乎涵盖了我的问题,但它没有为它提供修复。
我可以确认这是因为元素超出了缩放容器的原始宽度和高度:
该元素在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);
#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);
}
<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>
答案 3 :(得分:2)
一种方法,如果你可以修改你的html,将有问题的元素包装在一个与视频和容器大小相同的容器中,并使用正确的z-index。这样,您就可以拥有相同大小和位置的清晰图层,您可以在其中放置更复杂的元素。像这样举例如:
<div id="top-container">
<div class="on-top">
<h1>
I should always be on top.<br /> I have z-index 5
</h1>
</div>
</div>
#top-container {
width: 100%;
height: 100%;
position: absolute;
z-index: 5;
}
答案 4 :(得分:1)
我将z-index:-1;
放在video
上,从而解决了这个问题。
答案 5 :(得分:1)
我非常喜欢Salman A的答案。
唯一想到的就是用position: relative
重写。
但我不知道这是否是一种选择。
答案 6 :(得分:0)
我偶然发现了与绝对元素和变换相关的类似内容......
我不知道如果这会帮助你,但这里有一个链接。
CSS transform: translate moves postion:fixed inner Div
最后我通过使用转换来修复它:translateX(none)vs translateX(0)。
确实存在超级奇怪的行为,但该链接提供了一些更多链接,以帮助使事情更加清晰 - 就像每个规范的行为一样。
答案 7 :(得分:0)
答案 8 :(得分:0)
可能已经晚了,但是只是发布以防有人觉得有用。 在带有转换动画的父容器元素下添加一个空的div,并且什么也不会消失。该动画不执行任何操作,但会强制浏览器使用硬件加速来渲染所有元素。
<div class="emptydiv"></div>
.emptydiv{
transform:scale(1);
animation:fix 3s infinite;
}
@keyframes fix{
50%{
transform:scale(1);
}
}