There is a third option worth discussing and rejecting, which is to reset all the style properties of the div and its descendents to its default value. Pseudo-code:
#my-div, #my-div * {
@for-every-css-property {
%propertyName: initial !important;
}
}
This answer shows an attempt at such a solution. It uses specific values instead of initial
which will work in older browsers without the initial
keyword, but will not correctly reset elements which have a different default from the base (e.g. user566245 mentions that textarea
elements should have a border).
Issues:
- Unfortunately initial is not actually the browser's default value.
- If we don't use
!important
above then there is a risk that the page might have provided a rule with a more specific elector which overrides our own. For example if the page specified properties for table > tr > td
then this would be applied over our rule because that selector is more specific than #my-div *
.
- Since we do use
!important
, any custom styling we want to do after the reset must also use !important
on every property.
- If the page happens to inject any additional CSS styles after ours that uses
!important
then these can override our reset.
- It is rather inefficient. We are asking the browser to apply a huge bunch of CSS rules to every element under our div.
- Vendor-specific properties should also be reset. (E.g.
-webkit-animation-name
.)
- If new CSS properties come into existence in future, you will need to update your list.
Whilst this solution can be applied to current browsers, it is rather horrible, so roll on Shadow DOM! I would recommend the <iframe>
solution in the meantime.
I don't know if anyone has tried this, but a more efficient solution might be to use Javascript to detect what site-defined CSS properties could be problematic, and reset only those.