Using CSS to affect div style inside iframe
Asked Answered
M

14

336

Is it possible to change styles of a div that resides inside an iframe on the page using CSS only?

Multifaceted answered 24/2, 2009 at 21:46 Comment(2)
Possible duplicate of How to apply CSS to iframe?Decanal
More info about CORS: wikipedia.org/wiki/Content_Security_Policy and developer.mozilla.org/docs/Web/HTTP/CORSDillion
P
152

You need JavaScript. It is the same as doing it in the parent page, except you must prefix your JavaScript command with the name of the iframe.

Remember, the same origin policy applies, so you can only do this to an iframe element which is coming from your own server.

I use the Prototype framework to make it easier:

frame1.$('mydiv').style.border = '1px solid #000000'

or

frame1.$('mydiv').addClassName('withborder')
Persimmon answered 24/2, 2009 at 21:51 Comment(4)
see my this question it's similar #1963207 but can't we change style if frame is from another server?Aorangi
That is correct. The Iframe content is subject to the same-domain policy. If it's from your domain, you can control it, if not, you're locked out. This prevents all kinds of Iframe-based page hijacking.Persimmon
Not exactly a "CSS only" solution, but good enough for me. +1Produce
This is not CSS.Granulite
R
151

In short no.

You can not apply CSS to HTML that is loaded in an iframe, unless you have control over the page loaded in the iframe due to cross-domain resource restrictions.

Rachealrachel answered 24/2, 2009 at 21:49 Comment(3)
This is true but don't really help people give an example to of how toSwedenborgian
is this just come up in 2018? I remember that I used to config the style of iframe come from outside. I tried to apply css to iframe that rendered by script but it stil not work.lWithin
@SimonDragsbæk assume asking for example "how-to" if you DO have control over iFrame content? So heres mine. , if (window.location !== window.parent.location) { // The page is in an iFrame var css = 'nav { display: none; }', head = document.head || document.getElementsByTagName('head')[0], style = document.createElement('style'); head.appendChild(style); style.type = 'text/css'; style.appendChild(document.createTextNode(css)); } ,Ssm
W
54

Yes. Take a look at this other thread for details: How to apply CSS to iframe?

const cssLink = document.createElement("link");
cssLink.href  = "style.css";  
cssLink.rel   = "stylesheet";  
cssLink.type  = "text/css";  
frames['frame1'].contentWindow.document.body.appendChild(cssLink); 
//     ^frame1 is the #id of the iframe: <iframe id="frame1">
Worser answered 27/9, 2011 at 14:48 Comment(5)
is frame1 the id of the iframe ??Itchy
Yes, frame1 is the id of the iframe.Worser
This is no CSS.Granulite
this we cannot do if we are loading different domain in iframe.Petta
frame1 is the iframe name, not the IDTwilatwilight
P
13

You can retrieve the contents of an iframe first and then use jQuery selectors against them as usual.

$("#iframe-id").contents().find("img").attr("style","width:100%;height:100%")

$("#iframe-id").contents().find("img").addClass("fancy-zoom")

$("#iframe-id").contents().find("img").onclick(function(){ zoomit($(this)); });

Good Luck!

Pasley answered 11/3, 2015 at 20:34 Comment(2)
doesn't work: Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin "HOST" from accessing a cross-origin frame.Iila
@tubbo, in your case, you cannot embed unauthorised sites prevented from XSS. This is only for those looking for their own problems, not hackers :pPasley
B
12

The quick answer is: No, sorry.

It's not possible using just CSS. You basically need to have control over the iframe content in order to style it. There are methods using javascript or your web language of choice (which I've read a little about, but am not to familiar with myself) to insert some needed styles dynamically, but you would need direct control over the iframe content, which it sounds like you do not have.

Bilection answered 24/2, 2009 at 21:56 Comment(0)
M
9

Use Jquery and wait till the source is loaded, This is how I have achieved(Used angular interval, you can use javascript setInterval method):

var addCssToIframe = function() {
    if ($('#myIframe').contents().find("head") != undefined) {
        $('#myIframe')
                .contents()
                .find("head")
                .append(
                        '<link rel="stylesheet" href="app/css/iframe.css" type="text/css" />');
        $interval.cancel(addCssInterval);
    }
};
var addCssInterval = $interval(addCssToIframe, 500, 0, false);
Multifold answered 24/7, 2014 at 8:23 Comment(1)
why dont you use iframe loaded event ?Kantos
A
6

Apparently it can be done via jQuery:

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

https://mcmap.net/q/67364/-override-body-style-for-content-in-an-iframe

Aldrich answered 13/10, 2016 at 1:36 Comment(5)
You can't use this anymore because of the same origin policy in Chrome browser. The error message: Uncaught DOMException: Failed to read the 'contentDocument' property from 'HTMLIFrameElement': Blocked a frame with origin **** from accessing a cross-origin frame.Adolescent
@adamj, Can we change overwrite style sheet of iframe element? if yes, kindly add script.Saleswoman
this is an excellent answer if you are NOT using content from another webpage outside of your domain but is perfect if you are dealing with content related to your own page. Like rendering image uploads into iframes and such this is an excellent solution. Thank you @AldrichVlf
This is not working for meFrizzle
Mohammed is right, this no longer works due to CORS, but it would work if it's same domain that you are controlling.Aldrich
V
6

Combining the different solutions, this is what worked for me.

$(document).ready(function () {
    $('iframe').on('load', function() {
        $("iframe").contents().find("#back-link").css("display", "none");
    }); 
});
Vesicant answered 28/9, 2019 at 23:24 Comment(0)
L
3

probably not the way you are thinking. the iframe would have to <link> in the css file too. AND you can't do it even with javascript if it's on a different domain.

Literality answered 24/2, 2009 at 21:50 Comment(2)
Can you possibly give an example of how this can be done? Do you mean something like <iframe src="/source" link=css-stylesheet:"/css.css">?Antilles
@Antilles no, for a cross-origin iframe, the embeddable site would need to have the <link> tag inside of its own HTML. If the frame's source resides on the same parent domain, then you can inject a style tag (or inline styles) with JavaScript.Haight
K
3

If the iframe comes from another server, you will have CORS ERRORS like:

Uncaught DOMException: Blocked a frame with origin "https://your-site.com" from accessing a cross-origin frame.

Only in the case you have control of both pages, you can use https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage to safely send messages like this:

On you main site(one that loads the iframe):

const iframe = document.querySelector('#frame-id');
iframe.contentWindow.postMessage(/*any variable or object here*/, 'https://iframe-site.example.com');

on the iframe site:

// Called sometime after postMessage is called
window.addEventListener("message", (event) => {
  // Do we trust the sender of this message?
  if (event.origin !== "http://your-main-site.com")
    return;
...
...
  
});
Krak answered 10/10, 2022 at 12:57 Comment(0)
L
1

Not possible from client side . A javascript error will be raised "Error: Permission denied to access property "document"" since the Iframe is not part of your domaine. The only solution is to fetch the page from the server side code and change the needed CSS.

Locomotion answered 30/5, 2015 at 10:41 Comment(1)
This answer is correct in its' content but relates to JavaScript whereas the question relates to CSS. The answer may be that you need to use JavaScript but you don't say that. The answer also assumes that the content in the iFrame is from a different domain, which is not always the case. Lastly, the exact message will vary from browser to browser.Pissed
S
1

A sort of hack-ish way of doing things is like Eugene said. I ended up following his code and linking to my custom Css for the page. The problem for me was that, With a twitter timeline you have to do some sidestepping of twitter to override their code a smidgen. Now we have a rolling timeline with our css to it, I.E. Larger font, proper line height and making the scrollbar hidden for heights larger than their limits.

var c = document.createElement('link');
setTimeout(frames[0].document.body.appendChild(c),500); // Mileage varies by connection. Bump 500 a bit higher if necessary
Selfinsurance answered 15/12, 2015 at 15:3 Comment(1)
this is potentially very problematic since you have no possible way of ensuring that your timeout will be the correct value. I was attempting the same implementation and opted to use the above poster solution since it can be triggered directly by the iframes content onload event. See adamj's answerVlf
H
1

Just add this and all works well:

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
Humanity answered 26/9, 2019 at 14:42 Comment(2)
not sure whether this is the correct answer to the given question, but it was a great solution to resize the google form to the width of the device, many thanks!Extraterritoriality
@Extraterritoriality I have tried in one of the application and it works perfectHumanity
W
0

Yes, it's possible although cumbersome. You would need to print/echo the HTML of the page into the body of your page then apply a CSS rule change function. Using the same examples given above, you would essentially be using a parsing method of finding the divs in the page, and then applying the CSS to it and then reprinting/echoing it out to the end user. I don't need this so I don't want to code that function into every item in the CSS of another webpage just to aphtply.

References:

Wives answered 5/9, 2013 at 17:59 Comment(2)
The question specifically asks "using CSS only". With that in mind, your answer is wrong.Lisandra
This is not CSS.Granulite

© 2022 - 2024 — McMap. All rights reserved.