【问题标题】:How to apply CSS to iframe?如何将 CSS 应用于 iframe?
【发布时间】:2010-09-18 01:57:45
【问题描述】:

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

【问题讨论】:

  • 有可能,但前提是 iframe 的域与父级相同
  • gawpertron,澄清一下,你是说如果我使用来自我无法控制的其他域的 iFrame 内容,我无法控制该内容的 CSS?
  • 您能否列出该页面的链接,以便我们能够查看我们的更改。
  • 域、端口和协议必须相同,也不能与子域一起使用。

标签: html css iframe rss


【解决方案1】:

编辑:除非设置了适当的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);

【讨论】:

  • 请注意,在我看来,之前发布的一些示例现在对 html5 无效。您可以按如下方式访问框架的内容:document.getElementById("myframe").contentDocument。不过,嵌入 CSS 似乎仍然对我不起作用。
  • 链接可能只出现在 HEAD 中
  • 只有当我 ...document.head.appendChild(cssLink) - Firefox 和 Safari 时才为我工作。
  • 这真的可以跨域工作吗?我认为不会。
  • 所以没有其他人必须对其进行测试才能发现:正确,它不能跨域工作。在执行 frame['name'] 后,您会立即收到“不安全的 JavaScript 尝试从带有 URL blah 的框架访问带有 URL blah 的框架。域、协议和端口必须匹配。”
【解决方案2】:

我在 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');

将路径添加到样式表:

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

(这会将您的样式表放在最后一个 head 结束标记之前。)

在css和js相对调用的情况下,指定原始url的base url:

$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>

祝你好运!

【讨论】:

  • 如果您愿意,您可以根据定义将其称为黑客攻击。但是您没有提供任何更好的解决方案...此解决方案不是破坏 Google 服务或欺骗人们以利用他们的弱点的方式。
  • 我会想办法让这个解决方案与谷歌文档一起工作。它抛出各种javascript错误。 “未捕获的类型错误:无法读取未定义的属性‘a’”
  • @ChrisHoughton 仅供参考,基本上不是。但是,它可能会使整个 iframe 变得毫无意义(例如,使用 iframe 的一个原因是出于安全目的,例如使用卡付款,如果您按照此处的建议进行操作,您可能会遇到问题)。
  • 通过这样做,您始终以未登录用户的身份获取日历。使用普通的 html iframe,如果用户登录到谷歌,他们会看到他们自己的个人日历,但由于您的 PHP 代码无法知道用户的谷歌会话 ID,因此无法获取他们的个人日历。
【解决方案3】:

如果 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);

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

【讨论】:

  • 可能值得注意的是,如果页面位于不同的域中,同源策略将停止此工作。
  • 思路相同但更简洁:&lt;iframe onload="this.contentDocument.body.style.overflow='hidden';" /&gt;
  • 连 Firefox 都已经采用了 CORS
  • sn-p 为我工作。
  • var frm = frames['frame'].document; 应该是 var frm = window.frames['frame'].document;。尽管如此,仍然无法正常工作,文档返回为未定义。
【解决方案4】:
var $head = $("#eFormIFrame").contents().find("head");

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

【讨论】:

    【解决方案5】:

    这里是如何直接应用 CSS 代码而不使用 &lt;link&gt; 加载额外的样式表。

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

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

    【讨论】:

      【解决方案6】:

      如果您在 iframe 中控制页面,正如hangy 所说,最简单的方法是创建一个具有通用样式的共享 CSS 文件,然后从您的 html 页面链接到它。

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

      This tutorial 可能会为您提供有关编写 iframe 脚本的更多信息。 About cross frame scripting 从 IE 角度解释安全限制。

      【讨论】:

        【解决方案7】:

        iframe 被大多数浏览器普遍处理为不同的 HTML 页面。如果您想将相同的样式表应用于 iframe 的内容,只需从其中使用的页面中引用它即可。

        【讨论】:

        • @hangry 但是...怎么样?
        【解决方案8】:

        上面稍加改动就可以了:

        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

        【讨论】:

          【解决方案9】:

          以下内容对我有用。

          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();
          

          【讨论】:

            【解决方案10】:

            如果您想重用主页中的 CSS 和 JavaScript,也许您应该考虑将 &lt;IFRAME&gt; 替换为 Ajax 加载的内容。当搜索机器人能够执行 JavaScript 时,这对 SEO 更加友好。

            这是jQuery 示例,它将另一个html 页面包含到您的文档中。这比iframe 对 SEO 更友好。为了确保机器人没有索引包含的页面,只需将其添加为在 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>
            

            您也可以直接从 Google 中包含 jQuery:http://code.google.com/apis/ajaxlibs/documentation/ - 这意味着可选的自动包含较新版本并显着提高速度。此外,这意味着您必须相信他们只会为您提供 jQuery ;)

            【讨论】:

              【解决方案11】:

              扩展上述 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();
              });
              

              【讨论】:

                【解决方案12】:

                用户可以试试这个:

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

                【讨论】:

                • 如果您的 iframe 来自不同的来源,CORS 机制将不允许此工作区。
                【解决方案13】:

                我的精简版

                <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>
                

                但是,有时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>
                

                ...和 ​​jQuery 链接:

                <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
                

                【讨论】:

                  【解决方案14】:

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

                  首先,您需要知道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);
                      }
                  
                  }
                  

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

                  在主窗口中,

                  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
                  })
                  

                  然后,从 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);
                      }
                  })
                  

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

                  【讨论】:

                    【解决方案15】:

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

                    此代码使用原生 JavaScript。它创建一个新的&lt;style&gt; 元素。它将该元素的文本内容设置为包含新 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);
                    

                    【讨论】:

                      【解决方案16】:

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

                      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();
                      

                      【讨论】:

                        【解决方案17】:

                        您将无法以这种方式设置 iframe 内容的样式。我的建议是使用服务器端脚本(PHP、ASP 或 Perl 脚本)或查找将提要转换为 JavaScript 代码的在线服务。唯一的另一种方法是您可以执行服务器端包含。

                        【讨论】:

                        • 当你说某事不能做时要小心,而实际上它只是困难
                        【解决方案18】:

                        如果您有权访问 iframe 页面并且希望仅在您通过页面上的 iframe 加载它时应用不同的 CSS,我在这里找到了解决此类问题的方法

                        即使 iframe 正在加载不同的域,这也有效

                        查看postMessage()

                        计划是将css作为消息发送到iframe

                        iframenode.postMessage('h2{color:red;}','*');
                        

                        * 是发送此消息,无论它在 iframe 中是什么域

                        并在 iframe 中接收消息并将接收到的消息(CSS)添加到该文档头部。

                        在 iframe 页面中添加的代码

                        window.addEventListener('message',function(e){
                        
                            if(e.data == 'send_user_details')
                            document.head.appendChild('<style>'+e.data+'</style>');
                        
                        });
                        

                        【讨论】:

                          【解决方案19】:

                          我认为最简单的方法是在与 iframe 相同的位置添加另一个 div,然后

                          使其z-index 比 iframe 容器大,因此您可以轻松地设置自己的 div 样式。如果您需要点击它,只需在您自己的 div 上使用 pointer-events:none,这样 iframe 就可以在您需要点击它时工作;)

                          我希望它会对某人有所帮助;)

                          【讨论】:

                            【解决方案20】:

                            我找到了另一种解决方案,可以像这样将样式放在主 html 中

                            <style id="iframestyle">
                                html {
                                    color: white;
                                    background: black;
                                }
                            </style>
                            <style>
                                html {
                                    color: initial;
                                    background: initial;
                                }
                                iframe {
                                    border: none;
                                }
                            </style>
                            

                            然后在 iframe 中执行此操作(参见 js onload)

                            <iframe  onload="iframe.document.head.appendChild(ifstyle)" name="log" src="/upgrading.log"></iframe>
                            

                            在js中

                            <script>
                                ifstyle = document.getElementById('iframestyle')
                                iframe = top.frames["log"];
                            </script>
                            

                            这可能不是最好的解决方案,当然可以改进,但是如果您想在父窗口中保留“样式”标签,这是另一种选择

                            【讨论】:

                              【解决方案21】:

                              这里,域里面有两个东西

                              1. iFrame 部分
                              2. 页面加载到 iFrame 中

                              所以你想把这两个部分设置成如下样式,

                              1. iFrame 部分的样式

                              它可以使用具有受人尊敬的 idclass 名称的 CSS 设置样式。你也可以在你的父样式表中设置它的样式。

                              <style>
                              #my_iFrame{
                              height: 300px;
                              width: 100%;
                              position:absolute;
                              top:0;
                              left:0;
                              border: 1px black solid;
                              }
                              </style>
                              
                              <iframe name='iframe1' id="my_iFrame" src="#" cellspacing="0"></iframe>
                              

                              2。为 iFrame 中加载的页面设置样式

                              这个样式可以在 Javascript 的帮助下从父页面加载

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

                              然后将该 CSS 文件设置为受尊重的 iFrame 部分

                              //to Load in the Body Part
                              frames['my_iFrame'].document.body.appendChild(cssFile); 
                              //to Load in the Head Part
                              frames['my_iFrame'].document.head.appendChild(cssFile);
                              

                              在这里,您也可以使用这种方式在 iFrame 内编辑页面的头部部分

                              var $iFrameHead = $("#my_iFrame").contents().find("head");
                              $iFrameHead.append(
                                 $("<link/>",{ 
                                    rel: "stylesheet", 
                                    href: urlPath, 
                                    type: "text/css" }
                                   ));
                              

                              【讨论】:

                                【解决方案22】:

                                我们可以在 iframe 中插入 style 标签。

                                <style type="text/css" id="cssID">
                                .className
                                {
                                    background-color: red;
                                }
                                </style>
                                
                                <iframe id="iFrameID"></iframe>
                                
                                <script type="text/javascript">
                                    $(function () {
                                        $("#iFrameID").contents().find("head")[0].appendChild(cssID);
                                        //Or $("#iFrameID").contents().find("head")[0].appendChild($('#cssID')[0]);
                                    });
                                </script>
                                

                                【讨论】:

                                • 这不起作用。似乎正确插入了样式标签,但里面没有内容,也没有 ID。
                                【解决方案23】:

                                var link1 = document.createElement('link');
                                    link1.type = 'text/css';
                                    link1.rel = 'stylesheet';
                                    link1.href = "../../assets/css/normalize.css";
                                window.frames['richTextField'].document.body.appendChild(link1);

                                【讨论】:

                                • 我已经检查了很多次这个答案richTextField这里是什么?
                                • 这是 iframe 名称
                                • 我没试过,但我猜它不会因为它针对沙盒
                                【解决方案24】:

                                有一个wonderful script 将节点替换为自身的 iframe 版本。 CodePen Demo

                                用法示例:

                                // Single node
                                var component = document.querySelector('.component');
                                var iframe = iframify(component);
                                
                                // Collection of nodes
                                var components = document.querySelectorAll('.component');
                                var iframes = Array.prototype.map.call(components, function (component) {
                                  return iframify(component, {});
                                });
                                
                                // With options
                                var component = document.querySelector('.component');
                                var iframe = iframify(component, {
                                  headExtra: '<style>.component { color: red; }</style>',
                                  metaViewport: '<meta name="viewport" content="width=device-width">'
                                });
                                

                                【讨论】:

                                • 你为什么要这么做?!
                                【解决方案25】:

                                作为替代方案,您可以使用 CSS-in-JS 技术,如下库:

                                https://github.com/cssobj/cssobj

                                它可以将 JS 对象作为 CSS 动态注入到 iframe 中

                                【讨论】:

                                  【解决方案26】:

                                  这只是一个概念,但不要在没有安全检查和过滤的情况下实现它!否则脚本可能会入侵您的网站!

                                  回答:如果你控制目标站点,你可以设置接收脚本:

                                  1) 使用style参数设置iframe链接,如:

                                  http://your_site.com/target.php?color=red
                                  

                                  (最后一个短语是a{color:red},由urlencode函数编码。

                                  2) 像这样设置接收者页面target.php

                                  <head>
                                  ..........
                                  $col = FILTER_VAR(SANITIZE_STRING, $_GET['color']);
                                  <style>.xyz{color: <?php echo (in_array( $col, ['red','yellow','green'])?  $col : "black") ;?> } </style>
                                  ..........
                                  

                                  【讨论】:

                                  • 警告:这是最好的注射。
                                  • 是的,不要这样做,除非你想在你的服务器上加载大量的渗透测试机器人和脚本小子 =)...
                                  • 我现在更新了答案,增加了安全警告
                                  【解决方案27】:

                                  这就是我在生产中的做法。需要注意的是,如果 iframe 属于其他网站,则会触发 CORS 错误,无法正常工作。

                                      var $iframe =  document.querySelector(`iframe`);
                                      var doc = $iframe.contentDocument;
                                  
                                      var style = doc.createElement("style");
                                      style.textContent = `*{display:none!important;}`;
                                      doc.head.append(style);
                                  

                                  在某些情况下,您可能还想将load 事件附加到 iframe:

                                  var $iframe =  document.querySelector(`iframe`);
                                  
                                  $iframe.addEventListener("load", function() {
                                      var doc = $iframe.contentDocument;
                                      var style = doc.createElement("style");
                                      style.textContent = `*{display:none!important;}`;
                                      doc.head.append(style);
                                  });
                                  

                                  【讨论】:

                                    【解决方案28】:

                                    好吧,我已经按照以下步骤操作了:

                                    1. Div 有一个类来保存iframe
                                    2. iframe 添加到div
                                    3. 在 CSS 文件中,
                                    divClass { width: 500px; height: 500px; }
                                    divClass iframe { width: 100%; height: 100%; }
                                    

                                    这适用于 IE 6。应该适用于其他浏览器,请检查!

                                    【讨论】:

                                    • 需要控制iframe里面的div,这个不需要
                                    猜你喜欢
                                    • 2014-01-14
                                    • 1970-01-01
                                    • 2015-11-12
                                    • 2011-04-12
                                    • 1970-01-01
                                    • 2019-06-04
                                    • 2013-01-15
                                    • 2017-02-26
                                    相关资源
                                    最近更新 更多