如何将CSS应用于iframe?

976 html css iframe

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

Tam*_*ege 422

编辑:除非设置了适当的CORS标头,否则这不适用于跨域.

这里有两个不同的东西: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>
Run Code Online (Sandbox Code Playgroud)

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

<link type="text/css" rel="Stylesheet" href="Style/simple.css" />
Run Code Online (Sandbox Code Playgroud)

或者它可以使用Javascript从父页面加载:

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

  • 只是这样no1否则必须测试它才能找出:正确,它不适用于跨域.执行frame ['name']后,您会立即得到"不安全的JavaScript尝试使用URL blah从帧中获取URL blah.域,协议和端口必须匹配." (88认同)
  • 链接*可能只出现在HEAD中* (35认同)
  • 请注意,在我看来,之前发布的一些示例现在对html5无效.您可以按如下方式访问框架的内容:`document.getElementById("myframe").contentDocument`.虽然嵌入css似乎对我不起作用. (30认同)
  • 这实际上是跨域工作吗?我认为不会. (24认同)
  • 只有当我做了`... document.head.appendChild(cssLink)` - Firefox和Safari时才为我工作. (17认同)
  • 在我的情况下,它显示此错误:frames.frame1.document未定义 (5认同)

Seq*_*com 198

我在Google日历中遇到了这个问题.我想在较暗的背景上设计它并改变字体.

幸运的是,嵌入代码中的URL对直接访问没有限制,因此通过使用PHP函数file_get_contents,可以从页面获取整个内容.可以调用位于服务器上的php文件,而不是调用Google URL.google.php,其中包含原始内容并进行修改:

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

添加样式表的路径:

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

(这会将样式表放在head结束标记之前.)

如果css和js相对调用,请指定原始URL的基本URL:

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

最终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;
Run Code Online (Sandbox Code Playgroud)

然后将iframe嵌入代码更改为:

<iframe src="http://www.yourwebsiteurl.com/google.php" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>
Run Code Online (Sandbox Code Playgroud)

祝好运!

  • 如果你愿意,可以按定义调用该黑客.但是你没有提供任何更好的解决方案......这种解决方案不是一种破坏谷歌服务或欺骗人们以利用其弱点的方法. (64认同)
  • 仅供参考,这基本上是黑客攻击. (54认同)
  • 通过这样做,您始终将日历作为未登录的用户.使用普通的html iframe,如果用户登录谷歌,他们会看到他们自己的个人日历,但由于您的PHP代码无法知道用户的Google会话ID,因此无法获取他们的个人日历. (10认同)
  • @ChrisHoughton FYI,它基本上不是.但是,它可能会使整个iframe变得毫无意义(例如,使用iframe的一个原因是出于安全目的,例如使用卡支付,如果您执行此处建议的操作,则可能会导致问题). (9认同)
  • 我会杀死一种让这个解决方案与谷歌文档一起工作的方法.它抛出各种javascript错误."未捕获的TypeError:无法读取未定义的属性'a' (5认同)

Hor*_*ann 71

如果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);
Run Code Online (Sandbox Code Playgroud)

请注意,根据您使用的浏览器,这可能仅适用于来自同一域的网页.

  • 可能值得注意的是,如果页面位于不同的域中,相同的源策略将停止此工作. (81认同)
  • 在同一思路但更简洁:`<iframe onload ="this.contentDocument.body.style.overflow ='hidden';" /></iframe>` (2认同)

Ram*_*ine 58

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

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


han*_*ngy 32

大多数浏览器都会像一个不同的HTML页面一样处理iframe.如果要将相同的样式表应用于iframe的内容,只需从其中使用的页面引用它即可.

  • @hangry但......怎么样? (16认同)

dom*_*mih 27

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

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

这会在iframe页面中隐藏横幅.谢谢你的建议!

  • 这似乎不适用于我。我要编辑的iframe在dom中也没有直接位于其下方的头。那么这是否意味着我需要访问html文档的头部,还是jquery find函数应该能够自己完成的事情? (3认同)

Ash*_*Ash 26

如果您控制iframe中的页面,就像hangy所说的那样,最简单的方法是创建一个具有常见样式的共享CSS文件,然后从您的html页面链接到它.

否则,您不太可能从iframe中的外部页面动态更改页面样式.这是因为浏览器已经加强了跨框架dom脚本的安全性,因为可能会滥用欺骗和其他黑客攻击.

本教程可能会为您提供有关一般脚本编写iframe的更多信息. 关于跨框架脚本从IE角度解释了安全性限制.


小智 19

以上稍有改动的工作原理:

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);
Run Code Online (Sandbox Code Playgroud)

适用于ff3和ie8至少

  • 什么是myData,它来自哪里 (7认同)

sor*_*rin 13

如果你想从主页面重用CSS和JavaScript,你应该考虑用<IFRAME>Ajax加载的内容替换.现在,当搜索机器人能够执行JavaScript时,这更加SEO友好.

这是jQuery示例,其中包含另一个html页面到您的文档中.这比SEO更友好iframe.为了确保机器人没有索引包含的页面,只需将其添加到禁止进入robots.txt

<html>
  <header>
    <script src="/js/jquery.js" type="text/javascript"></script>
  </header>
  <body>
    <div id='include-from-outside'></div>
    <script type='text/javascript'>
      $('#include-from-outside').load('http://example.com/included.html');
    </script> 
  </body>
</html>
Run Code Online (Sandbox Code Playgroud)

您还可以直接在Google中添加jQuery:http://code.google.com/apis/ajaxlibs/documentation/ - 这意味着可选的自动包含更新的版本和一些显着的速度提升.此外,意味着您必须信任它们只为您提供jQuery;)


小智 12

以下对我有用.

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();
Run Code Online (Sandbox Code Playgroud)


Dav*_*haw 10

扩展上述jQuery解决方案,以应对加载帧内容的任何延迟.

$('iframe').each(function(){
    function injectCSS(){
        $iframe.contents().find('head').append(
            $('<link/>', { rel: 'stylesheet', href: 'iframe.css', type: 'text/css' })
        );
    }

    var $iframe = $(this);
    $iframe.on('load', injectCSS);
    injectCSS();
});
Run Code Online (Sandbox Code Playgroud)


Sup*_*nda 10

由于许多答案是为同一个域编写的,我将写下如何在跨域中执行此操作。

首先,您需要了解Post Message API。我们需要一个信使来在两个窗口之间进行通信。

这是我创建的信使。

/**
 * Creates a messenger between two windows
 *  which have two different domains
 */
class CrossMessenger {

    /**
     * 
     * @param {object} otherWindow - window object of the other
     * @param {string} targetDomain - domain of the other window
     * @param {object} eventHandlers - all the event names and handlers
     */
    constructor(otherWindow, targetDomain, eventHandlers = {}) {
        this.otherWindow = otherWindow;
        this.targetDomain = targetDomain;
        this.eventHandlers = eventHandlers;

        window.addEventListener("message", (e) => this.receive.call(this, e));
    }

    post(event, data) {

        try {
            // data obj should have event name
            var json = JSON.stringify({
                event,
                data
            });
            this.otherWindow.postMessage(json, this.targetDomain);

        } catch (e) {}
    }

    receive(e) {
        var json;
        try {
            json = JSON.parse(e.data ? e.data : "{}");
        } catch (e) {
            return;
        }
        var eventName = json.event,
            data = json.data;

        if (e.origin !== this.targetDomain)
            return;

        if (typeof this.eventHandlers[eventName] === "function") 
            this.eventHandlers[eventName](data);
    }

}
Run Code Online (Sandbox Code Playgroud)

在两个窗口中使用它进行通信可以解决您的问题。

在主窗口中,

var msger = new CrossMessenger(iframe.contentWindow, "https://iframe.s.domain");

var cssContent = Array.prototype.map.call(yourCSSElement.sheet.cssRules, css_text).join('\n');
msger.post("cssContent", {
   css: cssContent
})
Run Code Online (Sandbox Code Playgroud)

然后,从 Iframe 接收事件。

在 iframe 中:

var msger = new CrossMessenger(window.parent, "https://parent.window.domain", {
    cssContent: (data) => {
        var cssElem = document.createElement("style");
        cssElem.innerHTML = data.css;
        document.head.appendChild(cssElem);
    }
})
Run Code Online (Sandbox Code Playgroud)

有关更多详细信息,请参阅完整的 Javascript 和 Iframes教程。


Zbi*_*dro 9

我的紧凑版本:

<script type="text/javascript">
$(window).load(function () {
    var frame = $('iframe').get(0);
    if (frame != null) {
        var frmHead = $(frame).contents().find('head');
        if (frmHead != null) {
            frmHead.append($('style, link[rel=stylesheet]').clone()); // clone existing css link
            //frmHead.append($("<link/>", { rel: "stylesheet", href: "/styles/style.css", type: "text/css" })); // or create css link yourself
        }
    }   
});
</script>
Run Code Online (Sandbox Code Playgroud)

但是,有时iframe在窗口加载时没有准备好,因此需要使用计时器.

即用型代码(带定时器):

<script type="text/javascript">
var frameListener;
$(window).load(function () {
    frameListener = setInterval("frameLoaded()", 50);
});
function frameLoaded() {
    var frame = $('iframe').get(0);
    if (frame != null) {
        var frmHead = $(frame).contents().find('head');
        if (frmHead != null) {
            clearInterval(frameListener); // stop the listener
            frmHead.append($('style, link[rel=stylesheet]').clone()); // clone existing css link
            //frmHead.append($("<link/>", { rel: "stylesheet", href: "/styles/style.css", type: "text/css" })); // or create css link yourself
        }
    }
}
</script>
Run Code Online (Sandbox Code Playgroud)

...和jQuery链接:

<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
Run Code Online (Sandbox Code Playgroud)


小智 7

当你说"doc.open()"时,它意味着你可以在iframe中编写任何HTML标签,所以你应该为HTML页面编写所有基本标签,如果你想在你的iframe头中有一个CSS链接,那就写一个iframe中有CSS链接.我举个例子:

doc.open();

doc.write('<!DOCTYPE html><html><head><meta charset="utf-8"/><meta http-quiv="Content-Type" content="text/html; charset=utf-8"/><title>Print Frame</title><link rel="stylesheet" type="text/css" href="/css/print.css"/></head><body><table id="' + gridId + 'Printable' + '" class="print" >' + out + '</table></body></html>');

doc.close();
Run Code Online (Sandbox Code Playgroud)


jth*_*ter 7

这里的其他答案似乎使用jQuery和CSS链接。

此代码使用原始JavaScript。它创建一个新<style>元素。它将该元素的文本内容设置为包含新CSS的字符串。并将该元素直接附加到iframe文档的头部。

var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
  '.some-class-name {' +
  '  some-style-name: some-value;' +
  '}' 
;
iframe.contentDocument.head.appendChild(style);
Run Code Online (Sandbox Code Playgroud)


Aja*_*tra 7

使用可以尝试一下:

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

  • 如果您的iframe来自不同的来源,那么CORS机制将不允许此工作。 (3认同)

小智 6

您将无法以这种方式设置iframe的内容样式.我的建议是使用服务器端脚本(PHP,ASP或Perl脚本)或找到将feed转换为JavaScript代码的在线服务.唯一的另一种方法是,如果你可以做一个服务器端包含.

  • 当你说某些事情无法完成时要小心,实际上这很难 (28认同)