likes
comments
collection
share

如何用css影响iframe中的内容?

作者站长头像
站长
· 阅读数 24

前言

iframe 是一种外网页上显示外部内容的非常方便的方式。但是,如果说这个iframe 中的样式存在你不满意的地方,你如果想通过简单的在父容器上添加css 规则来改变它,这很明显是无效的,在本文中,我们将来尝试着如何通过 JavaScript 将 自定义的 css 注入 iframe

通过 contentDocument 注入 style

我们可以通过 contentDocument 来使得 iframe 中的内容通过 HTML 对象进行返回,具体可以先获取到 iframeDOM 对象,然后通过上面的 contentDocument 属性来获取 iframedocument ,值得注意的是,在部分浏览器当中不支持这个属性,但是可以通过 contentWindow 属性来获取 window 对象,然后我们可以再通过 window.document 达到一样的效果。

因为我们需要获取到元素,所以需要把逻辑都放在元素载入完成以后也就是 window.onload 当中

在获取到 document 对象之后,我们就可以通过修改 innerHTML 的方式来注入 style 标签,这样就能够做到修改 iframe 中的样式,具体的兼容代码如下:

window.onload = function(){
    let myIframe = document. getElementById('myIframe');
    let doc = (myIframe.contentDocument || myIframe.contentWindow)
    if (doc.document)doc=doc.document;
    doc.body.innerHTML = doc.body.innerHTML + '<style>body{color: blue;}</style>'
}

如何用css影响iframe中的内容?

动态获取css文件

fetch 获取 css 文件文本

上面的写法可能你会觉得太麻烦了 '<style>body{color: blue;}</style>' 这样来写样式文件很不符合正常人的写法。

我们可以通过 fetch 的方式来获取 css 文件,假如我就在同级目录下写入了一个 css 样式,就可以这样子来获取它。

如何用css影响iframe中的内容?

/* main.css */
body {
  font-size: 40px;
}

动态获取 css

async function setCss () {
      const baseStyle = await fetch("./main.css").then(res => res.text())
      console.log("🚀 ~ file: index.html:33 ~ setCss ~ baseStyle:", baseStyle)
}
setCss()

如何用css影响iframe中的内容?

成功获取到文件当中的内容,然后我们就可以把内容作为字符串拼接到 style 当中去。

window.onload = function () {
    let myIframe = document.getElementById('myIframe');
    let doc = (myIframe.contentDocument || myIframe.contentWindow)
    if (doc.document) doc = doc.document;
    async function setCss () {
      const baseStyle = await fetch("./main.css").then(res => res.text())
      doc.body.innerHTML = doc.body.innerHTML + `<style>${baseStyle}</style>`
    }
    setCss()
  }

如何用css影响iframe中的内容?

link 标签注入

除了上面的通过 fetch 方式获取 css 文本,我们还可以通过动态创建 link 标签的方式来代替上面的修改 body.innerHTML 的过程,我们可以直接注入 link 标签。

 window.onload = function () {
    let myIframe = document.getElementById('myIframe');
    let doc = (myIframe.contentDocument || myIframe.contentWindow)
    if (doc.document) doc = doc.document;
    let link = document.createElement('link')
    link.href = 'main.css'
    link.rel = 'stylesheet'
    link.type = 'text/css'
    console.log(link);
    doc.head.appendChild(link)
}

但是这种方式的限制在于,你 link 标签的 href 属性直接决定了子项目要去哪里获取这个 css 文件,这可能会导致路径错误的问题。比方说在同一个目录下的两个文件我这样引入是没有问题的。

如何用css影响iframe中的内容?

但是一旦我用一个文件夹来保存子文件,不让他们处于同一目录下

如何用css影响iframe中的内容?

这样就会导致 css 获取失败,我们从浏览器的元素审查中也能够看到

如何用css影响iframe中的内容?

子元素的标签只会去获取你写入 herf 的内容,所以这就需要了解子所在的目录位置

注意

注意上述的方法都只能用于在引用同源的 iframe 内容的时候,对于跨域内容,你只能通过 contentWindow 来获取 window 对象,contentDocument 将会返回一个 null 对象(这里在不同浏览器可能表现不同,本文主要是以谷歌浏览器作为例子)。并且在你想要访问 window 上的属性的时候,控制台将会抛出跨域的报错。

如何用css影响iframe中的内容?