access a set of seclectors with :before using javascript [duplicate] - javascript

This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
How to update placeholder color using Javascript?
(5 answers)
Closed 2 years ago.
Is it possible to change a CSS pseudo-element style via JavaScript?
For example, I want to dynamically set the color of the scrollbar like so:
document.querySelector("#editor::-webkit-scrollbar-thumb:vertical").style.background = localStorage.getItem("Color");
and I also want to be able to tell the scrollbar to hide like so:
document.querySelector("#editor::-webkit-scrollbar").style.visibility = "hidden";
Both of these scripts, however, return:
Uncaught TypeError: Cannot read property 'style' of null
Is there some other way of going about this?
Cross-browser interoperability is not important, I just need it to work in webkit browsers.

If you're comfortable with some graceful degradation in older browsers you can use CSS Vars. Definitely the easiest of the methods I've seen here and elsewhere.
So in your CSS you can write:
#editor {
--scrollbar-background: #ccc;
}
#editor::-webkit-scrollbar-thumb:vertical {
/* Fallback */
background-color: #ccc;
/* Dynamic value */
background-color: var(--scrollbar-background);
}
Then in your JS you can manipulate that value on the #editor element:
document.getElementById("#editor").style.setProperty('--scrollbar-background', localStorage.getItem("Color"));
Lots of other examples of manipulating CSS vars with JS here: https://eager.io/blog/communicating-between-javascript-and-css-with-css-variables/

To edit an existing one which you don't have a direct reference to requires iterating all style sheets on the page and then iterating all rules in each and then string matching the selector.
Here's a reference to a method I posted for adding new CSS for pseudo-elements, the easy version where you're setting from js
Javascript set CSS :after styles
var addRule = (function (style) {
var sheet = document.head.appendChild(style).sheet;
return function (selector, css) {
var propText = typeof css === "string" ? css : Object.keys(css).map(function (p) {
return p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p]);
}).join(";");
sheet.insertRule(selector + "{" + propText + "}", sheet.cssRules.length);
};
})(document.createElement("style"));
addRule("p:before", {
display: "block",
width: "100px",
height: "100px",
background: "red",
"border-radius": "50%",
content: "''"
});
sheet.insertRule returns the index of the new rule which you can use to get a reference to it for it which can be used later to edit it.

EDIT: There is technically a way of directly changing CSS pseudo-element styles via JavaScript, as this answer describes, but the method provided here is preferable.
The closest to changing the style of a pseudo-element in JavaScript is adding and removing classes, then using the pseudo-element with those classes. An example to hide the scrollbar:
CSS
.hidden-scrollbar::-webkit-scrollbar {
visibility: hidden;
}
JavaScript
document.getElementById("editor").classList.add('hidden-scrollbar');
To later remove the same class, you could use:
document.getElementById("editor").classList.remove('hidden-scrollbar');

I changed the background of the ::selection pseudo-element by using CSS custom properties doing the following:
/*CSS Part*/
:root {
--selection-background: #000000;
}
#editor::selection {
background: var(--selection-background);
}
//JavaScript Part
document.documentElement.style.setProperty("--selection-background", "#A4CDFF");

You can't apply styles to psuedo-elements in JavaScript.
You can, however, append a <style> tag to the head of your document (or have a placeholding <style id='mystyles'> and change its content), which adjusts the styles. (This would work better than loading in another stylesheet, because embedded <style> tags have higher precedence than <link>'d ones, making sure you don't get cascading problems.
Alternatively, you could use different class names and have them defined with different psuedo-element styles in the original stylesheet.

I posted a question similar to, but not completely like, this question.
I found a way to retrieve and change styles for pseudo elements and asked what people thought of the method.
My question is at Retrieving or changing css rules for pseudo elements
Basically, you can get a style via a statement such as:
document.styleSheets[0].cssRules[0].style.backgroundColor
And change one with:
document.styleSheets[0].cssRules[0].style.backgroundColor = newColor;
You, of course, have to change the stylesheet and cssRules index. Read my question and the comments it drew.
I've found this works for pseudo elements as well as "regular" element/styles.

An old question, but one I came across when try to dynamically change the colour of the content of an element's :before selector.
The simplest solution I can think of is to use CSS variables, a solution not applicable when the question was asked:
"#editor::-webkit-scrollbar-thumb:vertical {
background: --editorScrollbarClr
}
Change the value in JavaScript:
document.body.style.setProperty(
'--editorScrollbarClr',
localStorage.getItem("Color")
);
The same can be done for other properties.

Looks like querySelector won't work with pseudo-classes/pseudo-elements, at least not those. The only thing I can think of is to dynamically add a stylesheet (or change an existing one) to do what you need.
Lots of good examples here:
How do I load css rules dynamically in Webkit (Safari/Chrome)?

Related

Set Property Value of Pseudo-Elements Using JavaScript [duplicate]

This question already has answers here:
Selecting and manipulating CSS pseudo-elements such as ::before and ::after using javascript (or jQuery)
(26 answers)
How to update placeholder color using Javascript?
(5 answers)
Closed 2 years ago.
Is it possible to change a CSS pseudo-element style via JavaScript?
For example, I want to dynamically set the color of the scrollbar like so:
document.querySelector("#editor::-webkit-scrollbar-thumb:vertical").style.background = localStorage.getItem("Color");
and I also want to be able to tell the scrollbar to hide like so:
document.querySelector("#editor::-webkit-scrollbar").style.visibility = "hidden";
Both of these scripts, however, return:
Uncaught TypeError: Cannot read property 'style' of null
Is there some other way of going about this?
Cross-browser interoperability is not important, I just need it to work in webkit browsers.
If you're comfortable with some graceful degradation in older browsers you can use CSS Vars. Definitely the easiest of the methods I've seen here and elsewhere.
So in your CSS you can write:
#editor {
--scrollbar-background: #ccc;
}
#editor::-webkit-scrollbar-thumb:vertical {
/* Fallback */
background-color: #ccc;
/* Dynamic value */
background-color: var(--scrollbar-background);
}
Then in your JS you can manipulate that value on the #editor element:
document.getElementById("#editor").style.setProperty('--scrollbar-background', localStorage.getItem("Color"));
Lots of other examples of manipulating CSS vars with JS here: https://eager.io/blog/communicating-between-javascript-and-css-with-css-variables/
To edit an existing one which you don't have a direct reference to requires iterating all style sheets on the page and then iterating all rules in each and then string matching the selector.
Here's a reference to a method I posted for adding new CSS for pseudo-elements, the easy version where you're setting from js
Javascript set CSS :after styles
var addRule = (function (style) {
var sheet = document.head.appendChild(style).sheet;
return function (selector, css) {
var propText = typeof css === "string" ? css : Object.keys(css).map(function (p) {
return p + ":" + (p === "content" ? "'" + css[p] + "'" : css[p]);
}).join(";");
sheet.insertRule(selector + "{" + propText + "}", sheet.cssRules.length);
};
})(document.createElement("style"));
addRule("p:before", {
display: "block",
width: "100px",
height: "100px",
background: "red",
"border-radius": "50%",
content: "''"
});
sheet.insertRule returns the index of the new rule which you can use to get a reference to it for it which can be used later to edit it.
EDIT: There is technically a way of directly changing CSS pseudo-element styles via JavaScript, as this answer describes, but the method provided here is preferable.
The closest to changing the style of a pseudo-element in JavaScript is adding and removing classes, then using the pseudo-element with those classes. An example to hide the scrollbar:
CSS
.hidden-scrollbar::-webkit-scrollbar {
visibility: hidden;
}
JavaScript
document.getElementById("editor").classList.add('hidden-scrollbar');
To later remove the same class, you could use:
document.getElementById("editor").classList.remove('hidden-scrollbar');
I changed the background of the ::selection pseudo-element by using CSS custom properties doing the following:
/*CSS Part*/
:root {
--selection-background: #000000;
}
#editor::selection {
background: var(--selection-background);
}
//JavaScript Part
document.documentElement.style.setProperty("--selection-background", "#A4CDFF");
You can't apply styles to psuedo-elements in JavaScript.
You can, however, append a <style> tag to the head of your document (or have a placeholding <style id='mystyles'> and change its content), which adjusts the styles. (This would work better than loading in another stylesheet, because embedded <style> tags have higher precedence than <link>'d ones, making sure you don't get cascading problems.
Alternatively, you could use different class names and have them defined with different psuedo-element styles in the original stylesheet.
I posted a question similar to, but not completely like, this question.
I found a way to retrieve and change styles for pseudo elements and asked what people thought of the method.
My question is at Retrieving or changing css rules for pseudo elements
Basically, you can get a style via a statement such as:
document.styleSheets[0].cssRules[0].style.backgroundColor
And change one with:
document.styleSheets[0].cssRules[0].style.backgroundColor = newColor;
You, of course, have to change the stylesheet and cssRules index. Read my question and the comments it drew.
I've found this works for pseudo elements as well as "regular" element/styles.
An old question, but one I came across when try to dynamically change the colour of the content of an element's :before selector.
The simplest solution I can think of is to use CSS variables, a solution not applicable when the question was asked:
"#editor::-webkit-scrollbar-thumb:vertical {
background: --editorScrollbarClr
}
Change the value in JavaScript:
document.body.style.setProperty(
'--editorScrollbarClr',
localStorage.getItem("Color")
);
The same can be done for other properties.
Looks like querySelector won't work with pseudo-classes/pseudo-elements, at least not those. The only thing I can think of is to dynamically add a stylesheet (or change an existing one) to do what you need.
Lots of good examples here:
How do I load css rules dynamically in Webkit (Safari/Chrome)?

How put style in a element javascript [duplicate]

How I can set a style of a:visited with JavaScript or jQuery. I know how to set with a regular link like
document.getElementById('a12').style.color = '#ff0000';
But I don't know how it works with a:visited?
Style properties adjust style attributes which apply to elements, they completely replace selectors
You have two choices.
Write your rule-sets in advance, and then design the element to match the selector.
e.g.
.foo:visited {
color: #f00;
}
document.getElementById('a12').className += ' foo';
Dynamically generate rule-sets with selectors that match the element.
See bobince's answer at Setting CSS pseudo-class rules from JavaScript

remove / reset inherited css from an element [duplicate]

This question already has answers here:
How to reset/remove CSS styles for a specific element or selector only
(17 answers)
Closed last month.
I know this question was asked before, but before marking it as a duplicate, I want to tell you that my situation is a little different from what I found on the internet.
I'm building and embedded script that people can put it on their sites. This script creates a div with a certain width/height and some information in it.
My problem is that some websites declare styles for div that are inherited by my div as well.
for example:
div{
background-color:red;
}
so if I don't set any background color to my div, it will show red even if I don't want that.
The only solutions I come along is to overwrite as many css proprieties, this way my div will show exactly as I want.
The problem with this solution is that there are too many css proprieties to overwrite and I want my script to be as light as it can be.
So my question is if you know another solution to my problem.
It can be in css/javascript /jQuery.
Thanks
"Resetting" styles for a specific element isn't possible, you'll have to overwrite all styles you don't want/need. If you do this with CSS directly or using JQuery to apply the styles (depends on what's easier for you, but I wouldn't recommend using JavaScript/JQuery for this, as it's completely unnecessary).
If your div is some kind of "widget" that can be included into other sites, you could try to wrap it into an iframe. This will "reset" the styles, because its content is another document, but maybe this affects how your widget works (or maybe breaks it completely) so this might not be possible in your case.
Only set the relevant / important CSS properties.
Example (only change the attributes which may cause your div to look completely different):
background: #FFF;
border: none;
color: #000;
display: block;
font: initial;
height: auto;
letter-spacing: normal;
line-height: normal;
margin: 0;
padding: 0;
text-transform: none;
visibility: visible;
width: auto;
word-spacing: normal;
z-index: auto;
Choose a very specific selector, such as div#donttouchme, <div id="donttouchme"></div>. Additionally, you can add `!important before every semicolon in the declaration. Your customers are deliberately trying to mess up your lay-out when this option fails.
You could try overwriting the CSS and use auto
I don't think this will work with color specifically, but I ran into an issue where i had a parent property such as
.parent {
left: 0px;
}
and then I was able to just define my child with something like
.child {
left: auto;
}
and it effectively "reset" the property.
Technically what you are looking for is the unset value in combination with the shorthand property all:
The unset CSS keyword resets a property to its inherited value if it inherits from its parent, and to its initial value if not. In other words, it behaves like the inherit keyword in the first case, and like the initial keyword in the second case. It can be applied to any CSS property, including the CSS shorthand all.
.customClass {
/* specific attribute */
color: unset;
}
.otherClass{
/* unset all attributes */
all: unset;
/* then set own attributes */
color: red;
}
You can use the initial value as well, this will default to the initial browser value.
.otherClass{
/* unset all attributes */
all: initial;
/* then set own attributes */
color: red;
}
As an alternative:
If possible it is probably good practice to encapsulate the class or id in a kind of namespace:
.namespace .customClass{
color: red;
}
<div class="namespace">
<div class="customClass"></div>
</div>
because of the specificity of the selector this will only influence your own classes
It is easier to accomplish this in "preprocessor scripting languages" like SASS with nesting capabilities:
.namespace{
.customClass{
color: red
}
}
Try this: Create a plain div without any style or content outside of the red div. Now you can use a loop over all styles of the plain div and assign then to your inner div to reset all styles.
Of course this doesn't work if someone assigns styles to all divs (i.e. without using a class. CSS would be div { ... }).
The usual solution for problems like this is to give your div a distinct class. That way, web designers of the sites can adjust the styling of your div to fit into the rest of the design.
As long as they are attributes like classes and ids you can remove them by javascript/jQuery class modifiers.
document.getElementById("MyElement").className = "";
There is no way to remove specific tag CSS other than overriding them (or using another element).
you may use this below option.
<style>
div:not(.no_common_style){
background-color:red;
}
</style>
now , if their any place where you do not want to apply default style you can use 'no_common_style' class as class.
ex:
<div class="no_common_style">
It will not display in red
</div>
From what I understand you want to use a div that inherits from no class but yours. As mentioned in the previous reply you cannot completely reset a div inheritance. However, what worked for me with that issue was to use another element - one that is not frequent and certainly not used in the current html page. A good example, is to use instead of then customize it to look just like your ideal would.
area { background-color : red; }
One simple approach would be to use the !important modifier in css, but this can be overridden in the same way from users.
Maybe a solution can be achieved with jquery by traversing the entire DOM to find your (re)defined classes and removing / forcing css styles.

Change CSS of class in Javascript?

I've got a class with the display set to none I'd like to in Javascript now set it to inline I'm aware I can do this with an id with getElementById but what's the cleanest way to do it with a class?
You can do that — actually change style rules related to a class — using the styleSheets array (MDN link), but frankly you're probably better off (as changelog said) having a separate style that defines the display: none and then removing that style from elements when you want them no longer hidden.
Do you mean something like this?
var elements = document.getElementsByClassName('hidden-class');
for (var i in elements) {
if (elements.hasOwnProperty(i)) {
elements[i].className = 'show-class';
}
}
Then the CSS
.hidden-class { display: none; }
.show-class { display: inline; }
You can use getElementsByClassName in which you'll get an array of elements. However this is not implemented in older browsers. In those cases getElementsByClassName is undefined so the code has to iterate through elements and check which ones have the desired class name.
For this you should use a javascript framework such as jQuery, mootools, prototype, etc.
In jQuery it could be done with a one-liner as this:
$('.theClassName').css('display', 'inline')
you can create new style rule instead.
var cssStyle = document.createElement('style');
cssStyle.type = 'text/css';
var rules = document.createTextNode(".YOU_CLASS_NAME{display:hidden}");
cssStyle.appendChild(rules);
document.getElementsByTagName("head")[0].appendChild(cssStyle);
$("#YOUR_DOM_ID").addClass("YOUR_CLASS_NAME");
You may like to exploit/rewrite this function:
function getStyleRule(ruleClass, property, cssFile) {
for (var s = 0; s < document.styleSheets.length; s++) {
var sheet = document.styleSheets[s];
if (sheet.href.endsWith(cssFile)) {
var rules = sheet.cssRules ? sheet.cssRules : sheet.rules;
if (rules == null) return null;
for (var i = 0; i < rules.length; i++) {
if (rules[i].selectorText == ruleClass) {
return rules[i].style[property];
//or rules[i].style["border"]="2px solid red";
//or rules[i].style["boxShadow"]="4px 4px 4px -2px rgba(0,0,0,0.5)";
}
}
}
}
return null;
}
to scan all style sheets attached pass "" as third argument, otherwise something like "index.css"
ruleClass contains starting '.'
if (rules[i].selectorText && rules[i].selectorText.split(',').indexOf(property) !== -1) condition improvement found here https://stackoverflow.com/a/16966533/881375
don't forget to use javascript syntax over css properties, e.g. box-shadow vs. boxShadow
Although this is long gone, here a few remarks:
Using display: inline to make things visible again may spoil the
page flow. Some elements are displayed inline, others block etc. This
should be preserved. Hence, only define a .hidden style and remove it
to make things visible again.
How to hide: There are (at least) two ways to hide elements, one is
the above mentioned display: none which basically makes the element
behave as if it was not there, and the visibility: hidden which
renders the element invisible but keeps the space it occupies.
Depending on what you want to hide, the visibility may be a better
choice, as other elements will not move when showing/hiding an
element.
Adding/removing classes vs. manipulating CSS rules: The result is
quite different. If you manipulate the CSS rules, all elements having
a certain CSS class are affected - now and in the future, i.e. new
elements dynamically added to the DOM are also hidden, whereas when
you add/remove a class, you must make sure that newly added elements
also have the class added/removed. So, I'd say adding/removing
classes works well for static HTML, whereas manipulating CSS rules
might be a better choice for dynamically created DOM elements.
To change CLASS you need to edit document stylesheets
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.display='inline';
[...document.styleSheets[0].cssRules].find(x=> x.selectorText=='.box')
.style.display='inline';
.box {
margin: 10px;
padding: 10px;
background: yellow;
display: none
}
<div class="box" >My box 1</div>
<div class="box" >My box 2</div>
<div class="box" >My box 3</div>
Best way to do it is to have a hidden class, like so:
.hidden { display: none; }
After that, there is a className attribute to every element in JavaScript. You can just manipulate that string to remove occurrences of the hidden class and add another one.
One piece of advice: Use jQuery. Makes it easier to deal with that kind of stuff, you can do it like:
$('#element_id').removeClass('hidden').addClass('something');

What's the equivalent of IE's document.all in DOM?

I basically want to dynamically apply some style to all elements in a page, I know document.all is proprietary to IE, so, what's the equvalent (if any) in DOM? Is there an equivalent to * in css in DOM?
Note: Don't want to use JQuery or any other JS lib for this, just JS, thanks
use document.getElementsByTagName('*')
The World Wide Web Consortium gives a clear specification of this method (Search for getElementsByTagName).
As Scharrels said, you can use document.getElementsByTagName('*'). But you should note that applying styles to every single element on a page is going to impact performance. It would be better to dynamically create a <style> tag and add the styles in there:
function addStyles(styles) {
var styleTag = document.createElement('style');
styleTag.type = 'text/css';
try {
styleTag.appendChild(document.createTextNode(styles));
} catch(e) {
/* Exception thrown in IE */
styleTag.stylesheet.cssText = styles;
}
document.getElementsByTagName('head')[0].appendChild(styleTag);
return styleTag;
}
Usage:
addStyles('* { color: red; }');
Yep, I have just tested documentAll document.getElementsByTagName("*") on Safari, Explorer6, Opera and Firefox and seems to work for all them :)
Applying a style to all elements is not something that you would normally do, so what is it that you are going to use it for?
There are some styles that you can't apply to all elements. A select element for example doesn't support setting borders in all browsers. Setting margin on inline elements can have varying unexpected results...
Some styles are inherited, so if you for example apply a font-size to the body element, that would be inherited by any elements that doesn't already have a specific font-size set.
You can use the cascading in CSS to change the style on a lot of elements. If you for example have this style defined:
.highlight div.info { background: #ffc; }
.highlight strong { color: #f00; }
Setting className="highlight" to the body tag would give every div inside with class="info" a light yellow background and every strong element red text.

Categories