How to constrain the scope of inline CSS? - javascript

I'm rendering dynamic CSS for each item in a list. Each item will have potentially unique CSS rules for its elements, i.e.
<div id="thing1" class="vegas">
<style>
p {
font-size: 14pt; // this stuff is generated dynamically and i have no control over it
color: green;
}
</style>
<p>
I'm thing 1!
</p>
</div>
<div id="thing2" class="vegas" >
<style>
p {
font-size: 9pt; // so is this stuff
color: red;
}
</style>
<p>
I'm thing 2!
</p>
</div>
Is there a way to wrap each item in a general CSS rule that would limit the scope of each item's associated CSS to the item itself? Like
.vegas > * {
whatever-happens-in-here: stays in here;
}
Or any other way to handle scoping who-knows-what kinds of dynamically particular CSS?

The cascading style sheets are able to handle styling children of particular elements, so:
div#thing1 p {
rule: value; // Only applies to p in div with id="thing1"
}
div#thing2 p {
rule: value; // Only applies to p in div with id="thing2"
}

You need to know about the global styles that browsers have. For eg., find the below list:
font-family
line-height
text-align
The above have their default value as inherit, which means they get the property values from their parent, no matter what. So if you change the parent's property, your child also gets changed.
And you have other properties like:
margin
padding
border
width
height
These do not change, or inherit from the parent. So, if you wanna do something like what you wanted, you need to give your descendants, or immediate children, not to inherit or reset the styles for the children.

Why don't you use inline style attribute?
<p style="color:red;align:center"> Hello </p>
The above CSS style will only be applied to that particular paragraph tag.
You could use inline style statement for other tags and HTML elements too.
Or you could include an external common stylesheet and use the inline statements where you need a variation.CSS applies the latest style description it comes across.So the inline statements would over-ride the common css stylesheet effects.

Related

why are initial CSS styles not visible on DOM element.style field?

OK I have full expectation of going down in flames for asking something stupid (or at least duplicate), but in the attached snippet, why do I have to use window.getComputedStyle to access styles applied by CSS? I was under the impression that the .style field would at least reflect those styles initially applied by CSS, and/or manually changed since then.
If not, what are the exact rules governing which properties are reflected (and when) in an element's .style field?
setTimeout(() => {
console.log("the bckg color:", reddish.style.backgroundColor);
console.log("the width:", reddish.style.width);
console.log("from a computed style:", window.getComputedStyle(reddish).backgroundColor);
console.log("from a computed style:", window.getComputedStyle(reddish).width);
}, 100);
#reddish {
background-color: #fa5;
width: 100px;
height: 100px;
}
<html>
<body>
<div id="reddish"></div>
</body>
</html>
The HTMLElement.style property is not useful for completely
learning about the styles applied on the element, since it represents
only the CSS declarations set in the element's inline style
attribute, not those that come from style rules elsewhere, such as
style rules in the section, or external style sheets. To get
the values of all CSS properties for an element you should use
Window.getComputedStyle() instead.
Via- MDN Web Docs | Getting Style
Information
HTMLElement.style:
The HTMLElement.style property is used to get as well as set the inline style of an element.
console.log(document.getElementById("para").style.fontSize); // will work since the "font-size" property is set inline
console.log(document.getElementById("para").style.color); // will not work since the "color" property is not set inline
#para {color: rgb(34, 34, 34);}
<p id="para" style="font-size: 20px;">Hello</p>
Window.getComputedStyle():
The getComputedStyle() method however, returns an object containing the values of all CSS properties of an element, after applying active stylesheets and resolving any basic computation those values may contain thus returning the css properties from both inline style declarations as well as from external style-sheets.
console.log(window.getComputedStyle(document.getElementById("para")).fontSize); // will work
console.log(window.getComputedStyle(document.getElementById("para")).color); // will work
#para {
color: rgb(34, 34, 34);
}
<p id="para" style="font-size: 20px;">Hello</p>
HTMLElement.style is for the inline style of an element. It does not take into account CSS whatsoever. This is basically just directly setting or getting a property on the element object.
<div style="color: red;">Hello</div>
Window.getComputedStyle() takes into account inline styles and CSS, after resolving cascading, inheritance, etc. It's basically the "final" actual style value used to render the element on the page.
// CSS
#blue-text {
color: blue !important;
}
// HTML
<div style="color: red;" id="blue-text">Hello</div>
// JS
const myElement = document.querySelector("#blue-text");
myElement.style.color; // "red" because that's the inline style
window.getComputedStyle(myElement).color; // "rgb(0, 0, 255)" because CSS !important overrides inline style

Apply CSS styles to Light DOM (shadow DOM) in custom element HTML5

I have read all the documentation about web components and according to the standards it is not possible to apply isolated CSS styles (shadow) to the elements that the user enters inside a custom element (light DOM), that is, the content that the user adds within a slot element, an example below:
 
<! - Custom element ->
    <index-book>
     <slot>
       <! - Light DOM here / This content was introduced by the user ->
       <div class = "container">
         <span class = "section"> Section title ... </ span>
         <ul class = "sections">
           <li> ... </ li>
           <li> ... </ li>
           <li> ... </ li>
         </ ul>
       </ div>
     </ slot>
    </ index-book>
In fact, making use of the pseudo-element class of CSS ::slotted () could apply styles only to the first direct child of the slot element, that is, to div.container, but not to its children.
I have reached two conclusions, or if you can apply Shadow styles to the entire structure of elements of the DOM light and I do not know how, or the second option is that the user should not be allowed to enter content into a slot that has multi -level as in the previous example, div within div ...
If the correct answer is the second one, how should I do so that the user inserts content within the custom element and the final result is the same or similar to the example shown above (trying to create a custom book index element) and can apply isolated styles in the DOM tree of the custom element.
I must mention that I am not using Polymer or any other library to develop this custom element.
Thank you very much!
According to web fundamentals:
<name-badge>
<h2>Eric Bidelman</h2>
<span class="title">
Digital Jedi, <span class="company">Google</span>
</span>
</name-badge>
<style>
::slotted(h2) {
margin: 0;
font-weight: 300;
color: red;
}
::slotted(.title) {
color: orange;
}
/* DOESN'T WORK (can only select top-level nodes).
::slotted(.company),
::slotted(.title .company) {
text-transform: uppercase;
}
*/
</style>
<slot></slot>
So I guess you're out of luck here.
However if it's light dom maybe you could style it directly or wrap it in another custom element?
Why not use use normal CSS, that is bundled with your web component file, but applies to the normal dom instead of the shadowDOM, e.g.
<style>
index-book.container {
color: red;
}
index-book.sections{
color: blue;
}
/* or */
index-book > div {
color: red;
}
</style>
Since these styles beging with the custom web component name, they will not apply to any other elements

TinyMCE and multiple CSS selectors on the parent css file handling

I got a problem with TinyMCE when it comes to parent site CSS selectors.
My TinyMCE opens an iframe. I add the parent css to the tinyMCE via content_css property, no problem from there.
Now imagine that i got a css style like this:
.mysite.default .content h1 {
...
}
.mysite.default .info h4 {
}
The problem comes when i want to access to .content h1 or .info h4.
As by default, by adding to the body the class .mysite.default, if you got an h1 or h4, those won't be applied of course due to the selector .content and .info in the middle.
So inside the iframe's body i would be able to set styles only for
.mysite.default h1 { ... }
.mysite.default h4 { ... }
Is there a good strategy to have this kind of flexibility?
Problem is that I don't have only one h1 or h4 or span styling, I may got many of them, that's why I need a flexible selector strategy for this...
I can't just copy all the styles of the parent dynamically at runtime, because what if one of the parent selectors has a border, margins, padding (because it might be a parent div wrapper container with some unique styling) ?
So it's not that easy as saying, "hey add every parent style and that's all", because the child will have extra borders, extra margins when starting to edit that div.
If I understand you correctly, you should be able to use
.mysite.default * h1 { ... }
to select all h1s inside other tags: the * wildcard covers any wrapping tag/class/id.
Hope that is helpful...!

Remove CSS style rules from a single HTML element programatically

I want to add some HTML elements in my document that has no style at all. But I need to assure that these elements will not look differently regardless of project, webpage or anything else really. These elements will be inserted in the page by Javascript and will be SPAN.
My idea is to add SPANs to style snippets of text in the document. But some style might have been added to SPAN elements before and that will change the result I am expecting.
So let's assume I'm writing a Widget and any of you could be using it in your own webpages. This is why I can't do much to change the elements' style directly, like changing the stylesheets directly. The solution must be achieved by Javascript. JQuery is not wanted.
<head>
<style>
span{
font-weight: bold;
/*anything else goes below*/
}
</style>
</head>
<body>
<span class='a_regular_span'>This text must be bold and anything else</span>
<span>This text must have only the CSS rules I applied by Javascript, and must not inherit the rules for all SPANs in the page</span>
</body>
Any ideas?
So let's assume I'm writing a Widget and any of you could be using it
in your own webpages. This is why I can't do much to change the
elements' style directly
You could use a style element with scoped attribute. This way you can style only your elements, without affecting other parts of the page.
But be aware that old browsers don't support it.
And if you don't want page's styles to affect your elements, see How can I prevent CSS from affecting certain element?
If you really wish to separate the style of your elements from that of the other elements on the page, you could use a custom tag to do this.
For example, instead of using span, you could use customspan and style those elements any way you like.
<head>
<style>
span{
font-weight: bold;
/*anything else goes below*/
}
</style>
</head>
<body>
<span class='a_regular_span'>This text must be bold and anything else</span>
<customspan>This text must have only the CSS rules I applied by Javascript, and must not inherit the rules for all SPANs in the page</customspan>
</body>
can u try this?
<style>
span{
font-weight: bold;
/*anything else goes below*/
} .a_regular_span span{ font-weight: normal;
/*anything else goes below*/
}
</style>

conflict between the same class or id of multiple css files

Is there any way to stop the conflict between same class or id of multiple css files. As I am explaining below for better understanding:
There is a master web page which has several <div> but there is a <div class"dynamic"> which always reload the contents including css files. Let's suppose if any class of master page has the same name to reloaded elements' class while properties are different. Then how should I handle this to stop the conflict.
master.html
<html>
<head> //attached master.css file here </head>
<body>
<div class="myClass"> </div>
<div class="dynamic"> /* often reload elements by ajax */ </div>
</body>
</html>
master.css
.myClass { height: 100px; width: 150px; background : red;}
.dynamic { height: 200p; width: 200px; }
now i am showing the reloaded html elements & css files into dynamic div of master page
reloaded tag line by ajax : <div class"myClass"> </div>
reload.css
.myClass{height: 30px; width: 25px; background: yellow; }
Now as you can see there are two classes with same name but different properties. Then how should I stop the confliction?
#Edit Thanks everyone for your support & time but my problem is different here.
the dynamic reloaded contents & css files are streaming from the client/user machine while master html page & it's css streaing directly from server.
so whatever the contents loads in dynamic div, it's coming from client side (e.g. tag lines & css, js). in that case i am not able to handle the css file which is just reloaded by ajax() so i think it can be sort out using js/jQuery fn().
You could apply the cascading rules of the CSS:
In your case, div.myClass inside div.dynamic should override div.myClass belongs to the body.
you adjust the reload.css rules to
.dynamic .myClass{height: 30px; width: 25px; background: yellow; }
The cascading rules which are applied when determine which rules should apply to html div could be referenced here
Updated 11.23
As the OP only have control over master.css, the above solution won't work. Thus, I suggest use child selector to limit the CSS rules to only the outer div.myClass. Modify the rule in your master.css to:
body > .myClass {...}
This rule will only apply to the .myClass which is the child of body. It leaves the spaces of styling for inner .myClass div.
Option 1: A more specific selector
.dynamic .myClass { }
This selector selects the .myClass element that is a descendent of .dynamic.
.dynamic > .myClass { }
This selector selects the .myClass element that is a direct child of .dynamic.
Option 2: Inline CSS
<div class="dynamic">
<div class="myClass" style="background-color: yellow;"></div>
</div>
Option 3: Use a different class.
UPDATE
If you want to avoid the previous defined property to be overwritten by a later defined value, you can use the !important syntax.
.myClass { background-color: red !important; } /* Sets the property to red */
.myClass { background-color: yellow; } /* Property is NOT overwritten */
If I understand your question correctly, this should sort it.
So you should add !important to the properties that seem to be overwritten.
div.myclass { ble ble }
div.main div.myclass { ble ble }
<body>
<div class="myclass"></div>
<div class="main><div class="myclass"></div></div>
</body>
Whichever css class of the same name is loaded last will overwrite anything set by the earlier class. However, if you use an inline style attribute this will always take precedence over anything set by the css file (so using an inline style is one option).
You could also use different style names or clarify your style with tag names div.myClass or id's #myDiv.myClass.

Categories

Resources