Override body style for content in an iframe

594,426

Solution 1

An iframe is a 'hole' in your page that displays another web page inside of it. The contents of the iframe is not in any shape or form part of your parent page.

As others have stated, your options are:

  • give the file that is being loaded in the iframe the necessary CSS
  • if the file in the iframe is from the same domain as your parent, then you can access the DOM of the document in the iframe from the parent.

Solution 2

The below only works if the iframe content is from the same parent domain.

The following jquery script works for me. Tested on Chrome and IE8. The inner iframe references a page that is on the same domain as the parent page.

In this particular case, I am hiding an element with a specific class in the inner iframe.

Basically, you just append a style element to the head section of the document loaded in a frame:

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

You can also instead of style use a link element, for referencing a stylesheet resource.

Solution 3

You cannot change the style of a page displayed in an iframe unless you have direct access and therefore ownership of the source html and/or css files.

This is to stop XSS (Cross Site Scripting)

Solution 4

This code uses vanilla JavaScript. It creates a new <style> element. It sets the text content of that element to be a string containing the new CSS. And it appends that element directly to the iframe document's head.

Keep in mind, however, that accessing elements of a document loaded from another origin is not permitted (for security reasons) -- contentDocument of the iframe element will evaluate to null when attempted from the browsing context of the page embedding the frame.

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

Solution 5

Override another domain iframe CSS

By using part of SimpleSam5's answer, I achieved this with a few of Tawk's chat iframes (their customization interface is fine but I needed further customizations).

In this particular iframe that shows up on mobile devices, I needed to hide the default icon and place one of my background images. I did the following:

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

I do not own any Tawk's domain and this worked for me, thus you may do this even if it's not from the same parent domain (despite Jeremy Becker's comment on Sam's answer).

Share:
594,426

Related videos on Youtube

jd6699
Author by

jd6699

Updated on June 30, 2021

Comments

  • jd6699
    jd6699 almost 3 years

    How can I control the background image and colour of a body element within an iframe? Note, the embedded body element has a class, and the iframe is of a page that is part of my site.

    The reason I need this is that my site has a black background assigned to the body, and then a white background assigned to divs that contain text. A WYSIWYG editor uses an iframe to embed content when editing, but it doesn't include the div, so the text is very hard to read.

    The body of the iframe when in the editor has a class that isn't used anywhere else, so I'm assuming this was put there so problems like this could be solved. However, when I apply styles to class.body they don't override the styles applied to body. The weird thing is that the styles do appear in Firebug, so I've no idea what's going on!

    Thanks

    UPDATE - I've tried @mikeq's solution of adding a style to the class that is the body's class. This doesn't work when added to the main page's stylesheet, but it does work when added with Firebug. I'm assuming this is because Firebug is applied to all elements on the page whereas the CSS is not applied within iframes. Does this mean that adding the css after window load with JavaScript would work?

    • Frank Nocke
      Frank Nocke about 7 years
      While it's not possible to touch anything in an iframe, loading that URL per Ajax into a <div> can at times be a workaround (if given CORS-Header are allowing for that)... (and „sanitizing“ the loaded data by regexp on the way. Yes, all hacky...)
    • OG Sean
      OG Sean almost 7 years
      You can use javascript if the page domains match, but why not just put a style block in your inner page's HTML to override the colors you want changed? Just add more selectors in your override or use important! if all else fails, to override any color styles you want only on that one page...
    • Michael Yaeger
      Michael Yaeger about 2 years
      @FrankNocke I've got your method to work for loading external site content into a <div> via AJAX. However, how can I style the page better this way?
    • Frank Nocke
      Frank Nocke about 2 years
      @MichaelYaeger Well, sadly, you have to bring on fresh, new (or duplicated) styles (with the host document, in which you are placing things), likely specifically targeted (.class, #id) at that div in which you are loading...
  • jd6699
    jd6699 about 13 years
    What do you mean by 'direct access'? The page in the iframe is from my site, its all one domain.
  • Myles Gray
    Myles Gray about 13 years
    Well then you will need to change the source file on your site (you cannot modify any contents in an iframe) - so if the iframe is pointing at mysite.com/test.html then you will need to modify test.html directly...
  • jd6699
    jd6699 about 13 years
    This is weird. Your solution works for me when I add it to the page with firebug, but doesn't work if its in the page's normal css file. Could this be part of your comment 'assuming the page within the iFrame is yours to edit'? I didnt understand what you meant by that. Thanks
  • mikeq
    mikeq about 13 years
    I mean by that, is the page you are loading into the iFrame from your site and under your control? or is it from an external site that you cannot edit the source to include that id/class.
  • jd6699
    jd6699 about 13 years
    It is from my site, but as its done in by the editor it wont be easy to change the mark up that is pulled through.
  • mikeq
    mikeq about 13 years
    ps I didnt mean add the id="myId" to your main page, but to the page within the iFrame. That way you can target the body of the iFrame page with a different style to your main page. You are also referencing the CSS file in your iFrame pages also aren't you. You need to treat the page loaded in the iFrame as a completely independant page. If you load just that page into a web browser does it have the correct style?
  • jd6699
    jd6699 about 13 years
    Im not actually sure where the 'page' is as its not the whole page the editor uses. Thanks for your help, I think I understand how all this stuff works noe.
  • Shaiful Islam
    Shaiful Islam about 9 years
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes.
  • pwdst
    pwdst almost 9 years
    This only applies to the iFrame element itself - the question asks specifically about the iFrame content, which it currently isn't possible to change through CSS alone.
  • Kamalakannan J
    Kamalakannan J almost 8 years
    @SimpleSam5 Can you provide the Javascript alternative (without using Jquery) ?
  • Dennis98
    Dennis98 almost 8 years
    @sincerekamal Here's the code without the need of jQuery: jsfiddle.net/9g9wkpon You just need to know that hyphenated CSS properties are written in camelCase in JavaScript, like in my example. :)
  • Alex Stanese
    Alex Stanese over 7 years
    jquery.js?ver=1.12.4:2 Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "xxxxxxxxx.com" from accessing a cross-origin frame.
  • DA.
    DA. over 7 years
    @AlexStanese as jeremy states, this only works if the iframe page is coming from the same server as the parent page...which typically means you don't need to bother with javascript anyways...just add the CSS to the other page in the f irst place.
  • DA.
    DA. over 7 years
    @KamalakannanJ you don't even need to use Javascript. Just edit the page that's in the iFrame and put the CSS there.
  • Lawyerson
    Lawyerson about 7 years
    I suspect this only works because the people at Tawk have explicitly allowed it.
  • Alex Foxleigh
    Alex Foxleigh almost 7 years
    @ShaifulIslam which is precisely what has happened. Rending Tims answer useless.
  • OG Sean
    OG Sean almost 7 years
    Cannot? Under the conditions the OP says you can. For example, his inner iframe URL is same as his parent site so he should be able to access the DOM ok with any flavor of javascript you like...
  • OG Sean
    OG Sean almost 7 years
    Yes you can, with javascript. Note it works best with the iframe URL and the parent URL sharing the same domain. But, I think you are right in pointing out this can just be done with CSS on the page inside the iframe.
  • Mike
    Mike over 6 years
    Blocked a frame with origin xxxxxxxxx from accessing a cross-origin frame. I'm afraid it won't work
  • vasilisdmr
    vasilisdmr over 6 years
    @KamalakannanJ in order to get a better understanding, read the following article form MDN that explains what CORS (Cross-Origin Resource Sharing ) is. mzl.la/2E4ehEX I hope it helps!
  • Kevin M
    Kevin M about 5 years
    @Myles Gray Wrong. You can modify the content in an iframe from it's parent page if it's on the same domain, both with JavaScript and CSS.
  • Peter Buju
    Peter Buju about 5 years
    Does an iframe with an embedded pdf from the same domain qualify ? <iframe type="application/pdf" src="mydomain/resources/file.pdf"></iframe>
  • moses toh
    moses toh over 4 years
    @CPHPython Maybe you can help me. Look at this : stackoverflow.com/questions/60923168/…
  • moses toh
    moses toh over 4 years
    Maybe you can help me. Look at this : stackoverflow.com/questions/60923168/…
  • Justine M.
    Justine M. over 3 years
    @Mike I bypassed that by using a serverside lang(PHP) to parse iframe url and return html response to prevent cors errors
  • Camaleo
    Camaleo about 3 years
    tried to override the google tranlation bar css and it work!
  • Vega4
    Vega4 over 2 years
    The options actually are way broader but are much more sophisticated than using client side APIs and involve a custom proxy made available through say REST interface. Best to look at the GRIDNET OS' (gridnet.org) in-native browser web-browser.
  • RixTheTyrunt
    RixTheTyrunt about 2 years
    false. Don't get tricked!
  • augustus182l
    augustus182l about 2 years
    Hey @JustineM. would you please help me to achieve this