【问题标题】:Override body style for content in an iframe覆盖 iframe 中内容的正文样式
【发布时间】:2013-06-30 00:12:20
【问题描述】:

如何控制iframe 中正文元素的背景图像和颜色?请注意,嵌入的 body 元素有一个类,iframe 属于我网站的一部分。

我需要这个的原因是我的网站将黑色背景分配给正文,然后将白色背景分配给包含文本的 div。 WYSIWYG 编辑器在编辑时使用iframe 嵌入内容,但它不包含 div,因此文本很难阅读。

iframe 在编辑器中的主体有一个在其他任何地方都没有使用过的类,所以我假设它被放在那里这样这样的问题就可以解决了。但是,当我将样式应用于class.body 时,它们不会覆盖应用于正文的样式。奇怪的是样式确实出现在 Firebug 中,所以我不知道发生了什么!

谢谢

更新 - 我尝试了@mikeq 的解决方案,即向作为主体类的类添加样式。这在添加到主页的样式表时不起作用,但在与 Firebug 一起添加时它确实起作用。我假设这是因为 Firebug 应用于页面上的所有元素,而 CSS 未应用于 iframe。这是否意味着在使用 JavaScript 加载窗口后添加 css 会起作用?

【问题讨论】:

  • 虽然不可能触及 iframe 中的任何内容,但将每个 Ajax 的 URL 加载到 <div> 有时是一种解决方法(如果给定的 CORS-Header 允许这样做)...(并在途中通过正则表达式“清理”加载的数据。是的,所有 hacky...)
  • 如果页面域匹配,您可以使用 javascript,但为什么不在内部页面的 HTML 中放置一个样式块来覆盖您想要更改的颜色?只需在覆盖中添加更多选择器或使用重要!如果所有其他方法都失败了,则覆盖您只希望在该页面上的任何颜色样式...

标签: css iframe styles overriding


【解决方案1】:

iframe 有另一个作用域,因此您无法访问它来设置样式或使用 javascript 更改其内容。

基本上是“另一页”。

你唯一能做的就是编辑它自己的 CSS,因为你的全局 CSS 什么都做不了。

【讨论】:

  • 是的,你可以,用 javascript。请注意,它最适用于 iframe URL 和共享同一域的父 URL。但是,我认为您指出这可以通过 iframe 内页面上的 CSS 来完成。
【解决方案2】:

除非您有直接访问权限并因此拥有源 html 和/或 css 文件的所有权,否则您无法更改 iframe 中显示的页面样式。

这是停止XSS (Cross Site Scripting)

【讨论】:

  • “直接访问”是什么意思? iframe 中的页面来自我的网站,它是一个域。
  • 那么您将需要更改站点上的源文件(您不能修改 iframe 中的任何内容) - 因此,如果 iframe 指向 mysite.com/test.html,那么您将需要直接修改test.html...
  • 不能吗?在OP说你可以的条件下。例如,他的内部 iframe URL 与他的父站点相同,因此他应该能够使用您喜欢的任何类型的 javascript 访问 DOM...
  • @Myles Gray 错了。如果 iframe 位于同一域中,您可以从其父页面修改 iframe 中的内容,同时使用 JavaScript 和 CSS。
【解决方案3】:

为您的 iframe 页面的正文提供一个 ID(或您愿意的类)

<html>
<head></head>
<body id="myId">
</body>
</html>

然后,同样在 iframe 的页面中,为 CSS 中的页面分配背景

#myId {
    background-color: white;
}

【讨论】:

  • 这很奇怪。当我使用 firebug 将其添加到页面时,您的解决方案对我有用,但如果它在页面的普通 css 文件中则不起作用。这可能是您评论“假设 iFrame 中的页面是您要编辑的”的一部分吗?我没明白你的意思。谢谢
  • 我的意思是,您从您的网站加载到 iFrame 中的页面是否在您的控制之下?还是来自外部站点,您无法编辑源以包含该 ID/类。
  • 它来自我的网站,但由于它是由编辑器完成的,因此更改被拉出的标记并不容易。
  • ps 我的意思不是将 id="myId" 添加到您的主页,而是添加到 iFrame 中的页面。这样,您可以将 iFrame 页面的主体定位到与您的主页不同的样式。您也不是在 iFrame 页面中引用 CSS 文件。您需要将 iFrame 中加载的页面视为完全独立的页面。如果您只将该页面加载到网络浏览器中,它的样式是否正确?
  • 我实际上不确定“页面”在哪里,因为它不是编辑器使用的整个页面。感谢您的帮助,我想我明白所有这些东西是如何运作的。
【解决方案4】:

iframe 是页面中的一个“洞”,其中显示另一个网页。 iframe 的内容不是任何形状,也不是父页面的一部分。

正如其他人所说,您的选择是:

  • 为 iframe 中正在加载的文件提供必要的 CSS
  • 如果 iframe 中的文件与您的父级来自同一个域,那么您可以从父级访问 iframe 中文档的 DOM。

【讨论】:

  • 选项实际上更广泛,但比使用客户端 API 复杂得多,并且涉及通过 REST 接口提供的自定义代理。最好看看 GRIDNET OS 的 (gridnet.org) 原生浏览器网络浏览器。
【解决方案5】:

仅当 iframe 内容来自同一个父域时才有效。

以下 jquery 脚本适用于我。在 Chrome 和 IE8 上测试。内部 iframe 引用的页面与父页面位于同一域中。

在这种特殊情况下,我在内部 iframe 中隐藏了一个具有特定类的元素。

基本上,您只需将style 元素附加到加载到框架中的文档的头部:

frame.addEventListener("load", ev => {
    const new_style_element = document.createElement("style");
    new_style_element.textContent = ".my-class { display: none; }"
    ev.target.contentDocument.head.appendChild(new_style_element);
});

您也可以使用link 元素代替style 来引用样式表资源。

【讨论】:

  • @SimpleSam5 你能提供 Javascript 替代方案(不使用 Jquery)吗?
  • @sincerekamal 下面是不需要 jQuery 的代码:jsfiddle.net/9g9wkpon 你只需要知道连字符的 CSS 属性是在 JavaScript 中以驼峰形式编写的,就像在我的示例中一样。 :)
  • jquery.js?ver=1.12.4:2 Uncaught DOMException: 无法从 'HTMLIFrameElement' 中读取 'contentDocument' 属性: 阻止了原点为 "xxxxxxxxx.com" 的框架访问跨原始框架。
  • @AlexStanese 正如 jeremy 所说,这仅在 iframe 页面来自与父页面相同的服务器时才有效......这通常意味着您无论如何都不需要打扰 javascript......只需首先将 CSS 添加到其他页面即可。
  • @KamalakannanJ 你甚至不需要使用 Javascript。只需编辑 iFrame 中的页面并将 CSS 放在那里。
【解决方案6】:

也许它现在已经改变了,但是我使用了一个单独的样式表来处理这个元素:

.feedEkList iframe
{
max-width: 435px!important;
width: 435px!important;
height: 320px!important;
}

要成功设置嵌入式 youtube iframe 的样式...请参阅 the blog posts on this page

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接的答案可能会失效。
  • 这仅适用于 iFrame 元素本身 - 该问题专门询问 iFrame 内容,目前无法仅通过 CSS 进行更改。
  • @ShaifulIslam 这正是发生的事情。让 Tims 的回答毫无用处。
【解决方案7】:

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

但是请记住,不允许访问从另一个来源加载的文档的元素(出于安全原因)——当尝试从嵌入框架的页面。

var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
  'body {' +
  '  background-color: some-color;' +
  '  background-image: some-image;' +
  '}' 
;
iframe.contentDocument.head.appendChild(style);

【讨论】:

  • Blocked a frame with origin xxxxxxxxx from accessing a cross-origin frame. 恐怕不行
  • @Mike 我绕过了这一点,使用服务器端 lang(PHP) 解析 iframe url 并返回 html 响应以防止 cors 错误
【解决方案8】:

覆盖另一个域 iframe CSS

通过使用 SimpleSam5's answer 的一部分,我通过 Tawk 的一些聊天 iframe 实现了这一点(他们的 customization interface 很好,但我需要进一步自定义)。

在这个显示在移动设备上的特定 iframe 中,我需要隐藏默认图标并放置我的一张背景图片。我做了以下事情:

Tawk_API.onLoad = function() {
// without a specific API, you may try a similar load function
// perhaps with a setTimeout to ensure the iframe's content is fully loaded
  $('#mtawkchat-minified-iframe-element').
    contents().find("head").append(
     $("<style type='text/css'>"+
       "#tawkchat-status-text-container {"+
         "background: url(https://example.net/img/my_mobile_bg.png) no-repeat center center blue;"+
         "background-size: 100%;"+
       "} "+
       "#tawkchat-status-icon {display:none} </style>")
   );
};

我不拥有任何 Tawk 的域,这对我有用,因此即使它不是来自同一个父域,您也可以这样做(尽管 Sam 的回答是 Jeremy Becker's comment)。

【讨论】:

  • 我怀疑这只是因为 Tawk 的人明确允许这样做。
  • @CPHPython 也许你可以帮助我。看看这个:stackoverflow.com/questions/60923168/…
  • 试图覆盖谷歌翻译栏 css 并且成功了!
【解决方案9】:

如果您可以控制托管 iframe 的页面和 iframe 的页面,则可以将查询参数传递给 iframe...

这是一个根据托管网站是否为移动网站向 iframe 添加类的示例...

添加 iFrame:

var isMobile=$("mobile").length; //detect if page is mobile
var iFrameUrl ="https://myiframesite/?isMobile=" + isMobile; 

$(body).append("<div id='wrapper'><iframe src=''></iframe></div>");
$("#wrapper iframe").attr("src", iFrameUrl ); 

在 iFrame 内:

//add mobile class if needed
var url = new URL(window.location.href);
var isMobile = url.searchParams.get("isMobile");
if(isMobile == "1") {
    $("body").addClass("mobile");
}

【讨论】:

【解决方案10】:

我有一个blog,但在查找如何调整我的嵌入式要点时遇到了很多麻烦。帖子管理器只允许您编写文本、放置图像和嵌入 HTML 代码。博客布局本身就是响应式的。它是用 Wix 构建的。但是,嵌入式 HTML 不是。我读了很多关于如何在生成的 iFrame 主体内调整组件大小的信息。所以,这是我的建议:

如果 iFrame 中只有一个组件,即 gist,则只能调整 gist 的大小。忘记 iFrame。

我在视口、不同用户代理的特定布局方面遇到问题,这解决了我的问题:

<script language="javascript" type="text/javascript" src="https://gist.github.com/roliveiravictor/447f994a82238247f83919e75e391c6f.js"></script>

<script language="javascript" type="text/javascript">

function windowSize() {
  let gist = document.querySelector('#gist92442763');

  let isMobile = {
    Android: function() {
        return /Android/i.test(navigator.userAgent)
    },
    BlackBerry: function() {
        return /BlackBerry/i.test(navigator.userAgent)
    },
    iOS: function() {
        return /iPhone|iPod/i.test(navigator.userAgent)
    },
    Opera: function() {
        return /Opera Mini/i.test(navigator.userAgent)
    },
    Windows: function() {
        return /IEMobile/i.test(navigator.userAgent) || /WPDesktop/i.test(navigator.userAgent)
    },
    any: function() {
        return (isMobile.Android() || isMobile.BlackBerry() || isMobile.iOS() || isMobile.Opera() || isMobile.Windows());
    }
};

  if(isMobile.any()) {
    gist.style.width = "36%";
    gist.style.WebkitOverflowScrolling = "touch"
    gist.style.position = "absolute"
  } else {
    gist.style.width = "auto !important";
  }
}

windowSize();

window.addEventListener('onresize', function() {
    windowSize();
});

</script>

<style type="text/css">

.gist-data {
  max-height: 300px;
}

.gist-meta {
  display: none;
}

</style>

逻辑是根据用户代理设置 gist(或您的组件)css。在应用到查询选择器之前,请确保首先识别您的组件。 Feel free to take a look how responsiveness is working

【讨论】:

    【解决方案11】:

    如果您是两者的所有者,这应该适用于跨域

    这里的窍门是给你的 body 分配一个全局 css 变量,用新颜色监听消息,然后在收到消息后更改全局 css 变量。

    我正在使用 Angular,但它应该适用于纯 javascript

    我的用例是在保存之前向用户展示颜色变化将如何影响他在 iframe 中的网站

    域 A

    @ViewChildren('iframeContainer') iframeContainer: QueryList<ElementRef>
    
    sendDataToIframe(
      data = {
          type: 'colorChange',
          colors: {primary: '#000', secondary: '#fff'},
      },
    ): void {
      if (this.targetUrl)
        this.iframeContainer.first.nativeElement.contentWindow.postMessage(data) // You may use document.getElementById('iframeContainer') instead
    }
    

    域 B

    acceptedEditOrigins = [
      'https://my.origine.ccom', // Be sur to have a correct origin, to avoid xss injecto: https://en.wikipedia.org/wiki/Cross-site_scripting
    ]
    
    constructor() {
    // Listen to message
    window.addEventListener('message', (event) => this.receiveMessage(event), false)
    }
    
    receiveMessage(event: MessageEvent) {
      if (this.acceptedEditOrigins.includes(event.origin))
        switch (event.data.type) {
          case 'colorChange': {
            this.setWebsiteConfigColor(event.data.colors)
          }
        }
    }
    
    setWebsiteConfigColor(colors: WebsiteConfigColors) {
      if (colors) {
        const root = document.documentElement
        for (const [key, value] of Object.entries(colors)) {
           root.style.setProperty(`--${key}`, value) // --primary: #000, --secondary: #fff
        }
      }
    }
    
    
    body {
      background-color: var(--primary);
    }
    

    【讨论】:

      猜你喜欢
      • 2011-09-25
      • 2015-06-14
      • 1970-01-01
      • 2013-06-23
      • 2022-07-02
      • 2012-08-04
      相关资源
      最近更新 更多