Question

I'm working on a project which injects JS+CSS+HTML over web pages which I do not have control over.

I am concerned about the host page styling my injected code -- I want my injected code to only obey my styling, and not theirs.

At the moment the only method to do this I can think of involves explicitly specifying every possible tag for the container <div>'s class (using pre-defined, known browser defaults) and relying on inheritance for those rules to propagate down to the rest of my injected HTML. This CSS would need to appear at the bottom of the page's <head> tag.

I don't think that's the best solution, though, and I don't look forward to implementing it. Surely there are better ways.

Was it helpful?

Solution

Others have suggested very good ways to prevent your CSS from affecting the page's, as well as making sure that your CSS takes precedence, but you seem most concerned with the page's CSS affecting you - that is, adding a funky, unexpected style (like making all divs have a pink background).

The only way I can think for you to prevent their styling from affecting your injected code would be for you to sandbox what you've injected, like in an iframe. Otherwise there's simply too many things that you'd have to define - you'd have to define every single style (padding, border, margin, background... the list goes on and on) on the "*" selector (or better yet, "#yourid *", so you just override your own content), just so that you can guarantee absolute control over your CSS.

Edit: I realize that the latter solution wouldn't necessarily be too painful, if you're using the omni-selector to reset everything to a baseline:

#myid * {
    somestyle1: default;
    somestyle2: default;
    ... 
}

I've found someone who has written up such a solution. If you scroll down far enough on the page, you'll see it (from SuzyUK). It doesn't look complete, but is a good start for sure.

(I, too, would be interested to know if there's a good way to prevent this. I've written Greasemonkey scripts before that injects code onto the page, and have had to write CSS to override the page's CSS, but in those cases I knew who my target was and could tailor my CSS directly towards the page.)

OTHER TIPS

Wrap your injected HTML with a specifically-classed <div>, such as

<div class="my-super-specialized-unique-wrapper"><!--contents--></div>

Then in your CSS, prefix all rules with .my-super-specialized-unique-wrapper and use !important on every rule. That will instruct the client browser to treat your rule as supreme for any elements which match, regardless of any other styles that might target them - even if other rules outside your control are more-specific.

Why not injecting html elements with inline formatting like this:

<p style="color:red">This to be injected</p>

inline styling takes precedence over any other rule, and you're already creating the markup in order to insert it.

Other solution would be to use very specific DOM id's on your elements and then styling them on your added CSS

You'll just have to be very specific with your CSS selectors. That is, much more specific than the host page's CSS rules. You might also want to add a kind of global CSS reset modified to only reset your HTML. By that, I mean something which resets all colours, backgrounds, fonts, padding, etc, back to a single standard. From there you can build up your own styles.

If you're using a Mozilla browser you can actually (if illegally) add visible DOM content to the <html> element outside the <body> element. This will avoid any styles that match on body and are inherited by your content. It may be possible that some styles match on html, which would defeat this technique, but I've found it useful.

eg. using jquery: $('html').append('<div id="mycontent"> blah blah blah </div>');

Using a popular library is itself a challenge when you don't want your instance of the library to interfere with the uses of the library defined by the pages you're modifying. Greasemonkey's '@require' didn't work for me. I found it necessary (but possible!) to save any existing values of the two or three global names assigned by the jquery script, insert my instance of the library into the DOM, wait for it to be loaded (had to use a timer, that's annoying but I couldn't see a way around it), cache the values assigned to the globals within my own namespace for my own use, and restore the saved ones.

I'm not sure how should it be used, of the browser support for this, but it is one of the main causes to use http://www.w3.org/TR/shadow-dom/

The idea is that you could insert a web-component, that can be fully styled and have specific events that only affect the shadow-DOM (so your module will not affect the rest of the page).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top