How To Isolate a div from public CSS styles? - html

i have some code for example here in html
<html>
<body>
<img src='an image source'/>
<h1>Hi it's test</h1>
<div id='mydiv'>
<img src='an image source'/>
<h1>Hi it's test</h1>
</div>
</body>
</html>
if i used the following css code for styling it:
img{
width:100px;
height:100px;
}
h1{
font-size:26px;
color:red;
}
the question is : How can i prevent and isolate the tags inside the mydiv div tag from styling by the public tags style ?

CSS Cascading and Inheritance Level 3 introduces the all shorthand property and the unset keyword, which, together, allow you to achieve this conveniently.
For example, if an author specifies all: initial on an element it will
block all inheritance and reset all properties, as if no rules
appeared in the author, user, or user-agent levels of the cascade.
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.
Note, however, that any "default" style applied to that element (such
as, e.g. display: block from the UA style sheet on block elements such
as <div>) will also be blown away.
You’ll need to apply all: initial to your div and all: unset to its descendants:
#mydiv {
all: initial; /* blocking inheritance for all properties */
}
#mydiv * {
all: unset; /* allowing inheritance within #mydiv */
}
You may want to use a class on your div instead of an id, so that any rules you write to style its descendants won’t have to match or beat the high specificity used in this rule.
To be really safe, you may want to block styles on potential pseudo-element descendants too:
#mydiv::before,
#mydiv::after,
#mydiv *::before,
#mydiv *::after {
all: unset;
}
Alternatively, for broader browser support, you can manually attempt to do what all does by setting all known CSS properties (don’t forget the prefixed versions):
#mydiv {
/*
* using initial for all properties
* to totally block inheritance
*/
align-content: initial;
align-items: initial;
align-self: initial;
alignment-baseline: initial;
animation: initial;
backface-visibility: initial;
background: initial;
...
}
#mydiv::before,
#mydiv::after,
#mydiv *,
#mydiv *::before,
#mydiv *::after {
/*
* using inherit for normally heritable properties,
* and initial for the others, as unset does
*/
align-content: initial;
align-items: initial;
align-self: initial;
...
color: inherit;
...
}
You can encourage browser support for the all shorthand property and track its adoption with these issue links:
☑ Chrome 37+
☑ Firefox 27+
☑ Webkit (Safari 9.1+)
☐ Internet Explorer
☑ Edge 79+
☑ Opera 24+
Up-to-date browser support information for the all shorthand property is available here.

Old question, but things have changed a little bit since the accepted answer. There is now a CSSWG-recommended keyword called revert which would be better suited than initial and unset to solve this problem, as it resets properties to what they're defined to in the user agent stylesheet, rather than to their initial value (which has no regard for which element they're used on). So for instance, with revert, a div inside #mydiv will have its display set to block as we would expect and not inline (the initial value of display).
You'd have to do this:
#mydiv,
#mydiv::before,
#mydiv::after,
#mydiv *
#mydiv *::before,
#mydiv *::after {
all: revert;
}
At the time of writing, revert is supported in Edge, Firefox, Chrome, and Safari, but not IE or Opera.
There is also something else to take into consideration regarding the accepted answer. If you want to style anything inside #mydiv, you need to do so with a selector that is at least as specific as the one you used to unset or revert everything, otherwise it will be overridden by that rule, even if it comes after it in the CSS.
So you'd need to do something like this (note the #mydiv which boost the specificity of the rules):
#mydiv p {
margin-top: 20px;
}
#mydiv .bg-black {
background-color: black;
}
// etc.

You cannot technically, that's how CSS is suppose to work. If there is any style defined for
div tag in your style sheet it will be applied to all div elements.
Few things that you can try is don't style with tag name instead give class name and give style declaration to class. so that you can make sure where all styles will go.
OR. if you want some specific Div tag to not have the style while other Divs to have. you can always reset it give some different class name or id and reset the style declarations

iframe is also a decent solution for isolation of styles if it doesn't complicate other business logic. Plus this can be done in pure JavaScript and may work in older browsers too.
const HTMLToIsolate = `...` // get your div tag as HTML string
const parentContainerRef = document.body; // or something else
const newIframe = document.createElement('iframe');
// set height & width to 100% and remove borders for newIframe
parentContainerRef.appendChild(newIframe)
newIframe.contentWindow.document.open('text/html', 'replace');
newIframe.contentWindow.document.write(HTMLToIsolate);
newIframe.contentWindow.document.close();
// bonus to remove scroll bars by setting proper iframe's height
newIframe.addEventListener('load', function onIFrameLoad(e) {
const iframeBody = this.contentDocument.querySelector("body");
this.style.height = `${iframeBody.scrollHeight}px`;
});
This worked perfectly for me when I had to embed a complex HTML file into my webpage fetched remotely without MixedContent warning and without parent HTML styles overriding the embedded HTML. Thanks to https://benfrain.com/sandbox-local-htmlcss-code-snippets-inside-iframe-style-guidespattern-libraries/ for this excellent idea!
Though #mydiv * { all: unset } CSS trick, as suggested in the accepted solution here works, it ended being a complex browser operation as there were many DOM nodes on my page.

One thing that might be helpful is the CSS direct child selector, which is available in all browsers including IE7+. That lets you apply styling that doesn't cascade down into children. For example in your code you could use this CSS:
body > img {
width:100px;
height:100px;
}
body > h1 {
font-size:26px;
color:red;
}
And that CSS would only apply to elements directly on the BODY element.

Related

Override a CSS rule (needs to be delete)

I do not have access to the HTML file and we use a CDN for jQuery (so assume I don't have access to that as well).
How do I go about "deleting" a rule using my own custom CSS? I am attaching a picture with the CSS rule I want deleted.
This is how it looks:
This is how I want it to look:
If you just want the background-position to have no effect on the position of the image, use this:
.ui-icon-radio-off {
background-position: 0 0;
}
But if you want to reset it to what it was supposed to be set to if that default jquery css wasn't there, then you can unset it like this:
.ui-icon-radio-off {
background-position: initial;
}
N.B. You mgiht have to add an !important tag to the above properties if jquery renders the css property below the above property.
Some browsers accept the all CSS definition. What it does it resets or reverts all the CSS definition for all elements matching the CSS selector.
.my-class {
all: none;
}
Here is an good example from https://stackoverflow.com/a/31317986/3856582
#someselector {
all: initial;
* {
all: unset;
}
}
Or use the CSS initial keyword on any CSS definition.

Is it possible to apply a CSS style ONLY if a child class is present?

I'm using AngularJS and Cordova (ionic) in a mobile application project, and everything uses the same page perse. Everything is loaded into a single index.html file, so the body, html, ion-view, ion-content elements are all shared between each "page"/"interface"
Basically, all of my interfaces are set up with a unique identifier:
<ion-content id="interface-name">...</ion-content>
However, in this interface I need to make sure that the following elements have the following styles:
html, body, ion-view, ion-content, .scroll {
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
}
So that the interface can be fullscreen. This is all fine and dandy, but it's causing issues for my other interfaces not being able to scroll/expand vertically.
Is there a way (using CSS) to only apply a style if a child id/class is present, for example the above style is only applied if id="interface-name" is applied to a child element?
No. That's the "cascading" part of Cascading Style Sheets. It's a top down approach and you can't go back up the stream.
There is a relatively new pseudo-class :has() that allows you to only apply css to an element, if a specific child (or children) is present.
Link to the mdn web docs
For example, you can apply a selector to an element of the class .list only, of a child with the class .list-item is present:
.list:has(.list-item) {
display: block;
}
However, this feature is relatively new, and not all common browsers support that css selector yet: see the browser-compatibility
If you want your code above to work on ID/class, for example apply only to id="interface-name"
#interface-name {
height: 100%;
overflow: hidden;
margin: 0;
padding: 0;
}
You could do it with a JavaScript function at page load time, but you can't apply CSS rules conditionally on the existence of child elements. Something simple like
var parent = document.getElementById("elementId").childNodes;
var children = parent.childNodes;
for(child in children) {
if(child.id == "theIdYouAreLookingFor") {
parent.style.height = "100%";
// set other CSS rules here
// ...
break; // we're done, no need to check other children
}
}

Is there a way to change the whole document with one selector in CSS?

I am trying to change the font for the whole page in HTML. By whole I mean everything: buttons, forms, etc. Is there a way to do this in CSS?
html {
color: green;
}
This would make the text green, but not the text of buttons.
Well, there's universal selector:
* {
color: green;
}
Take note, though, that specificity of this selector is the lowest (MDN).
Wild card selector
* {
color: green;
}
It may be the case that you need to over ride inline CSS and javascript generated CSS. In this case use !important as well
* {
color: green !important;
}
Use the * universal CSS selector.
The universal selector matches any element type. It can be implied (and therefore omitted) if it isn’t the only component of the simple selector.
The selector div * will match the following em elements:
"Universal" in the h1 element ( matches the <h1> )
"emphasize" in the p element ( matches the <p> )
"not” in the first li element (matches the <ul> or the <li>)
"type” in the second li element (matches the <ul> or the <li>)
Example:
This rule set will be applied to every element in a document:
* {
color: green;
}
Also to add, it's compatible with most browsers, although it can be buggy in Internet Explorer 5.5, 6.0, 7.0.
If you don't need to support IE < 8, and want something that's less smelly, set an explicit color only on html and force everything else to inherit the color. Colors are already inherited by default on most elements, but not all of them.
Since this means applying two different color declarations, you will need two separate rules:
html {
color: green;
}
body * {
color: inherit !important;
}
Honestly, you shouldn't rely on a wildcard selector for doing this. You should take advantage of CSS's native inheritance. The best thing to do would be to remove the specific color declarations from your stylesheet (as needed) and add the color to your body or html tag. Using a wildcard is similar to this, except you are declaring that every single element should have the CSS as apposed to the native inheritance.

CSS: reset styles defined in an untouchable stylesheet

I need a simple <hr/> in a page that extends a default one (I'm using Django template framework); in this default page, a standard and untouchable stylesheet styles HR with border:none; height:1px but I would like to reset these styles to their default values.
I tried putting {border:1px inset; height:auto;} in my page but I didn't get the same aspect as having no style at all.
Is there a method to restore the default style for a tag?
In order to make your rule apply, you'll need to ensure that you give your rule a greater specificity than the existing rule in order to override it.
For example, if the rule is this:
hr {
/* rules */
}
Then you would need to do something like this:
html hr {
/* your rules */
}
Scores are calculated by these basic rules:
elements, like div are worth one point
classes, like .comment are worth 10 points
ids, like #user123 are worth 100 points
The total score for the selector is the sum of all of its parts, so div.class is worth 11 (10 for the .class and 1 for div
(It's actually a bit more complicated than this - see this article for details - but this explanation works as a general rule)
Edit:
I just saw your comment about not knowing the defaults.
According to Firebug, an hr appears to look like this:
hr {
height: 0;
width: 100%;
border: 1px solid #808080;
margin: 8px 0;
}
You can use the tools provided in other browsers to see if they use a different set of styles, then decide for yourself which ones would be the best ones to use.
Try YUI 2 Base CSS, seems to be doing what you want. Or even YUI 3 Base CSS
There is a possibility to "restore" default styles only for a certain context
Update
Just checked - Base CSS does not include styles for hr element
The default stylesheet for HTML documents, without any overrides, is defined by the W3C. You can find the full default stylesheet here: http://www.w3.org/TR/CSS2/sample.html
Alternatively, you could use Firebug in Firefox (or any similar tool) to view the styles of an <hr /> element on a test page without any styles applied.
Sure, you need to give your styles a bigger weight; add an id to your < hr/>, or do this in CSS:
html body hr { ... your styles ... }
No. You either have to not apply the styles in the first place, or override every broken style with explicit values.
You can also give your styles more weight with the !important property. If the original is like this:
.someClass { color: red }
You can override it with this:
.someClass { color: green !important}

How to stop Injected HTML-div / CSS from inheriting styles ? (Internet Explorer)

I am creating a extension for Internet Explorer where I am injecting CSS-styled span tags on webpages. If a specific part of this component is clicked on, a popup is shown.
This popup is in reality a "DIV"-element that I am injecting at the very end of the content page:s "BODY"-tag. I have a CSS-styled table inside this div, and depending on which site I am on, the appearance of this popup is either according to specification (in regards to width, and so on), or not.
I don't have that much knowledge when it comes to CSS and such, but can this be because the "parent" page already has some CSS for "BODY", "DIV", or "TABLE"-elements that is being inherited by my elements?
If this is the case, is there any way of stopping this?
There are (at least) two means of doing this1, but they're both a little messy.
Use an iframe with its own css (this way the pages are separated by being two entirely different web-pages).
Use increased specificity to target the inserted html elements.
body {
/* targets the 'body', and these styles are inherited by its descendant elements */
}
body div {
/* targets all divs that are contained within the 'body' element */
}
body > div {
/* targets only divs that are directly contained within the body element */
/* and these styles will/may be inherited by the children of these divs */
}
The problem with this latter approach, is that you're having to explicitly specify almost all the possible permutations. And there will always be edge cases that aren't accounted for. You'd be best off using class-names to specify the styles for the new content:
.insertedDiv {
/* this will apply to all elements of class 'insertedDiv', but may be overridden */
/* by a more specific id-based selector such as '#container > .insertedDiv' */
But I can only think of these two at the moment.
CSS naturally "cascades", meaning if a container element has a property, it's children will by default inherit it. You can however, of course, override the value on the more specific items by redefining the style for them.
You'll need to inject CSS along with the HTML which specifies all the necessary properties for your popup. Unlike most CSS, you won't be able to assume any defaults, you'll need to specify for your div anything which might be overrode by the page. Make sure you refer to the div specifically by id in your CSS to ensure that your styles override that of the page, and that you don't inadvertently mess with the page's formatting.
You should start with a css reset stylesheet. But it has to be modified to only affect your html. So if you wrap your html in a div with a id like "23d4o829" you can use edit each rule in your reset style sheet so it only affects html that is within that div.
For example,
html, body { /* some stuff */ }
table { /* more stuff */ }
becomes
html #23d4o829, body #23d4o829 { /* some stuff */ }
#23d4o829 table { /* more stuff */ }
and so on. After that, you can have all the css rules you need to control your appearance.
EDIT: I think using iFrames as mentioned by David Thomas is better.