在iframe中使用CSS vh单位

40

我试图在 iframe 中使用 CSS 的 vh 单位。但是我发现它们会以某种方式按比例缩放到 iframe 的大小。换句话说,100vh 并不等于窗口高度,而是设置为 iframe 的高度。

这是否正确?

是否有解决方法?


1
请使用JavaScript。查看window.innerWidthwindow.innerHeight - www139
你能为我们制作一个 JSFiddle 吗? - www139
这是同一个域。看起来我需要使用JS或将“vh”分数设置为总iframe高度。现在无法创建fiddle。@www139 - Union find
@codeinveritas,我的回答有帮到你吗?我能做得更好吗? - www139
2
顺便说一句:一开始我根本无法使用vw、vh。后来发现我复制了一个旧的iframe示例,其中设置了iframe标签的“width”和“height”属性。例如:<iframe ... width: "320" height: "200" .../>。删除它们 - 在那里vw和vh不起作用 - 并使用CSS样式。例如,如果要使用内联CSS:<iframe ... style="width: 100%; height: 80vh" .../>。 - ToolmakerSteve
显示剩余5条评论
2个回答

50

我知道这是一个老问题,但随着人们向vh单位转移,这个问题将变得更加普遍。

为了澄清问题,这里有一个示例。我们有一个加载iframe的HTML文件:

<!DOCTYPE html>
<html>
<head></head>
<style>
iframe {
    height: 50vh;
    width: 100%;
}
</style>
<body>
    <iframe src="iframe.html"/>
</body>
</html>

以及它的iframe

<!DOCTYPE html>
<html>
<head></head>
<style>
div {
    height: 50vh;
    width: 100%;
    background: blue;
}
</style>
<body>
    <div></div>
</body>
</html>

需要注意的是,这里的iframeiframediv元素都被指定为具有50vh的高度。预期的行为可能是iframe遵守父级上下文视口的高度或宽度。但是,结果看起来像这样:

进入图片描述

也就是说,蓝色元素的高度约为浏览器窗口的25%,而不是预期的50%(即iframe的100%)。虽然我们希望iframe遵守其父级视口,但这个例子很好地说明了这可能是多么不直观,尽管这对于使用v*单位来嵌入iframe的内容肯定会使其更有价值。该问题与如何确定视口高度有关。

规范中可以得知:

视口百分比长度相对于初始包含块的大小。当初始包含块的高度或宽度改变时,它们会相应地缩放。

iframe和浏览器窗口均可成为初始包含块时,二者都是有效的视口。视口不仅限于浏览器窗口,而是定义为用户通过屏幕查看文档的窗口或其他查看区域

当嵌入到文档中时,iframe会创建一个嵌套浏览上下文,因此是其自己的视口。

所以,这是预期的行为-不幸的是,没有纯CSS解决方法-但是,www139提供了一个使用JavaScript可以实现这一点的示例。使用v*单位控制许多元素大小的问题也从这里开始。


3
我希望Safari浏览器能保持与iframe相同的行为,但Safari倾向于使用vh作为主要浏览器视口而不是iframe的高度 :( 所以我和你恰恰相反,遇到了完全相反的问题 :( - Simon_Weaver
@Simon_Weaver 我在 Safari 11.1 中得到了我上面描述的相同结果。我无法想象这个工作方式会有很大的差异,因为它是规范的一部分。你确定你使用的是相同的机制吗?你在浏览器中尝试过上面的最小完整示例吗? - Jamie Counsell
Safari对于iframe非常挑剔。将元素设置为100vh的高度时,它们显示为内容的完整高度,而不是视口高度。固定位置元素会完全破坏滚动。此外,我认为同域iframe的行为也略有不同。因此,这些事情可能会产生影响。我试图创建一个iframe,在iPad上托管我的网站,以模拟不同的屏幕尺寸。但我放弃了,因为iOS似乎不想让你这样做。最后,我找到了一个名为“Inspect”的应用程序,可以在iOS上本地执行此操作,甚至还提供了控制台。 - Simon_Weaver
在你的测试中,你能滚动窗口吗?显然,为了测试一个网站,我需要滚动 - 这可能是区别。当我运行testiphone.com时,我能够看到我想要的“正确”行为(100vh填充视口),但我无法滚动它。我希望iframe像完全独立的浏览器一样运作,但显然这是不可能的。幸运的是,我找到的iPad应用程序工作得非常好。 - Simon_Weaver

9
这是个很好的问题。可悲的是,我没有找到CSS解决方案,但我已经找到了用JavaScript的解决方案,我认为这是目前最好的选择。请记住,框架必须在同一个域中才能工作。
希望这能帮到您。如果需要改进此答案,请在下面评论 :-)
理论解决方案(因为框架来源问题无法在SO上使用):
window.addEventListener('load',function(){
    initializeV();
    function initializeV(){
            //1% of the parent viewport width (same as 1vw):
            var vw = window.parent.innerWidth/100;
            //1% of the viewport height (same as 1vh):
            var vh = window.parent.innerHeight/100;

            //assign width and height to your v unit elements here
    }

    window.parent.addEventListener('resize',function(){
          //when the browser window is resized; recalculate
          initializeV();
    });
});

编辑(2018年12月):在评论中,有人要求提供一个示例。我无法提供精确的示例,因为Stackoverflow上的codepens加载的框架源与页面不同。但是,我可以模仿效果。对于实际应用,请参考上面的代码片段。此片段仅旨在说明其工作原理。

Practical Application. Uses the concept explained above but without frame reference.

window.addEventListener('load',function(){
        initializeV();
        function initializeV(){
                //note: I can't use window.parent becuase the code snippet loads on a different frame than the parent page. See the other snippet for a practical example. This snippet is meant to merely illustrate the effect.
                //1% of the parent viewport width (same as 1vw):
             var vw = window.innerWidth/100;
                //1% of the viewport height (same as 1vh):
             var vh = window.innerHeight/100;
        
              //this is where the magic happens. Simply set width/height/whatever to a multiple of vw/vh and add 'px'. Dimensions must be in pixels since the vw/vh measurement is based on pixels.
              document.getElementById('test').style.width = 30*vw+'px';
              document.getElementById('test').style.height = 50*vh+'px';
                //assign width and height to your v unit elements here
        }
        
        window.addEventListener('resize',function(){
              //when the browser window is resized; recalculate
              initializeV();
        });
    });
#test{
background:red;
}
<div id="test"></div>


1
@JamieCounsell "//在此处为您的v单位元素分配宽度和高度" 是什么意思?我该怎么做?你能举个例子吗?谢谢。 - user8581664
我在iframe中有另一个iframe,我认为这会导致它出现问题。这是主iframe的代码。https://jsfiddle.net/samgurdus/o3vkhp5o/ - user8581664
4
我认为任何负评都是因为您没有对计算出的值进行任何有用的操作。vh 的整个意义在于在 css 中使用它。您只是调用了一个无法用作 vh 的变量 vh。 - Simon_Weaver
@Simon_Weaver 谢谢。我直到现在才看到你的评论。我更新了答案。我无法提供确切的示例,因为片段在父级框架上加载,但我成功创建了一个说明影响的示例。 - www139
应用测量只需使用 elem.style.dimension = 50*vh+'px'; 将 vh/vw 测量乘以所需数字(50*vh 实际上是 50vh 单位),然后加上 'px'。必须以像素为单位进行测量,因为这是 vh/vw 测量基于的单位系统。 - www139
显示剩余3条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接