使用CSS影响iframe内部div样式

335

仅使用CSS,是否可能更改页面上iframe内部的div样式?


1
可能是如何将CSS应用于iframe?的重复问题。 - Alexander O'Mara
关于CORS的更多信息,请参阅:https://wikipedia.org/wiki/Content_Security_Policy 和 https://developer.mozilla.org/docs/Web/HTTP/CORS - ashleedawg
14个回答

151

你需要 JavaScript。这与在父页面中执行相同,唯一的区别是必须在 JavaScript 命令前加上 iframe 的名称。

请记住,同源策略适用,因此您只能对来自自己服务器的 iframe 元素执行此操作。

我使用 Prototype 框架使它更容易:

frame1.$('mydiv').style.border = '1px solid #000000'

或者

frame1.$('mydiv').addClassName('withborder')

3
请看这个问题,它和我的问题很相似:https://dev59.com/WkvSa4cB1Zd3GeqPawCT 但是如果 iframe 是来自另一个服务器的,我们能否改变样式? - Jitendra Vyas
25
没问题。Iframe内容受到同域策略的限制,如果是来自您的域名,您可以控制它,否则您将被锁定在外面。这可以防止各种基于Iframe的页面劫持。 - Diodeus - James MacFarlane
7
虽然不完全是“仅使用CSS”解决方案,但对我来说已经足够好了。+1 - Nicu Surdu
4
这不是CSS。 - stramin

150

简而言之,不行。

如果由于跨域资源限制,除非您可以控制加载在iframe中的页面,否则无法将CSS应用于其中的HTML。


81
这是真的,但并没有真正帮助人们举例说明如何做。 - Simon Dragsbæk
这只是在2018年才出现的吗?我记得以前我曾经配置过来自外部的iframe的样式。我尝试将CSS应用于由脚本渲染的iframe,但仍然无法工作。 - Võ Minh

54

可以。查看此其他线程以获取详细信息: 如何将CSS应用于iframe?

const cssLink = document.createElement("link");
cssLink.href  = "style.css";  
cssLink.rel   = "stylesheet";  
cssLink.type  = "text/css";  
frames['frame1'].contentWindow.document.body.appendChild(cssLink); 
//     ^frame1 is the #id of the iframe: <iframe id="frame1">

4
frame1是iframe的ID吗? - Toni Michel Caubet
5
是的,frame1 是 iframe 的 ID。 - Eugene Rosenfeld
19
这不是CSS。 - stramin
18
如果我们在 iframe 中加载不同的域名,那么我们无法这样做。 - Sunith Saga
1
frame1 是 iframe 的名称,而不是 ID。 - joseantgv

13
你可以首先检索 iframe 的内容,然后像往常一样使用 jQuery 选择器来操作它们。
$("#iframe-id").contents().find("img").attr("style","width:100%;height:100%")

$("#iframe-id").contents().find("img").addClass("fancy-zoom")

$("#iframe-id").contents().find("img").onclick(function(){ zoomit($(this)); });

祝你好运!


16
未捕获的DOM异常:无法从'HTMLIFrameElement'读取'contentDocument'属性:阻止了一个源为"http://HOST"的框架访问跨域框架。 - tubbo
@tubbo,在你的情况下,你不能嵌入被防止XSS的未授权站点。这只适用于那些寻找自己问题而非黑客的人 :p - Riyaz Hameed

12

简明回答是:不行,抱歉。

仅使用CSS是不可能的。基本上,您需要对iframe内容进行控制才能对其进行样式设置。有一些使用JavaScript或您选择的网络语言(我已经了解一些,但自己并不熟悉)来动态插入所需样式的方法,但您需要直接控制iframe内容,听起来好像您没有这个权限。


9

使用Jquery并等待源代码加载完成,这是我实现的方法(使用了Angular间隔,您也可以使用JavaScript的setInterval方法):

var addCssToIframe = function() {
    if ($('#myIframe').contents().find("head") != undefined) {
        $('#myIframe')
                .contents()
                .find("head")
                .append(
                        '<link rel="stylesheet" href="app/css/iframe.css" type="text/css" />');
        $interval.cancel(addCssInterval);
    }
};
var addCssInterval = $interval(addCssToIframe, 500, 0, false);

1
为什么不使用iframe加载事件? - ProllyGeek

6

结合不同的解决方案,以下是对我起作用的方法。

$(document).ready(function () {
    $('iframe').on('load', function() {
        $("iframe").contents().find("#back-link").css("display", "none");
    }); 
});

5

8
由于Chrome浏览器的同源策略,你不能再使用它了。错误信息为:Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin **** from accessing a cross-origin frame.(未捕获的DOM异常:无法从“HTMLIFrameElement”读取“contentDocument”属性:阻止来自****的跨源框架访问。) - Mohammed AlBanna
@adamj,我们可以更改iframe元素的覆盖样式表吗?如果可以,请添加脚本。 - Billu
2
如果您不使用来自域外其他网页的内容,那么这是一个非常好的答案,但如果您处理与自己页面相关的内容,例如将图像上传渲染到iframe中等,则这是一个完美的解决方案。感谢@adamj。 - d0rf47
这对我不起作用。 - Naren Verma
穆罕默德是对的,由于CORS的原因,这个方法已经不再有效了,但如果你控制的是同一个域名,它仍然可以工作。 - adamj

3

如果 iframe 来自另一个服务器,您将会遇到跨域错误,例如:

Uncaught DOMException: Blocked a frame with origin "https://your-site.com" from accessing a cross-origin frame.

只有在您控制两个页面的情况下,您才能使用https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage安全地发送消息,如下所示:
在您的主站点上(加载iframe的站点):
const iframe = document.querySelector('#frame-id');
iframe.contentWindow.postMessage(/*any variable or object here*/, 'https://iframe-site.example.com');

在iframe站点上:

// Called sometime after postMessage is called
window.addEventListener("message", (event) => {
  // Do we trust the sender of this message?
  if (event.origin !== "http://your-main-site.com")
    return;
...
...
  
});

3
也许不是你想象的那样。iframe中的CSS文件也必须有标签引用。即使使用JavaScript,如果在不同的域上也无法实现。

你能否举个例子来说明这个怎么做呢? 你是指类似于 <iframe src="/source" link=css-stylesheet:"/css.css"> 这样的吗? - Ant
1
@Ant 不行,对于跨域 iframe,可嵌入的站点需要在其自己的 HTML 中拥有 <link> 标签。如果框架的源位于相同的父域上,则可以使用 JavaScript 注入样式标签(或内联样式)。 - kano

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