如何将CSS应用于iframe?

1204

我有一个简单的页面,其中包含一些iframe部分(用于显示RSS链接)。我如何将主页面的相同CSS格式应用于在iframe中显示的页面?


79
只有当 iframe 的域名与父级相同时才可能实现。 - gawpertron
14
gawpertron,我想澄清一下,你的意思是说如果我使用来自我无法控制的其他域的iFrame内容,那么我就无法控制该内容的CSS样式吗? - Ville M
你能列出一个链接给我们看看我们的更改吗? - user3376708
5
域名、端口和协议必须保持一致,子域名也不可用。 - lee penkman
28个回答

504

编辑:除非设置了适当的CORS header,否则此方法不能在跨域时使用。

这里有两个不同的东西:iframe块的样式和嵌入在iframe中页面的样式。您可以像通常那样设置iframe块的样式:

<iframe name="iframe1" id="iframe1" src="empty.htm" 
        frameborder="0" border="0" cellspacing="0"
        style="border-style: none;width: 100%; height: 120px;"></iframe>

嵌入iframe的页面样式必须通过在子页面中包含它来设置:

<link type="text/css" rel="Stylesheet" href="Style/simple.css" />

或者可以通过Javascript从父页面加载:

var cssLink = document.createElement("link");
cssLink.href = "style.css"; 
cssLink.rel = "stylesheet"; 
cssLink.type = "text/css"; 
frames['iframe1'].document.head.appendChild(cssLink);

43
请注意,我认为之前发布的一些示例现在对于html5已失效。您可以按以下方式访问框架内容:document.getElementById("myframe").contentDocument。然而,嵌入css似乎仍然无法正常工作。 - Rehno Lindeque
38
链接只能出现在HEAD中 - Knu
22
只有当我执行 ...document.head.appendChild(cssLink) 时,它才对我起作用——在 Firefox 和 Safari 上。 - mojuba
25
这实际上能够跨域工作吗?我认为不行。 - Simon East
97
为了避免其他人进行测试以找出答案:正确,它不能跨域工作。一旦执行frames['name'],就会显示“Unsafe JavaScript attempt to access frame with URL blah from frame with URL blah. Domains, protocols and ports must match.”(不安全的JavaScript尝试访问URL为blah的框架,但其与URL为blah的框架的域名、协议和端口必须匹配)。 - Kevin

221

我在使用谷歌日历时遇到了这个问题。我想在较暗的背景下进行样式设置并更改字体。

幸运的是,嵌入代码中的URL没有直接访问限制,因此可以使用PHP函数file_get_contents获取页面上的整个内容。取而代之的是调用谷歌的URL,可以调用位于您服务器上的php文件,例如google.php,其中包含带有修改的原始内容:

$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');

将样式表的路径添加到你的页面中:

$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);

(这将把您的样式表放在 head 结束标记之前。)

指定原始 URL 的基本 URL,以防相对调用 CSS 和 JS:

$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);

最终的google.php文件应该是这样的:

<?php
$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');
$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);
$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);
echo $content;

然后你需要更改iframe嵌入代码为:

<iframe src="http://www.yourwebsiteurl.com/google.php" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>

祝你好运!


80
如果你愿意,你可以称之为“黑客行为”。但你并没有提供更好的解决方案……这个解决方案不是破坏谷歌服务或诱骗人们以利用他们的弱点的方法。 - SequenceDigitale.com
6
我很愿意为了让这个解决方案适用于谷歌文档而做出努力。但它在使用过程中会抛出各种JavaScript错误,其中一个是“未捕获的类型错误:无法读取未定义属性'a'”。 - deweydb
11
FYI,基本上并不是这样。但是,它可能会使整个 iframe 失去意义(例如,使用 iframe 的一个原因是出于安全考虑,例如在进行信用卡支付时,如果你按照这里建议的做法,可能会给自己带来问题)。 - al45tair
15
通过这样做,你总是以非登录用户的身份获取日历。使用普通的HTML iframe,如果用户登录Google,则会看到他们自己的个人日历,但由于你的PHP代码无法知道用户的Google会话ID,因此无法获取其个人日历。 - bdsl

84

如果iframe的内容不完全受你的控制,或者你想从不同样式的页面访问内容,则可以尝试使用JavaScript进行操作。

var frm = frames['frame'].document;
var otherhead = frm.getElementsByTagName("head")[0];
var link = frm.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", "style.css");
otherhead.appendChild(link);

请注意,根据您所使用的浏览器,这可能仅适用于从同一域名下提供的页面。


101
值得注意的是,如果页面位于不同的域名下,同源策略将阻止此方法的使用。 - ConroyP
3
相同的思路,但更为简洁:<iframe onload="this.contentDocument.body.style.overflow='hidden';" /> - Protector one
即使 Firefox 也已经支持 CORS。 - user985399
这段代码片段 <iframe id="iframe-payment2" onload="this.style.height='1600px';" frameborder="0" scrolling="no" height="1800" src="<?php echo "//" . $_SERVER['HTTP_HOST']; ?>/payment/" ></iframe> 对我起作用了。 - Pavan Yogi
var frm = frames['frame'].document; 应该改为 var frm = window.frames['frame'].document;。然而,仍然无法正常工作,因为文档返回未定义。 - Rogier de Ruijter

66
var $head = $("#eFormIFrame").contents().find("head");

$head.append($("<link/>", {
    rel: "stylesheet",
    href: url,
    type: "text/css"
}));

36

以下是如何直接应用CSS代码而无需使用<link>来加载额外的样式表。

这里是如何直接应用CSS代码而无需使用<link>来加载额外的样式表。

var head = jQuery("#iframe").contents().find("head");
var css = '<style type="text/css">' +
          '#banner{display:none}; ' +
          '</style>';
jQuery(head).append(css);

这将在iframe页面中隐藏横幅。感谢您的建议!


这个方法是否也能绕过CORS限制? - undefined

27

如果您可以控制iframe中的页面,那么最简单的方法就是创建一个共享的CSS文件,包含常用的样式,并从您的html页面链接到它。

否则,您很可能无法从iframe外部的页面动态更改页面的样式。这是因为浏览器加强了跨框架DOM脚本的安全性,以防止可能被用于欺骗和其他黑客攻击。

此教程提供了关于脚本iframes的更多信息。有关跨框架脚本的解释从IE的视角解释了安全限制。


25

在大多数浏览器中,iframe被视为不同的HTML页面。如果您想将相同的样式表应用于iframe中的内容,请从其中使用的页面引用它。


69
@hangry 但是...怎么做呢? - A Child of God

20

稍微修改一下之前的代码,就可以正常运行:

var cssLink = document.createElement("link") 
cssLink.href = "pFstylesEditor.css"; 
cssLink.rel = "stylesheet"; 
cssLink.type = "text/css"; 

//Instead of this
//frames['frame1'].document.body.appendChild(cssLink);
//Do this

var doc=document.getElementById("edit").contentWindow.document;

//If you are doing any dynamic writing do that first
doc.open();
doc.write(myData);
doc.close();

//Then append child
doc.body.appendChild(cssLink);

至少在ff3和ie8上运行良好


15

以下方法适用于我。

var iframe = top.frames[name].document;
var css = '' +
          '<style type="text/css">' +
          'body{margin:0;padding:0;background:transparent}' +
          '</style>';
iframe.open();
iframe.write(css);
iframe.close();

13

您可以尝试这个:

$('iframe').load( function() {
     $('iframe').contents().find("head")
     .append($("<style type='text/css'>  .my-class{display:none;}  </style>"));
  });

5
如果你的iframe来自不同的源,CORS机制将不允许这种解决方法。 - Mr. Anderson

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