34

I'm trying to make a css-selector that assigns diffrent properites based on weather the html is inside an iframe or not. I tried this:

html:not(:root) body {
    background: black !important;
}

I expect this to apply background: black; to the body if it's inside an iframe, but it doesn't, why? And are there any css options? I could always check with javascript if html is root.

IE8 support not requierd.

Himmators
  • 14,278
  • 36
  • 132
  • 223
  • The body is sometimes displayed inside an iframe as a widget on third party site, and sometimes it's displayed on it's own. – Himmators Feb 18 '14 at 01:26
  • 1
    You can't apply CSS from outside the iframe. An – Nick Grealy Feb 18 '14 at 01:58
  • Responded and then saw your concession that you could always use javascript, which was exactly what I was suggesting. From what I understand of how CSS operates within frames, I don't it is an option here :( – mirichan Feb 18 '14 at 05:27
  • This will put some light on your issue, please [review this answer](http://stackoverflow.com/questions/16428067/apply-css-to-html-but-not-iframe-html) – Sunil Kumar Feb 18 '14 at 05:34
  • @Sunil Kumar: That question is of a very different nature though. – BoltClock Feb 18 '14 at 05:36

5 Answers5

35

CSS is only scoped within the same document. An iframe is an entire document in its own right, and so a CSS rule that applies to the page that contains that iframe cannot apply to the page that's within that iframe.

This means that as far as HTML and CSS are concerned, html is always :root (and therefore can never be :not(:root)).

Unless you are able to transfer this CSS from the containing page to the page within the iframe (using a script for example), I don't believe there is a way using just CSS.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
27

It is probably possible to do the styling in an iframe with JavaScript.

document.querySelector('iframe').contentDocument.body.querySelector('#some-element').style.background-color = 'red';

IMPORTANT: Make sure that the iframe is on the same domain, otherwise you can't get access to its internals. That would be cross-site scripting.

Accessing elements inside iframes with JavaScript document futher here: Javascript - Get element from within an iFrame

Community
  • 1
  • 1
ThorSummoner
  • 16,657
  • 15
  • 135
  • 147
  • 1
    Using JS for detection is good, butd on't do the styling in JS: make the detection of the framing in JS, put a class (or data attribute) depending on the detection result, and apply your usual CSS file using this new class/data-attribute selector (this separates responsibilities, and allows using strict CSP) – Xenos Jun 02 '19 at 12:26
  • @Xenos what do you mean by "new class/data-attribute selector"? – sortas Feb 06 '20 at 11:27
  • 1
    Do `if (window.parent !== window) { document.documentElement.classList.add('inside-iframe'); }` + `html.inside-iframe { /* properties */ }` with both codes in the iframed-html page (JS detection code in parent frame would be like `document.querySelectorAll('iframe').forEach(i => i.contentDocument.documentElement.classList.add('inside-iframe'));` if prefered – Xenos Feb 07 '20 at 10:24
2

Posting my comment as an answer for better display, you should:

  • Put "is in iframe" detection code in JS, as I don't see any other way of doing so
  • Put CSS code inside the iframe depending on the JS result

So if all code is inside the iframe, do:

if (window.parent !== window) {
    document.documentElement.classList.add('inside-iframe');
}
html.inside-iframe {
    bkacground-color: black;
}

If you want the detection-JS-code to be inside the parent frame, go for:

document.querySelectorAll('iframe')
    .forEach(i => i.contentDocument.documentElement.classList.add('inside-iframe'));

Assuming the iframe is loaded when executing this JS (otherwise, contentDocument/documentElement will not exist). You may rely, in such case, on load event of the iframe (but it seems better anyway to put "is-in-iframe" detection indise the iframe itself, as the corresponding CSS is inside the iframe too)

Xenos
  • 3,351
  • 2
  • 27
  • 50
0
let iframe = document.querySelector('iframe[name="marco"]');
let ele = iframe.contentWindow.document.querySelector("#someElement")
cegprakash
  • 2,937
  • 33
  • 60
-2
html:not(root) body {
    background: black !important;
}

Works

Itay Grudev
  • 7,055
  • 4
  • 54
  • 86