1

I'm developing a Chrome Extension, an HTML subtree and a CSS style sheet are injected into the original page. I want the injected HTML subtree not to be affected by the original CSS, but I have no idea about how to finish the job perfectly. The problem:

<!DOCTYPE html>

<style>

/* original CSS */
input[type="text"] {
    background: green;
}

input[type="text"]:focus {
    background: yellow;
}

/* my injected CSS somewhere else */
.injected-root input[type="text"] {
    border: solid 1px navy;
}
</style>

<input type="text" value="original text">
<div class='injected-root'>
    <input type="text" value="injected text">
</div>

The original page is a random page on the internet, so it's impossible to know what the original CSS would be. As you can see from the code above, my injected text input is affected by the original CSS, I know it can be fixed by override the original CSS with new default values:

.injected-root input[type="text"] {
    border: solid 1px navy;
    background: white;
}

.injected-root input[type="text"]:focus {
    background: white;
}

But I don't think it's feasible to do it "manually" by supply every default attribute.

So, the question is:

  • Is there a way to reset the style of a subtree completely?

or

  • Any other strategy to make the subtree seems in an "isolated universe" (only affected by its own injected CSS)?
Liang Zhao
  • 145
  • 3
  • 14
  • 1. No 2. What I can think of is iframe... – Jimmy Ko Jul 01 '16 at 13:49
  • See [How can I prevent CSS from affecting certain element?](http://stackoverflow.com/q/17407424/1529630) – Oriol Jul 01 '16 at 13:51
  • 1
    I never used it, but it seems like you can achieve it with Shadow Dom: http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/ Since it's a Chrome extension, you don't have to worry about other browsers' support – Jav Rok Jul 01 '16 at 13:53
  • I also found a related question [How to really isolate stylesheets in the Google Chrome extension?](http://stackoverflow.com/questions/12783217/how-to-really-isolate-stylesheets-in-the-google-chrome-extension) – Liang Zhao Jul 02 '16 at 03:31

2 Answers2

1

A) Yes, you can reset styles for a “subtree” of the DOM, but this would mean to override ALL styles of ALL elements when they are nested inside .injected-root. As you can't know with which specificity the original styles were applied, you probably have to use !important only to reset the original styles. This will lead you into the !important-hell when applying styles to your own elements.

B) Yes, the better solution would be to provide a web component and use the shadow DOM to insert elements and apply styles.

See:

feeela
  • 29,399
  • 7
  • 59
  • 71
  • You could wrap all selectors within a root selector with ID specificity though. Even though your root sub-dom element doesn't have an ID. This would at least ensure your styles have a better chance to have higher specificity that anything above them. See [CSS class selector with ID specificity](https://erraticdev.blogspot.com/2018/11/css-class-selector-with-id-specificity.html) – Robert Koritnik Nov 15 '18 at 08:55
1

While an <iframe> is probably the most universal way, there is a new attribute in CSS3 which will eventually allow this. The all attribute allows controlling inheritance of all CSS attributes. Unfortunately, browser support is not yet universal, but since it sounds like you're targeting Chrome, perhaps that doesn't matter.

The rule you would want is:

.injected-root {all: initial;}

Example: http://codepen.io/anon/pen/pbPKby

Dark Falcon
  • 43,592
  • 5
  • 83
  • 98
  • _This can be useful for the root element of a "widget" included in a page, which does not wish to inherit the styles of the outer page._, from the [link](https://www.w3.org/TR/css3-cascade/#all-shorthand) you provided, great. But it can not reset -webkit-* I suppose. – Liang Zhao Jul 02 '16 at 02:52
  • Why would it not? Do you have a specific example? – Dark Falcon Jul 04 '16 at 13:04