apply css to html but not iframe html
Asked Answered
K

4

7

I'm making a user stylesheet for the add-on 'stylish.'

It applies a semi-transparent dark box over the entire page for night-browsing.

I'm using:

html:before {
    content:url()!important;
    position:fixed!important;
    width:100%!important;
    height:100%!important; 
    top:0!important; 
    left:0!important; 
    background:rgba(2,3,3,.35)!important; 
    z-index:99999999999999999!important;
    pointer-events:none!important;
}

to create the fixed, overlying div.

This works just fine, however, if there are any iframes in the site, it will apply this code into the iframes' HTML as well as you can see here:

because these social networking widgets rely on an IFRAME, its repeating the code into those pages, creating a double-overlaying of the semi transparent dark box i've made.

the desired look would be:

I've tried hack-ish things, like applying a much-higher z-index to iframes and specifying the background-color and background of * of anything in the iframes to 'white' and 'opaque' so that it 'floats' on top of the parent html page, but this doesn't work perfectly. i've also tried something like:

html:not(iframe):before{}

but this also doesn't work. I'm wondering if there is a way to do what I'm trying to do in a way that doesn't rely on 'html:before' to create the same effect, or if there's a way to do that but not have it repeat inside the html of iframes on a page.

I've exhausted my efforts trying to get this to work, so any help would be really appreciated. Thank you.

Klinges answered 7/5, 2013 at 20:33 Comment(10)
This is the first time I heard the term night-browsingJobholder
iframe html:before { display: none; }?Mandler
html:not(iframe) always matches quite simply because html is not iframe.Byrle
Unfortunately, these aren't working. Here's what's going on, i think: an iframe's html doesn't know it's an iframe, as far as 'Stylish' (the add-on) is concerned.. because it is applying the changes to ANY "html" first, blind to the fact that the html is in an iframe. Which is why I'm thinking I'll need to try something other than "html:before" to make the content appear over the 'parent' html page.Klinges
Is this CSS in a user stylesheet, considering you're using Stylish?Byrle
Night browsing ey? So what happens when you try and click a link and nothing happens because you have a massive box covering everything?Newspaper
yes.. it is a user stylesheet. I should have been more clear.Klinges
@mike robinson, 'pointer-events: none' prevents what you described.Klinges
@user1975224 Guess you're not supporting IE then?Newspaper
I didn't realize IE didn't support pointer-events. Someone gave an alternative approach which avoids the pointer-events route all together, fortunately.Klinges
B
1

Unfortunately, there is no way using CSS to target only the contents of an iframe from within the source of the iframe, i.e. the page that contains the iframe element.

I'm assuming, since you're using Stylish, that your CSS is in a Firefox user stylesheet. If so, you may have to look at the source URLs of those iframes, create a @-moz-document rule targeting those URLs at their domains, and remove the html:before pseudo-element accordingly.

Something like this, which should go beneath what you already have:

@-moz-document domain(/* Facebook Like */), 
    domain(/* Tweet Button */), 
    domain(/* Google +1 */)
{
    html:before
    {
        content: none !important;
    }
}

The content: none declaration disables the pseudo-element, preventing it from being rendered.

Having to exclude specific domains in this manner means this method is extremely limited and not very versatile at all, but it's the best I can think of.

Byrle answered 7/5, 2013 at 20:55 Comment(2)
I had tried domain-specific targeting for twitter, fb, etc, but for some reason it didn't work quite right. However, your code works perfectly. I think this is going to have to do. I really appreciate it. :)Klinges
@user1975224: No problem, glad I could help! Truthfully, it was something quick that I whipped up as I'm supposed to (and about to) head to bed - it's almost morning right now where I am!Byrle
P
1

You may want to try a different route:

html {
    box-shadow: inset 0 0 0 2000px rgba(2, 3, 3, .35) !important;
}

Demo

This way the webpage is still useable when the user's browser doesn't support pointer-events.

You may also want to checkout this question: CSS - max z-index value

To apply these styles to only the parent document's <html> element, and not to iframes, simply apply the box-shadow to document.documentElement with JS:

document.documentElement.style.boxShadow = "inset 0 0 0 2000px rgba(2, 3, 3, .35) !important";
Pedantry answered 7/5, 2013 at 20:53 Comment(1)
This is good. Thanks for the suggestion.. now onto finding a way to get it to not work for iframes :[.Klinges
B
1

Unfortunately, there is no way using CSS to target only the contents of an iframe from within the source of the iframe, i.e. the page that contains the iframe element.

I'm assuming, since you're using Stylish, that your CSS is in a Firefox user stylesheet. If so, you may have to look at the source URLs of those iframes, create a @-moz-document rule targeting those URLs at their domains, and remove the html:before pseudo-element accordingly.

Something like this, which should go beneath what you already have:

@-moz-document domain(/* Facebook Like */), 
    domain(/* Tweet Button */), 
    domain(/* Google +1 */)
{
    html:before
    {
        content: none !important;
    }
}

The content: none declaration disables the pseudo-element, preventing it from being rendered.

Having to exclude specific domains in this manner means this method is extremely limited and not very versatile at all, but it's the best I can think of.

Byrle answered 7/5, 2013 at 20:55 Comment(2)
I had tried domain-specific targeting for twitter, fb, etc, but for some reason it didn't work quite right. However, your code works perfectly. I think this is going to have to do. I really appreciate it. :)Klinges
@user1975224: No problem, glad I could help! Truthfully, it was something quick that I whipped up as I'm supposed to (and about to) head to bed - it's almost morning right now where I am!Byrle
J
0

Edit:

I don't know about the addon thing but you could give your HTML tag an ID and target it that way, although if you want this to apply to all pages then that's an issue

or maybe use html:first-child ? I honestly don't know what will happen, you can give it a try though

Jobholder answered 7/5, 2013 at 20:39 Comment(5)
Nope, of course it won't - html is the root element so it will never match in either case.Byrle
how does his css affect the file in iframe, I don't understandJobholder
I'm guessing it has to do with the add-on he's using, which is a user stylesheet manager for Firefox.Byrle
oh that's a different story thenJobholder
html:first-child will not match because html is the root element, and the root element does not have a parent so it is not a child.Byrle
A
0

CSS doesn't allow you to style HTML inside an iframe. Since you're using an add-on, this is a non-standard implementation of CSS. Styles are not inherited by iframes, because an iframe is basically a new browser window. The add-on is adding the style to every HTML page in the browser window. There's no way for the browser to know that a page is inside an iframe (at least not in a way that's accessible via CSS).

Apophyllite answered 7/5, 2013 at 20:55 Comment(2)
Correct, although the add-on in question is merely a UI frontend to Firefox's user stylesheets, which are integral to the cascade and are definitely part of the standard.Byrle
Right, but Firefox is applying the style to each html element. CSS doesn't cascade from one html element to an html element in an iframe. It applies the user stylesheet to both, separately.Apophyllite

© 2022 - 2024 — McMap. All rights reserved.